diff --git a/src/modules/auth/scope.decorator.ts b/src/modules/auth/scope.decorator.ts new file mode 100644 index 000000000..437bffc6b --- /dev/null +++ b/src/modules/auth/scope.decorator.ts @@ -0,0 +1,3 @@ +import { SetMetadata } from '@nestjs/common'; + +export const Scopes = (...scopes: string[]) => SetMetadata('scopes', scopes); diff --git a/src/modules/auth/scope.guard.ts b/src/modules/auth/scope.guard.ts index edc3a77bf..f78c508be 100644 --- a/src/modules/auth/scope.guard.ts +++ b/src/modules/auth/scope.guard.ts @@ -1,6 +1,6 @@ import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; -import { AccessTokenParsed } from './auth.interface'; +import { AccessTokenParsed, UserRequest } from './auth.interface'; import minimatch from 'minimatch'; @Injectable() @@ -9,10 +9,16 @@ export class ScopesGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const scopes = this.reflector.get('scopes', context.getHandler()); - console.log(scopes); if (!scopes) return true; - const request = context.switchToHttp().getRequest(); + const request = context.switchToHttp().getRequest(); const user: AccessTokenParsed = request.user; - // return user.scopes.includes(scopes); + let authorized = false; + for (const userScope of user.scopes) { + for (const scope of scopes) { + authorized = authorized || minimatch(scope, userScope); + if (authorized) return true; + } + } + return authorized; } } diff --git a/src/modules/user/user.controller.ts b/src/modules/user/user.controller.ts index 3374e1c0b..047bf32fd 100644 --- a/src/modules/user/user.controller.ts +++ b/src/modules/user/user.controller.ts @@ -18,6 +18,8 @@ import { OrderByPipe } from 'src/pipes/order-by.pipe'; import { WherePipe } from 'src/pipes/where.pipe'; import { UserRequest } from '../auth/auth.interface'; import { JwtAuthGuard } from '../auth/jwt-auth.guard'; +import { Scopes } from '../auth/scope.decorator'; +import { ScopesGuard } from '../auth/scope.guard'; import { UpdateUserDto } from './user.dto'; import { UsersService } from './user.service'; @@ -38,6 +40,8 @@ export class UserController { } @Get(':id') + @UseGuards(ScopesGuard) + @Scopes('user3:read') async get( @Req() req: UserRequest, @Param('id', ParseIntPipe) id: number,