fix: 全面优化安全、性能和代码质量
P0: 环境变量校验/事务保护/RBAC权限 P1: 花名册分页/密码重置验证码/ErrorBoundary/N+1查询优化 P2: 导出限制/自定义错误类/body大小限制/代码去重 P3: 自定义确认弹窗替换window.confirm
This commit is contained in:
@@ -1,8 +1,16 @@
|
||||
import { Request, Response, NextFunction } from 'express'
|
||||
import { ZodError } from 'zod'
|
||||
import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library'
|
||||
import { AppError } from '../lib/AppError'
|
||||
|
||||
export function errorHandler(err: unknown, _req: Request, res: Response, _next: NextFunction) {
|
||||
if (err instanceof AppError) {
|
||||
return res.status(err.statusCode).json({
|
||||
success: false,
|
||||
error: { code: err.code, message: err.message },
|
||||
})
|
||||
}
|
||||
|
||||
if (err instanceof ZodError) {
|
||||
return res.status(422).json({
|
||||
success: false,
|
||||
@@ -29,6 +37,24 @@ export function errorHandler(err: unknown, _req: Request, res: Response, _next:
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof err === 'object' && err !== null && 'code' in err && 'message' in err) {
|
||||
const e = err as { code: string; message: string }
|
||||
const statusMap: Record<string, number> = {
|
||||
NOT_FOUND: 404,
|
||||
CONFLICT: 409,
|
||||
VALIDATION_ERROR: 422,
|
||||
PLAN_LIMIT: 403,
|
||||
AUTH_FAILED: 401,
|
||||
TOKEN_INVALID: 401,
|
||||
ACCOUNT_DISABLED: 403,
|
||||
DUPLICATE: 400,
|
||||
}
|
||||
return res.status(statusMap[e.code] || 400).json({
|
||||
success: false,
|
||||
error: { code: e.code, message: e.message },
|
||||
})
|
||||
}
|
||||
|
||||
console.error('Unhandled error:', err)
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Response, NextFunction } from 'express'
|
||||
import { AuthRequest } from './auth'
|
||||
|
||||
export function requireRole(...roles: string[]) {
|
||||
return (req: AuthRequest, res: Response, next: NextFunction) => {
|
||||
if (!req.user) {
|
||||
return res.status(401).json({ success: false, error: { code: 'UNAUTHORIZED', message: '未认证' } })
|
||||
}
|
||||
if (!roles.includes(req.user.role)) {
|
||||
return res.status(403).json({ success: false, error: { code: 'FORBIDDEN', message: '无权限执行此操作' } })
|
||||
}
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
export const requireAdmin = requireRole('ADMIN')
|
||||
Reference in New Issue
Block a user