Files
novalon-website/src/lib/permissions.ts
T
zhangxiang d5d04aa96d feat: implement frontend-backend encrypted communication via AES-256-GCM
参考 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
2026-08-02 09:11:36 +08:00

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 };
}