feat: 分层 RBAC 权限管理系统
后端: - 新增 Role / RolePermission 实体(自动 seed 系统角色) - PermissionService——通过 isAdmin / TenantMember 链路解析用户权限 - @Permission() 装饰器 + PermissionsGuard 守卫 - /api/permissions 和 /api/roles REST API - UserController 内联 role 检查迁移到 @Permission() - PermissionModule 全局注册 前端: - usePermissions hook——获取当前用户权限集 - PermissionGate 组件级门控 - PermissionSettingsView——角色列表+权限矩阵编辑页面 - SettingsView 新增「权限管理」Tab(仅 admin 可见) - 权限预览(26 项,7 分类) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Put,
|
||||
Delete,
|
||||
Body,
|
||||
Param,
|
||||
Request,
|
||||
UseGuards,
|
||||
NotFoundException,
|
||||
BadRequestException,
|
||||
} from '@nestjs/common';
|
||||
import { PermissionService } from './permission.service';
|
||||
import { CombinedAuthGuard } from '../combined-auth.guard';
|
||||
import { RolesGuard } from '../roles.guard';
|
||||
import { Roles } from '../roles.decorator';
|
||||
import { UserRole } from '../../user/user-role.enum';
|
||||
|
||||
@Controller('roles')
|
||||
@UseGuards(CombinedAuthGuard, RolesGuard)
|
||||
export class RoleController {
|
||||
constructor(private readonly permissionService: PermissionService) {}
|
||||
|
||||
/** 列出角色(系统角色 + 租户自定义角色) */
|
||||
@Get()
|
||||
@Roles(UserRole.SUPER_ADMIN, UserRole.TENANT_ADMIN)
|
||||
async findAll(@Request() req) {
|
||||
const tenantId = req.tenantId || req.user.tenantId;
|
||||
return this.permissionService.findAllRoles(tenantId);
|
||||
}
|
||||
|
||||
/** 获取单个角色 */
|
||||
@Get(':id')
|
||||
@Roles(UserRole.SUPER_ADMIN, UserRole.TENANT_ADMIN)
|
||||
async findOne(@Param('id') id: string) {
|
||||
const role = await this.permissionService.findRoleById(id);
|
||||
if (!role) throw new NotFoundException('角色不存在');
|
||||
return role;
|
||||
}
|
||||
|
||||
/** 创建自定义角色 */
|
||||
@Post()
|
||||
@Roles(UserRole.SUPER_ADMIN, UserRole.TENANT_ADMIN)
|
||||
async create(@Body() body: { name: string; description?: string }, @Request() req) {
|
||||
if (!body.name) throw new BadRequestException('角色名不能为空');
|
||||
const tenantId = req.tenantId || req.user.tenantId;
|
||||
try {
|
||||
return await this.permissionService.createRole(body.name, body.description || '', tenantId);
|
||||
} catch (err: any) {
|
||||
throw new BadRequestException(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
/** 修改角色基本信息 */
|
||||
@Put(':id')
|
||||
@Roles(UserRole.SUPER_ADMIN, UserRole.TENANT_ADMIN)
|
||||
async update(@Param('id') id: string, @Body() body: { name?: string; description?: string }) {
|
||||
try {
|
||||
return await this.permissionService.updateRole(id, body);
|
||||
} catch (err: any) {
|
||||
throw new BadRequestException(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
/** 删除自定义角色 */
|
||||
@Delete(':id')
|
||||
@Roles(UserRole.SUPER_ADMIN, UserRole.TENANT_ADMIN)
|
||||
async remove(@Param('id') id: string) {
|
||||
try {
|
||||
await this.permissionService.deleteRole(id);
|
||||
return { success: true };
|
||||
} catch (err: any) {
|
||||
throw new BadRequestException(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取角色的权限列表 */
|
||||
@Get(':id/permissions')
|
||||
@Roles(UserRole.SUPER_ADMIN, UserRole.TENANT_ADMIN)
|
||||
async getPermissions(@Param('id') id: string) {
|
||||
const perms = await this.permissionService.getRolePermissions(id);
|
||||
return { permissions: perms };
|
||||
}
|
||||
|
||||
/** 设置角色的权限(全量替换) */
|
||||
@Put(':id/permissions')
|
||||
@Roles(UserRole.SUPER_ADMIN, UserRole.TENANT_ADMIN)
|
||||
async setPermissions(@Param('id') id: string, @Body() body: { permissions: string[] }) {
|
||||
if (!Array.isArray(body.permissions)) {
|
||||
throw new BadRequestException('permissions 必须是数组');
|
||||
}
|
||||
try {
|
||||
await this.permissionService.setRolePermissions(id, body.permissions);
|
||||
return { success: true, permissions: body.permissions };
|
||||
} catch (err: any) {
|
||||
throw new BadRequestException(err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user