feat: RBAC
This commit is contained in:
5
server/src/common/decorators/permissions.decorator.ts
Normal file
5
server/src/common/decorators/permissions.decorator.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { SetMetadata } from '@nestjs/common';
|
||||
|
||||
export const PERMISSIONS_KEY = 'permissions';
|
||||
export const Permissions = (...permissions: string[]) =>
|
||||
SetMetadata(PERMISSIONS_KEY, permissions);
|
||||
@@ -1,6 +1,6 @@
|
||||
export enum Role {
|
||||
User = 'user',
|
||||
Admin = 'admin',
|
||||
User = 'user',
|
||||
}
|
||||
|
||||
export enum RedisGroup {
|
||||
|
||||
@@ -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('无权访问!');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ export class MenuService {
|
||||
});
|
||||
|
||||
//step2 删除菜单数据
|
||||
await prisma.sysResourcePermission.delete({ where: { id } });
|
||||
await prisma.sysResource.delete({ where: { id } });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ export class ResourceService {
|
||||
});
|
||||
|
||||
//step2 删除资源数据
|
||||
await prisma.sysResourcePermission.delete({ where: { id } });
|
||||
await prisma.sysResource.delete({ where: { id } });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
|
||||
@@ -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 [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user