feat(auth): wire permission gating through menu, routes and actions
The store's can()/useCan() helpers existed but were unused. Now: - src/auth/permissions.ts PERM catalog mirrors backend keys - every nav item carries a permission; sidebar filter reuses can() - requirePermission() beforeLoad guard on all child routes (direct URLs redirect home when the session lacks the key) - useCan() hides/disables mutation buttons: moderation actions, retranslate, robot-author edit/pause, category + locale CRUD, and the reserved-SID assign path (admin:sid:override hint) - 403 responses toast 无权限执行此操作; can() unit tests added Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
53
src/auth/permissions.ts
Normal file
53
src/auth/permissions.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { redirect } from '@tanstack/react-router'
|
||||
import { can, useAuthStore } from '@/auth/store'
|
||||
|
||||
/**
|
||||
* Admin permission keys — mirrors the backend catalog
|
||||
* (Modules/{Module}/app/Permissions/{Module}Permissions.php).
|
||||
*/
|
||||
export const PERM = {
|
||||
CATEGORY_READ: 'admin:category:read',
|
||||
CATEGORY_CREATE: 'admin:category:create',
|
||||
CATEGORY_UPDATE: 'admin:category:update',
|
||||
CATEGORY_DELETE: 'admin:category:delete',
|
||||
CATEGORY_APPROVE: 'admin:category:approve',
|
||||
COMMENT_READ: 'admin:comment:read',
|
||||
COMMENT_MODERATE: 'admin:comment:moderate',
|
||||
FILEX_READ: 'admin:filex:read',
|
||||
FILEX_MODERATE: 'admin:filex:moderate',
|
||||
DIMZOU_READ: 'admin:dimzou:read',
|
||||
DIMZOU_RETRANSLATE: 'admin:dimzou:retranslate',
|
||||
EXC_READ: 'admin:exc:read',
|
||||
STUDIO_READ: 'admin:studio:read',
|
||||
STUDIO_MANAGE: 'admin:studio:manage',
|
||||
STUDIO_AGENT_TOKEN_ISSUE: 'admin:studio:agent-token:issue',
|
||||
LOCALE_READ: 'admin:locale:read',
|
||||
LOCALE_CREATE: 'admin:locale:create',
|
||||
LOCALE_UPDATE: 'admin:locale:update',
|
||||
LOCALE_DELETE: 'admin:locale:delete',
|
||||
SID_MANAGE: 'admin:sid:manage',
|
||||
SID_OVERRIDE: 'admin:sid:override',
|
||||
NOTIFICATION_READ: 'admin:notification:read',
|
||||
ROBOT_TOKEN_ISSUE: 'auth:robot-token:issue',
|
||||
// role management — only super-admin holds these
|
||||
ROLE_READ: 'auth:role:read',
|
||||
ROLE_CREATE: 'auth:role:create',
|
||||
ROLE_UPDATE: 'auth:role:update',
|
||||
ROLE_DELETE: 'auth:role:delete',
|
||||
ROLE_ASSIGN: 'auth:role:assign',
|
||||
PERMISSION_READ: 'auth:permission:read',
|
||||
} as const
|
||||
|
||||
export type Permission = (typeof PERM)[keyof typeof PERM]
|
||||
|
||||
/**
|
||||
* Route `beforeLoad` guard. Redirects home when the session is loaded and
|
||||
* lacks the permission; lets the request through while the session is still
|
||||
* empty (the API's 403 is the backstop, and /auth/me refreshes the store).
|
||||
*/
|
||||
export function requirePermission(permission: Permission): void {
|
||||
const { user } = useAuthStore.getState()
|
||||
if (user && !can(permission)) {
|
||||
throw redirect({ to: '/' })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user