Merge branch 'main' of http://git.dibox.tech/parttime/smart_grid_iot
This commit is contained in:
commit
7b6fe46d10
21 files changed
+3856
-110
No files matched your search
@@ -1,124 +1,117 @@
|
||||
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';
|
||||
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',
|
||||
'/api/jobs': 'system:job',
|
||||
'/api/customers': 'customer:list',
|
||||
'/api/customer-departments': 'customer:department',
|
||||
'/api/customer-accounts': 'customer:account',
|
||||
'/api/customer-visits': 'customer:visit',
|
||||
'/api/upload': 'customer:visit',
|
||||
'/api/customer-buildings': 'customer:building',
|
||||
'/api/customer-rooms': 'customer:room',
|
||||
'/api/survey-orders': 'project:survey',
|
||||
'/api/project-plans': 'project:plan',
|
||||
'/api/contracts': 'project:contract',
|
||||
'/api/install-orders': 'project:install',
|
||||
'/api/acceptances': 'project:acceptance',
|
||||
'/api/visit-records': 'project:visit',
|
||||
'/api/service-prices': 'dispatch:price',
|
||||
'/api/dispatch-prices': 'dispatch:cost',
|
||||
'/api/workers': 'dispatch:worker',
|
||||
"/api/users": "system:user",
|
||||
"/api/roles": "system:role",
|
||||
"/api/menus": "system:menu",
|
||||
"/api/dicts": "system:dict",
|
||||
"/api/logs": "system:log",
|
||||
"/api/jobs": "system:job",
|
||||
"/api/customers": "customer:list",
|
||||
"/api/customer-departments": "customer:department",
|
||||
"/api/customer-accounts": "customer:account",
|
||||
"/api/customer-visits": "customer:visit",
|
||||
"/api/upload": "customer:visit",
|
||||
"/api/customer-buildings": "customer:building",
|
||||
"/api/customer-rooms": "customer:room",
|
||||
"/api/survey-orders": "project:survey",
|
||||
"/api/project-plans": "project:plan",
|
||||
"/api/contracts": "project:contract",
|
||||
"/api/install-orders": "project:install",
|
||||
"/api/acceptances": "project:acceptance",
|
||||
"/api/visit-records": "project:visit",
|
||||
"/api/repair-requests": "dispatch:repair",
|
||||
"/api/repair-dispatchs": "dispatch:repair",
|
||||
"/api/maintenance-orders": "dispatch:maintenance",
|
||||
"/api/service-prices": "dispatch:price",
|
||||
"/api/dispatch-prices": "dispatch:cost",
|
||||
"/api/workers": "dispatch:worker"
|
||||
};
|
||||
|
||||
// 超级管理员角色编码,拥有全部权限
|
||||
const ADMIN_ROLE_CODE = 'ADMIN';
|
||||
const ADMIN_ROLE_CODE = "ADMIN";
|
||||
|
||||
@Provide()
|
||||
export class RbacMiddleware implements IMiddleware<Context, NextFunction> {
|
||||
// 中间件匹配范围:全局生效,跳过公开接口、仪表盘与电工 APP 接口
|
||||
// /api/workers/options 与 /api/workers/recommend 放行:业务员在「项目勘察派单」页
|
||||
// 仍可调用电工下拉与推荐接口,不受 dispatch:worker 权限限制(本次需求有意设计)
|
||||
ignore = [
|
||||
'/api/auth/*',
|
||||
'/api/health',
|
||||
'/api/dashboard/*',
|
||||
'/api/worker-app/*',
|
||||
'/api/workers/options',
|
||||
'/api/workers/recommend',
|
||||
];
|
||||
// 中间件匹配范围:全局生效,跳过公开接口、仪表盘与电工 APP 接口
|
||||
// /api/workers/options 与 /api/workers/recommend 放行:业务员在「项目勘察派单」页
|
||||
// 仍可调用电工下拉与推荐接口,不受 dispatch:worker 权限限制(本次需求有意设计)
|
||||
ignore = ["/api/auth/*", "/api/health", "/api/dashboard/*", "/api/worker-app/*", "/api/workers/options", "/api/workers/recommend"];
|
||||
|
||||
@Inject()
|
||||
permissionService!: PermissionService;
|
||||
@Inject()
|
||||
permissionService!: PermissionService;
|
||||
|
||||
@InjectRepository(SysUserRole)
|
||||
userRoleModel!: typeof SysUserRole;
|
||||
@InjectRepository(SysUserRole)
|
||||
userRoleModel!: typeof SysUserRole;
|
||||
|
||||
@InjectRepository(SysRole)
|
||||
roleModel!: typeof SysRole;
|
||||
@InjectRepository(SysRole)
|
||||
roleModel!: typeof SysRole;
|
||||
|
||||
resolve() {
|
||||
return async (ctx: Context, next: NextFunction) => {
|
||||
const user = ctx.state.user;
|
||||
resolve() {
|
||||
return async (ctx: Context, next: NextFunction) => {
|
||||
const user = ctx.state.user;
|
||||
|
||||
if (!user) {
|
||||
ctx.status = 401;
|
||||
ctx.body = {
|
||||
code: 401,
|
||||
message: '未登录',
|
||||
};
|
||||
return;
|
||||
}
|
||||
if (!user) {
|
||||
ctx.status = 401;
|
||||
ctx.body = {
|
||||
code: 401,
|
||||
message: "未登录"
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
// 路径前缀匹配,未匹配到任何权限映射的请求直接放行
|
||||
const permissionCode = this.matchPermissionCode(ctx.path);
|
||||
if (!permissionCode) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
// 路径前缀匹配,未匹配到任何权限映射的请求直接放行
|
||||
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 roleCodes = await this.getUserRoleCodes(user.userId);
|
||||
if (roleCodes.includes(ADMIN_ROLE_CODE)) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查用户菜单中是否包含该权限标识
|
||||
const hasPermission = await this.permissionService.checkUserPermission(
|
||||
user.userId,
|
||||
permissionCode
|
||||
);
|
||||
// 检查用户菜单中是否包含该权限标识
|
||||
const hasPermission = await this.permissionService.checkUserPermission(user.userId, permissionCode);
|
||||
|
||||
if (!hasPermission) {
|
||||
ctx.status = 403;
|
||||
ctx.body = {
|
||||
code: 403,
|
||||
message: '没有访问权限',
|
||||
};
|
||||
return;
|
||||
}
|
||||
if (!hasPermission) {
|
||||
ctx.status = 403;
|
||||
ctx.body = {
|
||||
code: 403,
|
||||
message: "没有访问权限"
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
await next();
|
||||
};
|
||||
}
|
||||
await next();
|
||||
};
|
||||
}
|
||||
|
||||
private matchPermissionCode(path: string): string {
|
||||
for (const [prefix, code] of Object.entries(PERMISSION_MAP)) {
|
||||
if (path === prefix || path.startsWith(prefix + '/')) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
private matchPermissionCode(path: string): string {
|
||||
for (const [prefix, code] of Object.entries(PERMISSION_MAP)) {
|
||||
if (path === prefix || path.startsWith(prefix + "/")) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private async getUserRoleCodes(userId: number): Promise<string[]> {
|
||||
const userRoles = await this.userRoleModel.findAll({
|
||||
where: { userId },
|
||||
include: [this.roleModel],
|
||||
});
|
||||
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[];
|
||||
}
|
||||
return userRoles.map((ur) => ur.role?.roleCode).filter(Boolean) as string[];
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user