feat: RBAC

This commit is contained in:
2025-03-11 17:21:40 +08:00
parent 5058aefd66
commit 95de4f6484
8 changed files with 68 additions and 12 deletions

View File

@@ -0,0 +1,5 @@
import { SetMetadata } from '@nestjs/common';
export const PERMISSIONS_KEY = 'permissions';
export const Permissions = (...permissions: string[]) =>
SetMetadata(PERMISSIONS_KEY, permissions);

View File

@@ -1,6 +1,6 @@
export enum Role {
User = 'user',
Admin = 'admin',
User = 'user',
}
export enum RedisGroup {

View File

@@ -11,6 +11,9 @@ import { Reflector } from '@nestjs/core';
import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager';
import { SKIP_AUTH } from '@/common/decorators/skip-auth.decorator';
import { PERMISSIONS_KEY } from '@/common/decorators/permissions.decorator';
import { PrismaService } from '@/prisma/prisma.service';
import { PermissionType, Role } from '@/common/enum';
@Injectable()
export class PermissionGuard implements CanActivate {
@@ -18,16 +21,58 @@ export class PermissionGuard implements CanActivate {
private readonly configService: ConfigService,
private reflector: Reflector,
@Inject(CACHE_MANAGER) private cacheService: Cache,
private readonly prisma: PrismaService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
request['isAdmin'] = request?.user?.account === 'admin';
return true;
// if (request.isSkipAuth === SKIP_AUTH || request.user.account === 'admin') {
// return true;
// }
const requiredPermissions = this.reflector.getAllAndOverride<string[]>(
PERMISSIONS_KEY,
[context.getHandler(), context.getClass()],
);
// throw new ForbiddenException('无权访问!');
// 跳过验证
if (request.isSkipAuth === SKIP_AUTH) return true;
// 查找当前用户拥有的角色
const userRoles = await this.prisma.sysRole.findMany({
select: {
id: true,
code: true,
},
where: {
sysUserRole: {
some: {
userId: request.user.sub,
},
},
},
});
// 所有用户的code
const roleCodes = userRoles.map((item) => item.code);
const roleIds = userRoles.map((item) => item.id);
// 如果是管理员 直接通过验证不需要进行接口鉴权
if (roleCodes.includes(Role.Admin)) {
request['isAdmin'] = true;
return true;
}
console.log(roleIds);
// 已知 权限字符 通过权限字符找出权限id 再根据权限id 找出拥有权限的角色code
const hasPermission = await this.prisma.sysRolePermission.findMany({
where: {
roleId: {
in: roleIds,
},
},
});
// TODO
console.log(hasPermission);
// 判断当前接口是否存在权限
throw new ForbiddenException('无权访问!');
}
}

View File

@@ -111,7 +111,7 @@ export class MenuService {
});
//step2 删除菜单数据
await prisma.sysResourcePermission.delete({ where: { id } });
await prisma.sysResource.delete({ where: { id } });
});
}
}

View File

@@ -107,7 +107,7 @@ export class ResourceService {
});
//step2 删除资源数据
await prisma.sysResourcePermission.delete({ where: { id } });
await prisma.sysResource.delete({ where: { id } });
});
}
}

View File

@@ -2,9 +2,11 @@ import { Controller, Get } from '@nestjs/common';
import { TestService } from './test.service';
import { SkipAuth } from '@/common/decorators/skip-auth.decorator';
import { Permissions } from '@/common/decorators/permissions.decorator';
@Controller()
@SkipAuth()
// @SkipAuth()
@Permissions('test', 'test2')
export class TestController {
constructor(private readonly testService: TestService) {}

View File

@@ -1,8 +1,11 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { PrismaService } from '@/prisma/prisma.service';
@Injectable()
export class TestService {
findAll() {
throw new HttpException('用户不存在!', HttpStatus.NOT_FOUND);
constructor(private readonly prisma: PrismaService) {}
async findAll() {
return [];
}
}

View File

@@ -33,6 +33,7 @@ export class UserController {
getUserInfo(@Request() req) {
const { sub } = req['user'];
const { isAdmin } = req;
console.log(isAdmin);
return this.userService.getUserInfo(sub, isAdmin);
}