chore: sync marketing pages, CMS extensions, tests and project docs
同步工作区剩余变更,主要包括: - 营销页面组件与布局持续优化(about/news/services/solutions/team 等) - 详情页四层叙事组件、布局组件、UI 组件调整 - CMS 数据模型、API 路由、权限、工作流、站内通知、媒体管理扩展 - 新增/补充单元测试与 E2E 测试(cms-workflow.spec.ts 等) - ESLint 9 迁移、jest/tsconfig 配置更新、依赖调整 - 新增 ADR、CMS 评估文档、Release Review / Acceptance 报告 - 移除水墨装饰组件与大体积未使用字体文件
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import { NextRequest } 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: Response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验请求是否已认证并具备指定权限
|
||||
* 通过返回 { 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 };
|
||||
}
|
||||
Reference in New Issue
Block a user