227 lines
6.1 KiB
TypeScript
227 lines
6.1 KiB
TypeScript
import { createRouter, createWebHistory, type RouteLocationNormalized } from 'vue-router'
|
|
|
|
import { useAuthStore } from '@/stores/authStore'
|
|
import type { AuthPermissionCode } from '@/types/auth'
|
|
import { resolveAuthenticatedEntryPath, resolveLoginRedirectPath } from '@/utils/authNavigation'
|
|
|
|
type AuthStore = ReturnType<typeof useAuthStore>
|
|
type AppRouteMeta = {
|
|
public?: boolean
|
|
layout?: 'plain' | 'app'
|
|
permission?: AuthPermissionCode
|
|
}
|
|
|
|
export const router = createRouter({
|
|
history: createWebHistory(),
|
|
routes: [
|
|
{
|
|
path: '/',
|
|
name: 'home',
|
|
component: {
|
|
name: 'HomeRedirectView',
|
|
render: () => null,
|
|
},
|
|
},
|
|
{
|
|
path: '/login',
|
|
name: 'login',
|
|
component: () => import('@/views/auth/LoginView.vue'),
|
|
meta: {
|
|
public: true,
|
|
layout: 'plain',
|
|
titleKey: 'auth.loginTitle',
|
|
},
|
|
},
|
|
{
|
|
path: '/unauthorized',
|
|
name: 'unauthorized',
|
|
component: () => import('@/views/auth/UnauthorizedView.vue'),
|
|
meta: {
|
|
titleKey: 'auth.unauthorizedTitle',
|
|
},
|
|
},
|
|
{
|
|
path: '/reservation/workbench',
|
|
redirect: '/reservation/orders',
|
|
},
|
|
{
|
|
path: '/reservation/orders',
|
|
name: 'reservation-order-list',
|
|
component: () => import('@/views/reservation/ReservationOrderListView.vue'),
|
|
meta: {
|
|
titleKey: 'nav.orders',
|
|
permission: 'RESERVATION_ORDER_READ',
|
|
},
|
|
},
|
|
{
|
|
path: '/reservation/tasks',
|
|
name: 'reservation-task-list',
|
|
component: () => import('@/views/reservation/ReservationTaskListView.vue'),
|
|
meta: {
|
|
titleKey: 'nav.taskQueue',
|
|
permission: 'RESERVATION_TASK_READ',
|
|
},
|
|
},
|
|
{
|
|
path: '/reservation/orders/:orderId',
|
|
name: 'reservation-order-detail',
|
|
component: () => import('@/views/reservation/ReservationOrderDetailView.vue'),
|
|
meta: {
|
|
titleKey: 'nav.orderDetail',
|
|
permission: 'RESERVATION_ORDER_READ',
|
|
},
|
|
},
|
|
{
|
|
path: '/reservation/tasks/:taskId',
|
|
name: 'reservation-task-detail',
|
|
component: () => import('@/views/reservation/ReservationTaskDetailView.vue'),
|
|
meta: {
|
|
titleKey: 'nav.taskDetail',
|
|
permission: 'RESERVATION_TASK_READ',
|
|
},
|
|
},
|
|
{
|
|
path: '/reservation/source-messages/:sourceMessageId/conversation',
|
|
name: 'reservation-source-message-conversation',
|
|
component: () => import('@/views/reservation/ReservationSourceMessageConversationView.vue'),
|
|
meta: {
|
|
titleKey: 'nav.sourceMessageConversation',
|
|
permission: 'SOURCE_MESSAGE_ORIGINAL_READ',
|
|
},
|
|
},
|
|
{
|
|
path: '/debug/eml-superagent',
|
|
name: 'debug-eml-superagent',
|
|
component: () => import('@/views/debug/DebugEmlSuperAgentRunView.vue'),
|
|
meta: {
|
|
titleKey: 'debugEml.title',
|
|
permission: 'SYSTEM_DEBUG_EML_RUN',
|
|
},
|
|
},
|
|
{
|
|
path: '/system',
|
|
component: () => import('@/views/system/SystemAdminLayoutView.vue'),
|
|
meta: {
|
|
titleKey: 'nav.systemSettings',
|
|
permission: 'SYSTEM_ADMIN_CONSOLE_ACCESS',
|
|
},
|
|
children: [
|
|
{
|
|
path: 'users',
|
|
name: 'system-users',
|
|
component: () => import('@/views/system/SystemUsersView.vue'),
|
|
meta: {
|
|
titleKey: 'nav.systemUsers',
|
|
permission: 'SYSTEM_USER_MANAGE',
|
|
},
|
|
},
|
|
{
|
|
path: 'roles',
|
|
name: 'system-roles',
|
|
component: () => import('@/views/system/SystemRolesView.vue'),
|
|
meta: {
|
|
titleKey: 'nav.systemRoles',
|
|
permission: 'SYSTEM_ROLE_MANAGE',
|
|
},
|
|
},
|
|
{
|
|
path: 'menus',
|
|
name: 'system-menus',
|
|
component: () => import('@/views/system/SystemMenusView.vue'),
|
|
meta: {
|
|
titleKey: 'nav.systemMenus',
|
|
permission: 'SYSTEM_MENU_MANAGE',
|
|
},
|
|
},
|
|
{
|
|
path: 'hotels',
|
|
name: 'system-hotels',
|
|
component: () => import('@/views/system/SystemHotelsView.vue'),
|
|
meta: {
|
|
titleKey: 'nav.systemHotels',
|
|
permission: 'HOTEL_MANAGE',
|
|
},
|
|
},
|
|
{
|
|
path: 'audits',
|
|
name: 'system-audits',
|
|
component: () => import('@/views/system/SystemAuditsView.vue'),
|
|
meta: {
|
|
titleKey: 'nav.systemAudits',
|
|
permission: 'SYSTEM_ADMIN_CONSOLE_ACCESS',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
path: '/:pathMatch(.*)*',
|
|
name: 'not-found',
|
|
component: () => import('@/views/system/RouteNotFoundView.vue'),
|
|
meta: {
|
|
titleKey: 'notFound.title',
|
|
},
|
|
},
|
|
],
|
|
})
|
|
|
|
router.beforeEach(createAuthGuard())
|
|
|
|
export function createAuthGuard(resolveAuthStore: () => AuthStore = () => useAuthStore()) {
|
|
return async (to: RouteLocationNormalized) => {
|
|
const authStore = resolveAuthStore()
|
|
const meta = to.meta as AppRouteMeta
|
|
|
|
if (!authStore.restoreAttempted && authStore.hasStoredToken()) {
|
|
await authStore.restoreFromSession()
|
|
}
|
|
|
|
if (meta.public) {
|
|
if (to.name === 'login' && authStore.isAuthenticated) {
|
|
return resolveLoginRedirectPath(to.query.redirect, authStore.firstMenuPath)
|
|
}
|
|
return true
|
|
}
|
|
|
|
if (!authStore.isAuthenticated) {
|
|
return {
|
|
path: '/login',
|
|
query: {
|
|
redirect: to.fullPath,
|
|
},
|
|
}
|
|
}
|
|
|
|
if (to.path === '/') {
|
|
return resolveAuthenticatedEntryPath(authStore.firstMenuPath)
|
|
}
|
|
|
|
if (meta.permission && !authStore.hasPermission(meta.permission)) {
|
|
return {
|
|
name: 'unauthorized',
|
|
}
|
|
}
|
|
|
|
if (to.path === '/system') {
|
|
return resolveSystemAdminEntryPath(authStore)
|
|
}
|
|
|
|
return true
|
|
}
|
|
}
|
|
|
|
function resolveSystemAdminEntryPath(authStore: AuthStore): string {
|
|
if (authStore.hasPermission('SYSTEM_USER_MANAGE')) {
|
|
return '/system/users'
|
|
}
|
|
if (authStore.hasPermission('SYSTEM_ROLE_MANAGE')) {
|
|
return '/system/roles'
|
|
}
|
|
if (authStore.hasPermission('SYSTEM_MENU_MANAGE')) {
|
|
return '/system/menus'
|
|
}
|
|
if (authStore.hasPermission('HOTEL_MANAGE')) {
|
|
return '/system/hotels'
|
|
}
|
|
return '/system/audits'
|
|
}
|