Merge branch 'dev/front-methapon' into dev/front

This commit is contained in:
Methapon2001 2023-11-29 16:59:06 +07:00
commit 2dd8b2b92d
No known key found for this signature in database
GPG key ID: 849924FEF46BD132
8 changed files with 72 additions and 172 deletions

View file

@ -1,7 +1,5 @@
<script setup lang="ts"></script>
<template>
<div id="azay-admin-app">
<div>
<router-view v-slot="{ Component }">
<transition>
<component :is="Component" />
@ -9,5 +7,3 @@
</router-view>
</div>
</template>
<style scoped></style>

View file

@ -1,10 +1,8 @@
<script setup lang="ts">
import { getUsername, logout } from '@/services/KeyCloakService'
import { ref } from 'vue'
import KeyCloakService from '@/services/KeyCloakService'
const dropdownOpen = ref<boolean>(false)
const accountName = ref<string>()
accountName.value = KeyCloakService.GetUserName()
const accountName = ref<string>(getUsername())
</script>
<template>
@ -32,16 +30,7 @@ accountName.value = KeyCloakService.GetUserName()
</div>
<q-btn-dropdown stretch flat v-model="dropdownOpen">
<q-list>
<q-item
clickable
v-close-popup
tabindex="0"
@click="
() => {
KeyCloakService.CallLogOut()
}
"
>
<q-item clickable v-close-popup tabindex="0" @click="() => logout()">
<q-item-section avatar>
<q-avatar icon="logout" color="primary" text-color="white" caption>
</q-avatar>
@ -50,7 +39,6 @@ accountName.value = KeyCloakService.GetUserName()
<q-item-label>Logout</q-item-label>
</q-item-section>
</q-item>
<q-separator inset spaced></q-separator>
</q-list>
</q-btn-dropdown>
</template>

View file

@ -5,18 +5,18 @@ import th from 'quasar/lang/th'
import App from './App.vue'
import HttpService from '@/services/HttpService'
import quasarUserOptions from './quasar-user-options'
import router from './router'
import 'quasar/src/css/index.sass'
import { login } from './services/KeyCloakService'
await login()
const app = createApp(App)
const pinia = createPinia()
app.use(router)
app.use((await import('./router')).default)
app.use(pinia)
app.use(Quasar, {
...quasarUserOptions,
plugins: {
@ -28,9 +28,7 @@ app.use(Quasar, {
app.component(
'full-loader',
defineAsyncComponent(() => import('@/components/FullLoader.vue'))
defineAsyncComponent(() => import('@/components/FullLoader.vue')),
)
app.mount('#app')
HttpService.configureAxiosKeycloak()

View file

@ -1,73 +1,52 @@
import { createRouter, createWebHistory } from 'vue-router'
import UserModule from '@/modules/01_user/router'
import AdminModule from '@/modules/02_admin/router'
import KeyCloakService from '@/services/KeyCloakService'
import { getRole, getToken, login } from '@/services/KeyCloakService'
const history = createWebHistory(import.meta.env.BASE_URL)
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
history,
routes: [
{
path: '/',
name: 'UserModule',
component: () => import('@/views/MainLayout.vue'),
beforeEnter: (_to, _from, next) => {
const token = KeyCloakService.GetAccesToken()
if (token) {
next()
} else {
KeyCloakService.CallLogin(() => {
const tokenAfterLogin = KeyCloakService.GetAccesToken()
const roles = KeyCloakService.GetUserRoles()
beforeEnter: async (_to, _from, next) => {
const token = await getToken()
if (
tokenAfterLogin &&
(roles.includes('user') || roles.includes('admin'))
) {
next()
} else {
console.error('ไม่สามารถดึง Token หลังจากล็อกอินได้')
next('/')
}
})
}
if (token) return next()
await login(async () => {
if (await getToken()) return next()
return next('/')
})
},
children: [...UserModule],
meta: {
statusAccount: false,
},
meta: { statusAccount: false },
},
{
path: '/admin',
name: 'AdminModule',
component: () => import('@/views/MainLayout.vue'),
beforeEnter: (_to, _from, next) => {
const token = KeyCloakService.GetAccesToken()
if (token) {
next()
} else {
KeyCloakService.CallLogin(() => {
const tokenAfterLogin = KeyCloakService.GetAccesToken()
const roles = KeyCloakService.GetUserRoles()
console.log(roles)
beforeEnter: async (_to, _from, next) => {
const token = await getToken()
if (tokenAfterLogin && roles.includes('admin')) {
next()
} else {
console.error('ไม่สามารถดึง Token หลังจากล็อกอินได้')
next('/')
}
})
}
},
meta: {
statusAccount: true,
if (token) return next()
await login(async () => {
const token = await getToken()
const roles = getRole()
if (token && roles.includes('admin')) {
return next()
}
return next('/')
})
},
meta: { statusAccount: true },
children: [...AdminModule],
},
/**
* 404 Not Found
* ref: https://router.vuejs.org/guide/essentials/dynamic-matching.html#catch-all-404-not-found-route
*/
{
path: '/:pathMatch(.*)*',
name: 'NotFound',

View file

@ -1,36 +1,11 @@
import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios'
import axios from 'axios'
import KeyCloakService from '@/services/KeyCloakService'
import { getToken } from './KeyCloakService'
const HttpMethods = {
GET: 'GET',
POST: 'POST',
DELETE: 'DELETE',
}
const instance = axios.create()
const _axios = axios.create()
const cb = (config: InternalAxiosRequestConfig) => {
config.headers.Authorization = `Bearer ${KeyCloakService.GetAccesToken()}`
instance.interceptors.request.use(async (config) => {
config.headers.Authorization = `Bearer ${await getToken()}`
return config
}
})
const configureAxiosKeycloak = (): void => {
_axios.interceptors.request.use(
(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig => {
if (KeyCloakService.IsLoggedIn()) {
KeyCloakService.UpdateToken(cb(config))
}
return config
}
)
}
const getAxiosClient = (): AxiosInstance => _axios
const HttpService = {
HttpMethods,
configureAxiosKeycloak,
getAxiosClient,
}
export default HttpService
export default instance

View file

@ -1,77 +1,42 @@
import Keycloak from 'keycloak-js'
const keycloakInstance = new Keycloak()
const keycloak = new Keycloak()
interface CallbackOneParam<T1 = void, T2 = void> {
(param1: T1): T2
}
/**
* Initializes Keycloak instance and calls the provided callback function if successfully authenticated.
*
* @param onAuthenticatedCallback
*/
const Login = (onAuthenticatedCallback: CallbackOneParam): void => {
keycloakInstance
.init({ onLoad: 'login-required' })
.then(function (authenticated) {
authenticated ? onAuthenticatedCallback() : alert('non authenticated')
})
.catch((e) => {
console.dir(e)
console.log(`keycloak init exception: ${e}`)
export async function login(cb?: (...args: any[]) => void) {
const auth = await keycloak
.init({
onLoad: 'login-required',
responseMode: 'query',
checkLoginIframe: false,
})
.catch((e) => console.dir(e))
if (auth && cb) cb()
}
const UserName = (): string | undefined =>
keycloakInstance?.tokenParsed?.preferred_username
export async function logout() {
await keycloak.logout()
}
const Token = (): string | undefined => keycloakInstance?.token
const IdToken = (): string | undefined => keycloakInstance?.idToken
export async function getToken() {
await keycloak.updateToken(60).catch(() => login())
return keycloak.token
}
const LogOut = () => keycloakInstance.logout()
export function getUsername(): string {
return keycloak.tokenParsed?.preferred_username
}
/*
const UserRoles = (): string[] | undefined => {
if (keycloakInstance.resourceAccess === undefined) return undefined;
if (keycloakInstance.resourceAccess["express-client"] === undefined) return undefined;
export function getRole(): string[] {
const decoded = keycloak.tokenParsed
return keycloakInstance.resourceAccess["express-client"].roles;
};
*/
const UserRoles = () => {
const decoded = DecodeToken()
if (decoded && decoded.resource_access) {
return decoded.resource_access[decoded.azp ?? ''].roles
if (decoded && decoded.resource_access && decoded.azp) {
return decoded.resource_access[decoded.azp].roles
}
return []
}
const updateToken = (successCallback: any) =>
keycloakInstance.updateToken(5).then(successCallback).catch(doLogin)
const doLogin = keycloakInstance.login
const isLoggedIn = () => !!keycloakInstance.token
const DecodeToken = () => {
return keycloakInstance.tokenParsed
export function isLoggedIn() {
return !!keycloak.token
}
const DecodeIdToken = () => {
return keycloakInstance.idTokenParsed
}
const KeycloakService = {
CallLogin: Login,
GetUserName: UserName,
GetAccesToken: Token,
GetIdToken: IdToken,
CallLogOut: LogOut,
GetUserRoles: UserRoles,
UpdateToken: updateToken,
IsLoggedIn: isLoggedIn,
GetDecodeToken: DecodeToken,
GetDecodeIdToken: DecodeIdToken,
}
export default KeycloakService

View file

@ -1,9 +1,8 @@
import { ref } from 'vue'
import { defineStore } from 'pinia'
import { useLoader } from '@/stores/loader'
import HttpService from '@/services/HttpService'
import axiosClient from '@/services/HttpService'
const axiosClient = HttpService.getAxiosClient()
const apiEndpoint: string = import.meta.env.VITE_API_ENDPOINT
export interface EhrFolder {

View file

@ -29,9 +29,9 @@ const { loader } = storeToRefs(loaderStore)
</q-header>
<q-page-container>
<QPage>
<q-page>
<router-view :key="$route.fullPath" />
</QPage>
</q-page>
</q-page-container>
<full-loader :visibility="loader" />
</q-layout>