参考 novavis-authority 的加解密方案,实现前后端通信的应用层加密: - 重写 src/lib/crypto.ts 使用 Web Crypto API(浏览器兼容),PBKDF2+AES-256-GCM - 新增 src/lib/crypto-server.ts 服务端加解密工具(Node.js crypto) - 新增 src/lib/api-crypto.ts API 路由中间件 withCrypto(),自动解密请求体/加密响应体 - 更新 src/lib/admin-api.ts 自动加密所有请求/解密响应 - 所有 11 个 admin API 路由文件已应用 withCrypto 包装器 - 更新 .env 文件,添加 NEXT_PUBLIC_ENCRYPTION_SECRET 和 ENCRYPTION_SECRET
88 lines
2.3 KiB
TypeScript
88 lines
2.3 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { prisma } from '@/lib/db';
|
|
import { authenticateRequest, type JwtPayload } from '@/lib/auth';
|
|
import { unauthorized, forbidden } from '@/lib/api-response';
|
|
|
|
export type PermissionAction = 'create' | 'read' | 'update' | 'delete' | 'publish';
|
|
|
|
export interface Permission {
|
|
roleCode: string;
|
|
modelCode: string;
|
|
action: PermissionAction;
|
|
}
|
|
|
|
/**
|
|
* 判断一组角色是否对指定模型和操作具备权限
|
|
* super_admin 默认拥有所有权限
|
|
*/
|
|
export function hasPermission(
|
|
roles: string[],
|
|
modelCode: string,
|
|
action: PermissionAction,
|
|
permissions: Permission[]
|
|
): boolean {
|
|
if (roles.includes('super_admin')) return true;
|
|
return permissions.some(
|
|
(p) => roles.includes(p.roleCode) && p.modelCode === modelCode && p.action === action
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 查询数据库判断指定用户是否具备权限
|
|
*/
|
|
export async function checkUserPermission(
|
|
userId: string,
|
|
modelCode: string,
|
|
action: PermissionAction
|
|
): Promise<boolean> {
|
|
const userRoles = await prisma.userRole.findMany({
|
|
where: { userId },
|
|
});
|
|
|
|
const roleCodes = userRoles.map((ur) => (ur as { roleCode: string }).roleCode);
|
|
if (roleCodes.includes('super_admin')) return true;
|
|
if (roleCodes.length === 0) return false;
|
|
|
|
const permissionRecords = await prisma.permission.findMany({
|
|
where: { roleCode: { in: roleCodes } },
|
|
});
|
|
|
|
const permissions = permissionRecords.map((p) => ({
|
|
roleCode: (p as { roleCode: string }).roleCode,
|
|
modelCode: (p as { modelCode: string }).modelCode,
|
|
action: (p as { action: PermissionAction }).action,
|
|
}));
|
|
|
|
return hasPermission(roleCodes, modelCode, action, permissions);
|
|
}
|
|
|
|
export interface PermissionSuccess {
|
|
user: JwtPayload;
|
|
}
|
|
|
|
export interface PermissionFailure {
|
|
response: NextResponse;
|
|
}
|
|
|
|
/**
|
|
* 校验请求是否已认证并具备指定权限
|
|
* 通过返回 { user },失败返回 { response }
|
|
*/
|
|
export async function requirePermission(
|
|
request: NextRequest,
|
|
modelCode: string,
|
|
action: PermissionAction
|
|
): Promise<PermissionSuccess | PermissionFailure> {
|
|
const user = authenticateRequest(request);
|
|
if (!user) {
|
|
return { response: unauthorized() };
|
|
}
|
|
|
|
const allowed = await checkUserPermission(user.userId, modelCode, action);
|
|
if (!allowed) {
|
|
return { response: forbidden() };
|
|
}
|
|
|
|
return { user };
|
|
}
|