fix(auth): 完善权限控制与强制改密流程

This commit is contained in:
xy
2026-09-17 16:33:09 +08:00
parent 81922d774f
commit 61b4b19f55
22 changed files with 618 additions and 59 deletions
+65 -17
View File
@@ -1,6 +1,8 @@
import { createRouter, createWebHistory } from 'vue-router'
import ClinicalLayout from '@/layouts/ClinicalLayout.vue'
import ChangePasswordView from '@/views/auth/ChangePasswordView.vue'
import ForbiddenView from '@/views/auth/ForbiddenView.vue'
import LoginView from '@/views/auth/LoginView.vue'
import DocumentPermissionsView from '@/views/management/document-permissions/index.vue'
import DocumentsView from '@/views/management/documents/index.vue'
@@ -11,6 +13,23 @@ import ConsentTasksView from '@/views/workbench/signing/index.vue'
import DashboardView from '@/views/workbench/home/index.vue'
import { useLoginStore } from '@/stores/login'
import { readStoredAuthSession } from '@/utils/auth-storage'
import { mockFlags } from '@/utils/mock-flags'
const authorizedLandingRoutes = [
{ name: 'workbench-home', permission: 'sign:task:query' },
{ name: 'workbench-signing', permission: 'sign:task:query' },
{ name: 'management-documents', permission: 'sign:template:query' },
{ name: 'management-reports', permission: 'report:signing:query' },
{ name: 'management-users', permission: 'system:user:query' },
{ name: 'management-document-permissions', permission: 'sign:template:permission:query' },
] as const
function firstAuthorizedRoute(loginStore: ReturnType<typeof useLoginStore>) {
return (
authorizedLandingRoutes.find((route) => loginStore.hasPermission(route.permission))?.name ??
'forbidden'
)
}
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@@ -21,6 +40,18 @@ const router = createRouter({
component: LoginView,
meta: { title: '登录' },
},
{
path: '/change-password',
name: 'change-password',
component: ChangePasswordView,
meta: { title: '修改密码', requiresAuth: true },
},
{
path: '/forbidden',
name: 'forbidden',
component: ForbiddenView,
meta: { title: '无访问权限', requiresAuth: true },
},
{
path: '/',
name: 'clinical',
@@ -36,13 +67,13 @@ const router = createRouter({
path: 'home',
name: 'workbench-home',
component: DashboardView,
meta: { title: '首页', group: '工作台' },
meta: { title: '首页', group: '工作台', permission: 'sign:task:query' },
},
{
path: 'signing',
name: 'workbench-signing',
component: ConsentTasksView,
meta: { title: '签署工作台', group: '工作台' },
meta: { title: '签署工作台', group: '工作台', permission: 'sign:task:query' },
},
],
},
@@ -54,13 +85,13 @@ const router = createRouter({
path: 'documents',
name: 'management-documents',
component: DocumentsView,
meta: { title: '文档库管理', group: '管理' },
meta: { title: '文档库管理', group: '管理', permission: 'sign:template:query' },
},
{
path: 'reports',
name: 'management-reports',
component: ReportsView,
meta: { title: '报表分析', group: '管理' },
meta: { title: '报表分析', group: '管理', permission: 'report:signing:query' },
},
{
path: 'users',
@@ -101,7 +132,7 @@ const router = createRouter({
],
})
router.beforeEach((to) => {
router.beforeEach(async (to) => {
const loginStore = useLoginStore()
if (to.name === 'login' && loginStore.isLoggedIn) {
@@ -110,7 +141,11 @@ router.beforeEach((to) => {
return true
}
return { name: 'workbench-home' }
return {
name: loginStore.user?.passwordChangeRequired
? 'change-password'
: firstAuthorizedRoute(loginStore),
}
}
if (to.meta.requiresAuth && !loginStore.isLoggedIn) {
@@ -121,21 +156,34 @@ router.beforeEach((to) => {
}
if (to.meta.requiresAuth) {
return loginStore
.ensureCurrentUser()
.then(() => {
const requiredPermission = to.meta.permission as string | string[] | undefined
try {
const user = await loginStore.ensureCurrentUser()
if (requiredPermission && !loginStore.hasPermission(requiredPermission)) {
return { name: 'workbench-home' }
}
if (user?.passwordChangeRequired && to.name !== 'change-password') {
return { name: 'change-password' }
}
return true
})
.catch(() => ({
if (!user?.passwordChangeRequired && to.name === 'change-password') {
return { name: firstAuthorizedRoute(loginStore) }
}
if (to.name === 'management-settings' && !mockFlags.settings) {
return { name: 'forbidden' }
}
const requiredPermission = to.meta.permission as string | string[] | undefined
if (requiredPermission && !loginStore.hasPermission(requiredPermission)) {
return { name: firstAuthorizedRoute(loginStore) }
}
return true
} catch {
loginStore.clearSession()
return {
name: 'login',
query: { redirect: to.fullPath },
}))
}
}
}
return true