keycloak fix
This commit is contained in:
+33
-33
@@ -1,52 +1,52 @@
|
||||
// project imports
|
||||
import mock from './mockAdapter';
|
||||
|
||||
import type { notificationType, profileType, languageType, appsLinkType,searchType } from '@/types/HeaderTypes'
|
||||
import type { notificationType, profileType, languageType, appsLinkType, searchType } from '@/types/HeaderTypes'
|
||||
//
|
||||
// Notification
|
||||
//
|
||||
const notifications:notificationType[] = [
|
||||
const notifications: notificationType[] = [
|
||||
{
|
||||
avatar: 'widget-3-line-duotone',
|
||||
color:'error',
|
||||
color: 'error',
|
||||
title: 'Launch Admin',
|
||||
subtitle: 'Just see the my new admin!',
|
||||
time:'9:30 AM'
|
||||
time: '9:30 AM'
|
||||
},
|
||||
{
|
||||
avatar: 'calendar-line-duotone',
|
||||
color:'primary',
|
||||
color: 'primary',
|
||||
title: 'Event Today',
|
||||
subtitle: 'Just a reminder that you have event',
|
||||
time:'9:15 AM'
|
||||
time: '9:15 AM'
|
||||
},
|
||||
{
|
||||
avatar: 'settings-line-duotone',
|
||||
color:'secondary',
|
||||
color: 'secondary',
|
||||
title: 'Settings',
|
||||
subtitle: 'You can customize this template as you want',
|
||||
time:'4:36 PM'
|
||||
time: '4:36 PM'
|
||||
},
|
||||
{
|
||||
avatar: 'widget-4-line-duotone',
|
||||
color:'warning',
|
||||
color: 'warning',
|
||||
title: 'Launch Admin',
|
||||
subtitle: 'Just see the my new admin!',
|
||||
time:'9:30 AM'
|
||||
time: '9:30 AM'
|
||||
},
|
||||
{
|
||||
avatar: 'calendar-line-duotone',
|
||||
color:'primary',
|
||||
color: 'primary',
|
||||
title: 'Event Today',
|
||||
subtitle: 'Just a reminder that you have event',
|
||||
time:'9:15 AM'
|
||||
time: '9:15 AM'
|
||||
},
|
||||
{
|
||||
avatar: 'settings-line-duotone',
|
||||
color:'secondary',
|
||||
color: 'secondary',
|
||||
title: 'Settings',
|
||||
subtitle: 'You can customize this template as you want',
|
||||
time:'4:36 PM'
|
||||
time: '4:36 PM'
|
||||
},
|
||||
];
|
||||
|
||||
@@ -57,29 +57,29 @@ const profileDD: profileType[] = [
|
||||
{
|
||||
title: 'My Profile',
|
||||
href: '/apps/user/profile',
|
||||
badge:false
|
||||
badge: false
|
||||
},
|
||||
{
|
||||
title: 'My Subscription',
|
||||
href: '/pages/pricing',
|
||||
badge:false
|
||||
badge: false
|
||||
},
|
||||
{
|
||||
title: 'My Notes',
|
||||
href: '/apps/notes',
|
||||
badge:true
|
||||
badge: true
|
||||
},
|
||||
{
|
||||
title: 'Account Settings',
|
||||
href: '/pages/account-settings',
|
||||
badge:false
|
||||
badge: false
|
||||
},
|
||||
{
|
||||
title: 'Sign Out',
|
||||
href: '/auth/login2',
|
||||
badge:false
|
||||
},
|
||||
|
||||
// {
|
||||
// title: 'Sign Out',
|
||||
// href: '/auth/login2',
|
||||
// badge:false
|
||||
// },
|
||||
|
||||
];
|
||||
|
||||
//
|
||||
@@ -102,57 +102,57 @@ const languageDD: languageType[] = [
|
||||
const appsLink: appsLinkType[] = [
|
||||
{
|
||||
avatar: 'chat-line-bold-duotone',
|
||||
color:'primary',
|
||||
color: 'primary',
|
||||
title: 'Chat Application',
|
||||
subtext: 'New messages arrived',
|
||||
href: '/apps/chats'
|
||||
},
|
||||
{
|
||||
avatar: 'user-bold-duotone',
|
||||
color:'success',
|
||||
color: 'success',
|
||||
title: 'User Profile App',
|
||||
subtext: 'Get profile details',
|
||||
href: '/apps/user/profile'
|
||||
},
|
||||
{
|
||||
avatar: 'bill-list-bold-duotone',
|
||||
color:'secondary',
|
||||
color: 'secondary',
|
||||
title: 'eCommerce App',
|
||||
subtext: 'learn more information',
|
||||
href: '/ecommerce/products'
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
avatar: 'calendar-minimalistic-bold-duotone',
|
||||
color:'primary',
|
||||
color: 'primary',
|
||||
title: 'Calendar App',
|
||||
subtext: 'Get dates',
|
||||
href: '/apps/calendar'
|
||||
},
|
||||
{
|
||||
avatar: 'phone-calling-rounded-bold-duotone',
|
||||
color:'warning',
|
||||
color: 'warning',
|
||||
title: 'Contact Application',
|
||||
subtext: '2 Unsaved Contacts',
|
||||
href: '/apps/contacts'
|
||||
},
|
||||
{
|
||||
avatar: 'settings-bold-duotone',
|
||||
color:'info',
|
||||
color: 'info',
|
||||
title: 'Account Setting App',
|
||||
subtext: 'Account settings',
|
||||
href: '/pages/account-settings'
|
||||
},
|
||||
{
|
||||
avatar: 'checklist-minimalistic-bold',
|
||||
color:'error',
|
||||
color: 'error',
|
||||
title: 'Kanban App',
|
||||
subtext: 'Get new Task',
|
||||
href: '/apps/kanban'
|
||||
},
|
||||
{
|
||||
avatar: 'notes-bold-duotone',
|
||||
color:'warning',
|
||||
color: 'warning',
|
||||
title: 'Notes Application',
|
||||
subtext: 'To-do and Daily tasks',
|
||||
href: '/apps/notes'
|
||||
|
||||
@@ -59,7 +59,9 @@ const login = () => {
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
<v-btn size="large" color="primary" :disabled="valid" block flat @click="login">Sign In</v-btn>
|
||||
<!-- <v-btn size="large" color="primary" :disabled="valid" block flat @click="login">Sign In</v-btn> -->
|
||||
<v-btn v-for="provider in providers" :key="provider" @click="signIn(provider.id)" color="primary" size="large"
|
||||
block flat>Sign in with {{ provider.name }}</v-btn>
|
||||
<!-- <div class="mt-2">
|
||||
<v-alert color="error"></v-alert>
|
||||
</div> -->
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { signOut } from "next-auth/react";
|
||||
import { profileDD } from "@/_mockApis/headerData";
|
||||
|
||||
const { data, status, getCsrfToken, getProviders } = useAuth()
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const logout = async () => {
|
||||
await signOut()
|
||||
const LogOutKeycloakURL = `${runtimeConfig.public.keycloakUrl}/realms/${runtimeConfig.public.keycloakRealm}/protocol/openid-connect`
|
||||
const logOutURL = `${LogOutKeycloakURL}/logout?client_id=${runtimeConfig.public.keycloakClient}&post_logout_redirect_uri=${encodeURIComponent(window.location.origin)}/auth/login`;
|
||||
window.location.href = logOutURL
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -8,19 +18,9 @@ import { profileDD } from "@/_mockApis/headerData";
|
||||
<!-- ---------------------------------------------- -->
|
||||
<v-menu open-on-hover open-on-click>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn
|
||||
variant="text"
|
||||
class="custom-hover-primary"
|
||||
color="primary"
|
||||
v-bind="props"
|
||||
icon
|
||||
>
|
||||
<v-btn variant="text" class="custom-hover-primary" color="primary" v-bind="props" icon>
|
||||
<v-avatar size="35">
|
||||
<img
|
||||
src="@/assets/images/profile/user-1.jpg"
|
||||
width="35"
|
||||
alt="Julia"
|
||||
/>
|
||||
<img src="@/assets/images/profile/user-1.jpg" width="35" alt="Julia" />
|
||||
</v-avatar>
|
||||
</v-btn>
|
||||
</template>
|
||||
@@ -34,30 +34,23 @@ import { profileDD } from "@/_mockApis/headerData";
|
||||
<h6 class="text-subtitle-1">
|
||||
David McMichael <span class="text-success text-caption">Pro</span>
|
||||
</h6>
|
||||
<span class="text-subtitle-1 textSecondary"
|
||||
>david@wrappixel.com</span
|
||||
>
|
||||
<span class="text-subtitle-1 textSecondary">david@wrappixel.com</span>
|
||||
</div>
|
||||
</div>
|
||||
<v-divider></v-divider>
|
||||
<perfect-scrollbar
|
||||
style="height: calc(100vh - 240px); max-height: 240px"
|
||||
>
|
||||
<perfect-scrollbar style="height: calc(100vh - 240px); max-height: 240px">
|
||||
<v-list class="py-0 theme-list mt-3" lines="one">
|
||||
<v-list-item
|
||||
v-for="item in profileDD"
|
||||
:key="item.title"
|
||||
class="py-0 px-2 rounded-md custom-text-primary"
|
||||
color="primary"
|
||||
:to="item.href"
|
||||
>
|
||||
<v-list-item v-for="item in profileDD" :key="item.title" class="py-0 px-2 rounded-md custom-text-primary"
|
||||
color="primary" :to="item.href">
|
||||
<div class="d-flex gap-3 align-center">
|
||||
<p class="text-subtitle-1 heading custom-title">
|
||||
{{ item.title }}
|
||||
</p>
|
||||
<v-chip size="small" color="error" v-if="item.badge">4</v-chip>
|
||||
</div>
|
||||
|
||||
</v-list-item>
|
||||
<v-btn @click="logout" color="primary" variant="outlined" block>Logout</v-btn>
|
||||
</v-list>
|
||||
</perfect-scrollbar>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export const useUseGetUserLoginComposables = (data: any) => {
|
||||
console.log('data useUseGetUserLoginComposables', data)
|
||||
return data;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
const userInfoStores = useUserInfoStore()
|
||||
const { getUserInfoStore } = storeToRefs(useUserInfoStore())
|
||||
const { data } = useAuth()
|
||||
export default defineNuxtRouteMiddleware((to, from) => {
|
||||
console.log(data.value)
|
||||
if (data.value === null || !data.value) {
|
||||
navigateTo('/sample-page')
|
||||
} else {
|
||||
navigateTo('/sambelPage_copy')
|
||||
console.log('berhasil login')
|
||||
}
|
||||
})
|
||||
+10
-10
@@ -103,16 +103,16 @@ export default defineNuxtConfig({
|
||||
keycloakRealm: process.env.KEYCLOAK_REALM,
|
||||
}
|
||||
},
|
||||
// auth: {
|
||||
// isEnabled: true,
|
||||
// baseURL: process.env.AUTH_ORIGIN,
|
||||
// provider: {
|
||||
// type: "authjs",
|
||||
// },
|
||||
// globalAppMiddleware: {
|
||||
// isEnabled: true,
|
||||
// },
|
||||
// },
|
||||
auth: {
|
||||
isEnabled: true,
|
||||
baseURL: process.env.AUTH_ORIGIN,
|
||||
provider: {
|
||||
type: "authjs",
|
||||
},
|
||||
globalAppMiddleware: {
|
||||
isEnabled: true,
|
||||
},
|
||||
},
|
||||
devServerHandlers: [],
|
||||
|
||||
hooks: {},
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: ['auth']
|
||||
})
|
||||
import { ref } from "vue";
|
||||
import UiParentCard from "@/components/shared/UiParentCard.vue";
|
||||
import { useAuth, useUserInfoStore } from "#imports";
|
||||
import { useUseGetUserLoginComposables } from "~/composables/useGetUserLoginComposables"
|
||||
|
||||
const { setUserInfoStore } = useUserInfoStore();
|
||||
const { getUserInfoStore } = storeToRefs(useUserInfoStore());
|
||||
const { data, status, getCsrfToken, getProviders, signOut, getSession } = useAuth()
|
||||
const tokens = ref('')
|
||||
onMounted(async () => {
|
||||
// $fetch(`/api/auth/protected`).then(res => console.log('ini responnya',res))
|
||||
const headers = useRequestHeaders(['cookie']) as HeadersInit
|
||||
const { data: token } = await useFetch('/api/token', { headers })
|
||||
tokens.value = token.value
|
||||
// userAuthenticate(token.value)
|
||||
setUserInfoStore(token.value)
|
||||
})
|
||||
const getUserFromComposable = () => {
|
||||
const a = useUseGetUserLoginComposables(getUserInfoStore.value)
|
||||
console.log('ini a', a)
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<v-row>
|
||||
<v-col cols="12" md="12">
|
||||
<v-card elevation="10">
|
||||
<v-card-item>
|
||||
<!-- <pre><span>Providers:</span> {{ getUserInfoStore }}</pre> -->
|
||||
<h5 class="text-h5 mb-3">Sample Page</h5>
|
||||
<p class="text-body-1">This is a sample page</p>
|
||||
<div class="mt-4">
|
||||
<!-- <v-btn @click="getUserFromComposable" color="primary" variant="outlined" block>useComposables</v-btn> -->
|
||||
|
||||
<!-- <pre><span>Providers:</span> {{ tokens }}</pre> -->
|
||||
</div>
|
||||
</v-card-item>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
+29
-1
@@ -1,14 +1,42 @@
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: ['auth']
|
||||
})
|
||||
import { ref } from "vue";
|
||||
import UiParentCard from "@/components/shared/UiParentCard.vue";
|
||||
import { useAuth, useUserInfoStore } from "#imports";
|
||||
import { useUseGetUserLoginComposables } from "~/composables/useGetUserLoginComposables"
|
||||
|
||||
const { setUserInfoStore } = useUserInfoStore();
|
||||
const { getUserInfoStore } = storeToRefs(useUserInfoStore());
|
||||
const { data, status, getCsrfToken, getProviders, signOut, getSession } = useAuth()
|
||||
const tokens = ref('')
|
||||
onMounted(async () => {
|
||||
// $fetch(`/api/auth/protected`).then(res => console.log('ini responnya',res))
|
||||
const headers = useRequestHeaders(['cookie']) as HeadersInit
|
||||
const { data: token } = await useFetch('/api/token', { headers })
|
||||
tokens.value = token.value
|
||||
// userAuthenticate(token.value)
|
||||
setUserInfoStore(token.value)
|
||||
})
|
||||
const getUserFromComposable = () => {
|
||||
const a = useUseGetUserLoginComposables(getUserInfoStore.value)
|
||||
console.log('ini a', a)
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<v-row>
|
||||
<v-col cols="12" md="12">
|
||||
<v-card elevation="10">
|
||||
<v-card-item>
|
||||
<h5 class="text-h5 mb-3">Sample Page</h5>
|
||||
<pre><span>Providers:</span> {{ getUserInfoStore }}</pre>
|
||||
<h5 class="text-h5 mb-3">Sample Page</h5>
|
||||
<p class="text-body-1">This is a sample page</p>
|
||||
<div class="mt-4">
|
||||
<v-btn @click="getUserFromComposable" color="primary" variant="outlined" block>useComposables</v-btn>
|
||||
|
||||
<!-- <pre><span>Providers:</span> {{ tokens }}</pre> -->
|
||||
</div>
|
||||
</v-card-item>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
/*-For Set Blank Layout-*/
|
||||
// definePageMeta({
|
||||
// layout: "blank",
|
||||
// });
|
||||
definePageMeta({
|
||||
layout: "blank",
|
||||
layout: "auth",
|
||||
auth: {
|
||||
unauthenticatedOnly: true,
|
||||
navigateAuthenticatedTo: '/sample-page',
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { getServerSession, getToken } from '#auth'
|
||||
|
||||
export default eventHandler(async (event) => {
|
||||
const session = await getServerSession(event)
|
||||
if (!session) {
|
||||
return { status: 'unauthenticated!' }
|
||||
}
|
||||
const token = await getToken({ event })
|
||||
return token || { status: 'no token present' }
|
||||
})
|
||||
@@ -0,0 +1,38 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { timestampToDate } from "~/utils/helper";
|
||||
|
||||
export const useUserInfoStore = defineStore("userInfoStore", () => {
|
||||
const getUserInfoStore = ref<any>([])
|
||||
const setUserInfoStore = (data: any) => {
|
||||
const userInfo: any[] =
|
||||
{
|
||||
user_name: data?.access_token_payload?.preferred_username,
|
||||
type_user: data?.access_token_payload?.type_user,
|
||||
role_access: data?.access_token_payload?.resource_access[data?.access_token_payload.azp],
|
||||
userInfo: [
|
||||
{
|
||||
id: data?.user?.id,
|
||||
fullname: data?.access_token_payload?.name,
|
||||
given_name: data?.access_token_payload?.given_name || '-',
|
||||
family_name: data?.access_token_payload?.family_name || '-',
|
||||
email: data?.access_token_payload?.email || '- ',
|
||||
group: data?.access_token_payload?.group,
|
||||
}
|
||||
],
|
||||
expires_in: [
|
||||
{
|
||||
timestamps: data?.expires_at,
|
||||
date: timestampToDate(data?.expires_at, 'id-ID'),
|
||||
}
|
||||
],
|
||||
};
|
||||
// console.log(data)
|
||||
getUserInfoStore.value = userInfo;
|
||||
}
|
||||
|
||||
const getMenuAkses = ref<any>([])
|
||||
// const
|
||||
|
||||
|
||||
return { setUserInfoStore, getUserInfoStore }
|
||||
})
|
||||
@@ -0,0 +1,26 @@
|
||||
export function capitalizeEachWord(text: string) {
|
||||
// const lowercase = text.toLowerCase();
|
||||
// return lowercase.charAt(0).toUpperCase() + lowercase.slice(1);
|
||||
return text
|
||||
.toLowerCase()
|
||||
.split(' ')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
export function timestampToDate(timestamp: number, locale: string, options = {}) {
|
||||
const date = new Date(timestamp * 1000);
|
||||
// locale forma --> `id-ID`
|
||||
return date.toLocaleString(locale, {
|
||||
// timeZone: options.timeZone,
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
timeZoneName: 'short',
|
||||
...options
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user