diff --git a/server/src/common/decorators/permissions.decorator.ts b/server/src/common/decorators/permissions.decorator.ts new file mode 100644 index 0000000..e5902ee --- /dev/null +++ b/server/src/common/decorators/permissions.decorator.ts @@ -0,0 +1,5 @@ +import { SetMetadata } from '@nestjs/common'; + +export const PERMISSIONS_KEY = 'permissions'; +export const Permissions = (...permissions: string[]) => + SetMetadata(PERMISSIONS_KEY, permissions); diff --git a/server/src/common/enum/index.ts b/server/src/common/enum/index.ts index ab98fc2..89e955f 100644 --- a/server/src/common/enum/index.ts +++ b/server/src/common/enum/index.ts @@ -1,6 +1,6 @@ export enum Role { - User = 'user', Admin = 'admin', + User = 'user', } export enum RedisGroup { diff --git a/server/src/common/guard/permission.guard.ts b/server/src/common/guard/permission.guard.ts index acffe4c..8339240 100644 --- a/server/src/common/guard/permission.guard.ts +++ b/server/src/common/guard/permission.guard.ts @@ -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 { 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( + 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('无权访问!'); } } diff --git a/server/src/modules/system/menu/menu.service.ts b/server/src/modules/system/menu/menu.service.ts index 989d6c0..0f15b72 100644 --- a/server/src/modules/system/menu/menu.service.ts +++ b/server/src/modules/system/menu/menu.service.ts @@ -111,7 +111,7 @@ export class MenuService { }); //step2 删除菜单数据 - await prisma.sysResourcePermission.delete({ where: { id } }); + await prisma.sysResource.delete({ where: { id } }); }); } } diff --git a/server/src/modules/system/resource/resource.service.ts b/server/src/modules/system/resource/resource.service.ts index 2c4c305..337b9a5 100644 --- a/server/src/modules/system/resource/resource.service.ts +++ b/server/src/modules/system/resource/resource.service.ts @@ -107,7 +107,7 @@ export class ResourceService { }); //step2 删除资源数据 - await prisma.sysResourcePermission.delete({ where: { id } }); + await prisma.sysResource.delete({ where: { id } }); }); } } diff --git a/server/src/modules/system/test/test.controller.ts b/server/src/modules/system/test/test.controller.ts index be084d7..51b7376 100644 --- a/server/src/modules/system/test/test.controller.ts +++ b/server/src/modules/system/test/test.controller.ts @@ -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) {} diff --git a/server/src/modules/system/test/test.service.ts b/server/src/modules/system/test/test.service.ts index e6639ee..44457da 100644 --- a/server/src/modules/system/test/test.service.ts +++ b/server/src/modules/system/test/test.service.ts @@ -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 []; } } diff --git a/server/src/modules/system/user/user.controller.ts b/server/src/modules/system/user/user.controller.ts index b475798..5056e58 100644 --- a/server/src/modules/system/user/user.controller.ts +++ b/server/src/modules/system/user/user.controller.ts @@ -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); }