iconsulting/packages/admin-client/src/shared/hooks/useAuth.ts

106 lines
2.5 KiB
TypeScript

import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import api from '../utils/api';
interface AdminInfo {
id: string;
username: string;
name: string;
role: string;
permissions: string[];
}
interface AuthState {
admin: AdminInfo | null;
token: string | null;
isAuthenticated: boolean;
login: (username: string, password: string) => Promise<void>;
logout: () => void;
checkAuth: () => Promise<boolean>;
hasPermission: (permission: string) => boolean;
}
export const useAuth = create<AuthState>()(
persist(
(set, get) => ({
admin: null,
token: null,
isAuthenticated: false,
login: async (username: string, password: string) => {
const response = await api.post('/admin/login', { username, password });
const { data } = response.data;
localStorage.setItem('admin_token', data.token);
set({
admin: data.admin,
token: data.token,
isAuthenticated: true,
});
},
logout: () => {
localStorage.removeItem('admin_token');
set({
admin: null,
token: null,
isAuthenticated: false,
});
},
checkAuth: async () => {
const token = localStorage.getItem('admin_token');
if (!token) {
set({ isAuthenticated: false, admin: null, token: null });
return false;
}
try {
const response = await api.get('/admin/verify');
if (response.data.success) {
set({
admin: response.data.data,
token,
isAuthenticated: true,
});
return true;
}
} catch {
localStorage.removeItem('admin_token');
}
set({ isAuthenticated: false, admin: null, token: null });
return false;
},
hasPermission: (permission: string) => {
const { admin } = get();
if (!admin) return false;
const permissions = admin.permissions || [];
// 超管拥有所有权限
if (permissions.includes('*')) return true;
// 完全匹配
if (permissions.includes(permission)) return true;
// 通配符匹配
const [resource] = permission.split(':');
if (permissions.includes(`${resource}:*`)) return true;
return false;
},
}),
{
name: 'auth-storage',
partialize: (state) => ({
admin: state.admin,
token: state.token,
isAuthenticated: state.isAuthenticated,
}),
}
)
);