Files
opsxsql/数据审核平台菜单优化/app/src/hooks/useAuth.tsx
T
loganandClaude Opus 4.7 439155c92e Initial commit: SQL audit platform v0.1.0
FastAPI backend with auth, user, instance, ticket, query, dashboard APIs.
React + TypeScript frontend with mock data UI (10 pages).
SQLite + async SQLAlchemy, JWT auth, role-based access control.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:11:57 +08:00

158 lines
4.7 KiB
TypeScript

import { createContext, useContext, useState, useCallback, useMemo } from 'react';
import { menuItems, currentUser as defaultUser } from '@/lib/mock';
export type UserRole = 'admin' | 'dba' | 'developer' | 'guest';
export interface AuthUser {
id: number;
username: string;
email: string;
role: UserRole;
roleName: string;
avatar: string;
}
interface AuthContextType {
user: AuthUser;
isLoggedIn: boolean;
login: (username: string, password: string) => Promise<boolean>;
logout: () => void;
switchRole: (role: UserRole) => void;
hasPermission: (menuId: string) => boolean;
visibleMenuItems: typeof menuItems;
isAdmin: boolean;
isDBA: boolean;
isDeveloper: boolean;
isGuest: boolean;
}
const roleNameMap: Record<UserRole, string> = {
admin: '超级管理员',
dba: '数据库管理员',
developer: '开发人员',
guest: '访客',
};
const routePermissionMap: Record<string, UserRole[]> = {
dashboard: ['admin', 'dba', 'developer', 'guest'],
mysql: ['admin', 'dba'],
postgres: ['admin', 'dba'],
redis: ['admin', 'dba'],
mongo: ['admin', 'dba'],
clickhouse: ['admin', 'dba'],
tickets: ['admin', 'dba', 'developer'],
queries: ['admin', 'dba', 'developer', 'guest'],
roles: ['admin'],
users: ['admin'],
'data-permission': ['admin', 'dba'],
'audit-rules': ['admin', 'dba'],
workflow: ['admin', 'dba'],
'auto-task': ['admin'],
announcement: ['admin'],
'config-platform': ['admin'],
notifications: ['admin'],
};
// 页面内操作权限
export const actionPermissionMap: Record<string, UserRole[]> = {
'ticket.create': ['admin', 'dba', 'developer'],
'ticket.approve': ['admin', 'dba'],
'ticket.execute': ['admin', 'dba'],
'ticket.rollback': ['admin', 'dba'],
'ticket.delete': ['admin'],
'query.create': ['admin', 'dba', 'developer'],
'query.export': ['admin', 'dba', 'developer'],
'instance.add': ['admin'],
'instance.edit': ['admin', 'dba'],
'instance.delete': ['admin'],
'user.manage': ['admin'],
'role.manage': ['admin'],
'rule.manage': ['admin', 'dba'],
'workflow.manage': ['admin', 'dba'],
'config.manage': ['admin'],
'announcement.manage': ['admin'],
'auto-task.manage': ['admin'],
};
const AuthContext = createContext<AuthContextType | null>(null);
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<AuthUser>({
id: defaultUser.id,
username: defaultUser.username,
email: defaultUser.email,
role: defaultUser.role,
roleName: defaultUser.roleName,
avatar: defaultUser.avatar,
});
const [isLoggedIn, setIsLoggedIn] = useState(true);
const login = useCallback(async (username: string, _password: string): Promise<boolean> => {
await new Promise(r => setTimeout(r, 800));
setIsLoggedIn(true);
setUser({
id: 1,
username,
email: `${username}@company.com`,
role: username === 'admin' ? 'admin' : username === 'dba' ? 'dba' : 'developer',
roleName: username === 'admin' ? '超级管理员' : username === 'dba' ? '数据库管理员' : '开发人员',
avatar: username.charAt(0).toUpperCase(),
});
return true;
}, []);
const logout = useCallback(() => {
setIsLoggedIn(false);
}, []);
const switchRole = useCallback((role: UserRole) => {
setUser(prev => ({
...prev,
role,
roleName: roleNameMap[role],
username: role === 'admin' ? 'admin' : role === 'dba' ? 'zhangsan' : role === 'developer' ? 'wangwu' : 'visitor',
email: `${role}@company.com`,
avatar: role.charAt(0).toUpperCase(),
}));
}, []);
const hasPermission = useCallback((menuId: string): boolean => {
const allowedRoles = routePermissionMap[menuId];
if (!allowedRoles) return false;
return allowedRoles.includes(user.role);
}, [user.role]);
const visibleMenuItems = useMemo(() => {
return menuItems.filter(item => item.roles.includes(user.role));
}, [user.role]);
const value = useMemo(() => ({
user,
isLoggedIn,
login,
logout,
switchRole,
hasPermission,
visibleMenuItems,
isAdmin: user.role === 'admin',
isDBA: user.role === 'dba',
isDeveloper: user.role === 'developer',
isGuest: user.role === 'guest',
}), [user, isLoggedIn, login, logout, switchRole, hasPermission, visibleMenuItems]);
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
export function useAuth(): AuthContextType {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
return ctx;
}
export function useActionPermission(action: string): boolean {
const { user } = useAuth();
const allowedRoles = actionPermissionMap[action];
if (!allowedRoles) return false;
return allowedRoles.includes(user.role);
}