refactor: 系统权限模块重构,迁移至PostgreSQL并对齐新设计
- 切换数据库为PostgreSQL,更新依赖与配置 - 重构权限体系,使用sys_user/sys_role/sys_menu等新实体替代旧模型 - 移除旧的用户角色/权限/系统设置相关代码与实体 - 新增字典、菜单管理模块与基础CRUD接口 - 优化鉴权逻辑,基于菜单权限标识进行接口校验 - 前端同步更新API、路由与权限控制逻辑 - 删除冗余的v-permission指令与相关代码
This commit is contained in:
1 parent
98c22f6afb
commit
0a8103f33d
67 files changed
+3263
-1924
No files matched your search
@@ -1,14 +1,37 @@
|
||||
import { Middleware, IMiddleware } from '@midwayjs/core';
|
||||
import { Context, NextFunction } from '@midwayjs/koa';
|
||||
import { Provide, Inject } from '@midwayjs/core';
|
||||
import { InjectRepository } from '@midwayjs/sequelize';
|
||||
import { PermissionService } from '../service/permission.service';
|
||||
import SysUserRole from '../entity/sysUserRole.entity';
|
||||
import SysRole from '../entity/sysRole.entity';
|
||||
|
||||
// 请求路径前缀 → 菜单权限标识映射
|
||||
const PERMISSION_MAP: Record<string, string> = {
|
||||
'/api/users': 'system:user',
|
||||
'/api/roles': 'system:role',
|
||||
'/api/menus': 'system:menu',
|
||||
'/api/dicts': 'system:dict',
|
||||
'/api/logs': 'system:log',
|
||||
};
|
||||
|
||||
// 超级管理员角色编码,拥有全部权限
|
||||
const ADMIN_ROLE_CODE = 'ADMIN';
|
||||
|
||||
@Provide()
|
||||
export class RbacMiddleware implements IMiddleware<Context, NextFunction> {
|
||||
// 中间件匹配范围:全局生效,跳过公开接口与仪表盘
|
||||
ignore = ['/api/auth/*', '/api/health', '/api/dashboard/*'];
|
||||
|
||||
@Inject()
|
||||
permissionService!: PermissionService;
|
||||
|
||||
@InjectRepository(SysUserRole)
|
||||
userRoleModel!: typeof SysUserRole;
|
||||
|
||||
@InjectRepository(SysRole)
|
||||
roleModel!: typeof SysRole;
|
||||
|
||||
resolve() {
|
||||
return async (ctx: Context, next: NextFunction) => {
|
||||
const user = ctx.state.user;
|
||||
@@ -22,17 +45,21 @@ export class RbacMiddleware implements IMiddleware<Context, NextFunction> {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取当前请求路径和方法,转换为权限码
|
||||
// 例如:GET /api/user/list -> user:list
|
||||
const permissionCode = this.extractPermissionCode(ctx);
|
||||
|
||||
// 超级管理员拥有所有权限
|
||||
if (user.roles && user.roles.includes('super_admin')) {
|
||||
// 路径前缀匹配,未匹配到任何权限映射的请求直接放行
|
||||
const permissionCode = this.matchPermissionCode(ctx.path);
|
||||
if (!permissionCode) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查用户是否拥有该权限
|
||||
// 查询用户角色编码,超级管理员直接放行
|
||||
const roleCodes = await this.getUserRoleCodes(user.userId);
|
||||
if (roleCodes.includes(ADMIN_ROLE_CODE)) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查用户菜单中是否包含该权限标识
|
||||
const hasPermission = await this.permissionService.checkUserPermission(
|
||||
user.userId,
|
||||
permissionCode
|
||||
@@ -51,24 +78,21 @@ export class RbacMiddleware implements IMiddleware<Context, NextFunction> {
|
||||
};
|
||||
}
|
||||
|
||||
private extractPermissionCode(ctx: Context): string {
|
||||
const url = ctx.path.replace('/api/', '').replace(/^\//, '');
|
||||
const method = ctx.method.toLowerCase();
|
||||
|
||||
const methodMap: Record<string, string> = {
|
||||
post: 'create',
|
||||
put: 'update',
|
||||
delete: 'delete',
|
||||
get: 'list',
|
||||
};
|
||||
|
||||
const action = methodMap[method] || method;
|
||||
|
||||
const parts = url.split('/');
|
||||
if (parts.length >= 2) {
|
||||
return `${parts[0]}:${action}`;
|
||||
private matchPermissionCode(path: string): string {
|
||||
for (const [prefix, code] of Object.entries(PERMISSION_MAP)) {
|
||||
if (path === prefix || path.startsWith(prefix + '/')) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
return `${url}:${action}`;
|
||||
private async getUserRoleCodes(userId: number): Promise<string[]> {
|
||||
const userRoles = await this.userRoleModel.findAll({
|
||||
where: { userId },
|
||||
include: [this.roleModel],
|
||||
});
|
||||
|
||||
return userRoles.map(ur => ur.role?.roleCode).filter(Boolean) as string[];
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user