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 {
|
export enum Role {
|
||||||
User = 'user',
|
|
||||||
Admin = 'admin',
|
Admin = 'admin',
|
||||||
|
User = 'user',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum RedisGroup {
|
export enum RedisGroup {
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import { Reflector } from '@nestjs/core';
|
|||||||
|
|
||||||
import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager';
|
import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager';
|
||||||
import { SKIP_AUTH } from '@/common/decorators/skip-auth.decorator';
|
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()
|
@Injectable()
|
||||||
export class PermissionGuard implements CanActivate {
|
export class PermissionGuard implements CanActivate {
|
||||||
@@ -18,16 +21,58 @@ export class PermissionGuard implements CanActivate {
|
|||||||
private readonly configService: ConfigService,
|
private readonly configService: ConfigService,
|
||||||
private reflector: Reflector,
|
private reflector: Reflector,
|
||||||
@Inject(CACHE_MANAGER) private cacheService: Cache,
|
@Inject(CACHE_MANAGER) private cacheService: Cache,
|
||||||
|
private readonly prisma: PrismaService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
const request = context.switchToHttp().getRequest();
|
const request = context.switchToHttp().getRequest();
|
||||||
request['isAdmin'] = request?.user?.account === 'admin';
|
const requiredPermissions = this.reflector.getAllAndOverride<string[]>(
|
||||||
return true;
|
PERMISSIONS_KEY,
|
||||||
// if (request.isSkipAuth === SKIP_AUTH || request.user.account === 'admin') {
|
[context.getHandler(), context.getClass()],
|
||||||
// return true;
|
);
|
||||||
// }
|
|
||||||
|
|
||||||
// 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 删除菜单数据
|
//step2 删除菜单数据
|
||||||
await prisma.sysResourcePermission.delete({ where: { id } });
|
await prisma.sysResource.delete({ where: { id } });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ export class ResourceService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//step2 删除资源数据
|
//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 { TestService } from './test.service';
|
||||||
|
|
||||||
import { SkipAuth } from '@/common/decorators/skip-auth.decorator';
|
import { SkipAuth } from '@/common/decorators/skip-auth.decorator';
|
||||||
|
import { Permissions } from '@/common/decorators/permissions.decorator';
|
||||||
|
|
||||||
@Controller()
|
@Controller()
|
||||||
@SkipAuth()
|
// @SkipAuth()
|
||||||
|
@Permissions('test', 'test2')
|
||||||
export class TestController {
|
export class TestController {
|
||||||
constructor(private readonly testService: TestService) {}
|
constructor(private readonly testService: TestService) {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||||
|
import { PrismaService } from '@/prisma/prisma.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TestService {
|
export class TestService {
|
||||||
findAll() {
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
throw new HttpException('用户不存在!', HttpStatus.NOT_FOUND);
|
|
||||||
|
async findAll() {
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export class UserController {
|
|||||||
getUserInfo(@Request() req) {
|
getUserInfo(@Request() req) {
|
||||||
const { sub } = req['user'];
|
const { sub } = req['user'];
|
||||||
const { isAdmin } = req;
|
const { isAdmin } = req;
|
||||||
|
console.log(isAdmin);
|
||||||
return this.userService.getUserInfo(sub, isAdmin);
|
return this.userService.getUserInfo(sub, isAdmin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user