Merge branch 'dev/front-methapon' into dev/front
This commit is contained in:
commit
2dd8b2b92d
8 changed files with 72 additions and 172 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue