/** * 认证中间件 * 用于保护需要登录的 API 路由 */ import { NextRequest, NextResponse } from 'next/server'; import { extractTokenFromHeader, TokenPayload } from './jwt'; import { Role } from '@prisma/client'; import { getUserInfo, UserInfo } from './permissions'; import { validateToken } from './token-validator'; import type { AllowedRole } from './role-scope'; import { hasAllowedRole } from './role-scope'; /** * 认证结果 */ export interface AuthResult { success: boolean; payload?: TokenPayload; userInfo?: UserInfo; error?: string; } /** * 验证请求的认证信息 */ export async function authenticateRequest(request: NextRequest): Promise { // 优先从 Authorization 头中读取 Bearer Token(适用于前端显式传入) const authHeader = request.headers.get('authorization'); let token = extractTokenFromHeader(authHeader); // 如果请求头中没有 Token,则退回到 Cookie 中的 auth-token(适用于浏览器自动带上的 Cookie) if (!token) { const cookieToken = request.cookies.get('auth-token')?.value; if (cookieToken) { token = cookieToken; } } if (!token) { return { success: false, error: '未提供认证令牌', }; } const payload = await validateToken(token, process.env.JWT_SECRET || ''); if (!payload) { return { success: false, error: '认证令牌无效或已过期', }; } // 获取用户完整信息(包括管理关系) const userInfo = await getUserInfo(payload.userId); if (!userInfo) { return { success: false, error: '用户不存在', }; } // 检查用户状态 if (userInfo.status === 'PENDING') { return { success: false, error: '账号待管理员激活', }; } if (userInfo.status !== 'ACTIVE') { return { success: false, error: '账号已被停用', }; } return { success: true, payload, userInfo, }; } /** * 检查用户是否有指定角色 */ export function hasRole(userInfo: UserInfo, allowedRoles: readonly AllowedRole[]): boolean { return hasAllowedRole(userInfo, allowedRoles); } /** * 检查用户是否为管理员(超级管理员或管理员) */ export function isAdmin(payload: TokenPayload): boolean { return ['SUPER_ADMIN', 'ADMIN'].includes(payload.role); } /** * 检查用户是否为部门管理员或更高权限 */ export function isDepartmentManagerOrAbove(payload: TokenPayload): boolean { return ['SUPER_ADMIN', 'ADMIN', 'SUPERVISOR'].includes(payload.role); } /** * 检查用户是否为组长或更高权限 */ export function isTeamLeaderOrAbove(payload: TokenPayload): boolean { return ['SUPER_ADMIN', 'ADMIN', 'SUPERVISOR'].includes(payload.role); } /** * 创建未授权响应 */ export function unauthorizedResponse(message: string = '未授权访问'): NextResponse { return NextResponse.json( { error: message }, { status: 401 } ); } /** * 创建禁止访问响应 */ export function forbiddenResponse(message: string = '权限不足'): NextResponse { return NextResponse.json( { error: message }, { status: 403 } ); } /** * 认证中间件包装器 * 用于包装需要认证的 API 处理函数 */ export function withAuth( handler: (request: NextRequest, payload: TokenPayload, userInfo: UserInfo) => Promise, options?: { allowedRoles?: AllowedRole[]; } ) { return async (request: NextRequest): Promise => { // 验证认证 const authResult = await authenticateRequest(request); if (!authResult.success || !authResult.payload || !authResult.userInfo) { return unauthorizedResponse(authResult.error); } // 检查角色权限 if (options?.allowedRoles && !hasRole(authResult.userInfo, options.allowedRoles)) { return forbiddenResponse('您没有权限访问此资源'); } // 调用实际的处理函数 return handler(request, authResult.payload, authResult.userInfo); }; }