/** * 认证相关的React Hook * 提供JWT认证状态管理和用户信息获取功能 */ import { useLoaderData } from "@remix-run/react"; import { JWTUtils, type UserInfoForJWT } from "~/utils/jwt"; // 定义从loader返回的认证数据结构 interface AuthLoaderData { userInfo?: { sub: string; user_id: string; username: string; nick_name: string; email?: string; phone_number?: string; ou_id: string; ou_name: string; is_leader: boolean; user_role: string; frontend_jwt?: string; }; isAuthenticated?: boolean; userRole?: string; } /** * 认证状态Hook * @returns 认证状态和用户信息 */ export function useAuth() { // 从loader data中获取认证信息 const loaderData = useLoaderData() as AuthLoaderData; const isAuthenticated = loaderData?.isAuthenticated || false; const userInfo = loaderData?.userInfo; const frontendJWT = userInfo?.frontend_jwt; /** * 验证JWT是否有效 * @returns JWT验证结果 */ const validateJWT = () => { if (!frontendJWT) { return { valid: false, error: "JWT不存在" }; } return JWTUtils.verifyJWT(frontendJWT); }; /** * 检查JWT是否即将过期 * @param bufferMinutes 缓冲时间(分钟) * @returns 是否即将过期 */ const isJWTExpiringSoon = (bufferMinutes: number = 5) => { if (!frontendJWT) { return true; } return JWTUtils.isJWTExpiringSoon(frontendJWT, bufferMinutes); }; /** * 从JWT中获取用户信息 * @returns 用户信息 */ const getUserInfoFromJWT = (): UserInfoForJWT | null => { if (!frontendJWT) { return null; } return JWTUtils.extractUserInfo(frontendJWT); }; /** * 获取JWT过期时间 * @returns 过期时间戳 */ const getJWTExpiration = () => { if (!frontendJWT) { return null; } return JWTUtils.getJWTExpiration(frontendJWT); }; /** * 检查用户是否有特定角色 * @param role 角色名称 * @returns 是否有该角色 */ const hasRole = (role: string) => { return userInfo?.user_role === role; }; /** * 检查用户是否为管理员 * @returns 是否为管理员 */ const isAdmin = () => { return userInfo?.user_role === 'developer' || userInfo?.is_leader === true; }; return { // 基本认证状态 isAuthenticated, userInfo, frontendJWT, // JWT相关方法 validateJWT, isJWTExpiringSoon, getUserInfoFromJWT, getJWTExpiration, // 权限检查方法 hasRole, isAdmin, // 便捷属性 userId: userInfo?.user_id, username: userInfo?.username, nickName: userInfo?.nick_name, email: userInfo?.email, phoneNumber: userInfo?.phone_number, ouName: userInfo?.ou_name, userRole: userInfo?.user_role, isLeader: userInfo?.is_leader }; } export default useAuth;