import * as _ from "lodash" ; import { Reflector } from "@nestjs/core" ; import { CanActivate , ExecutionContext , Injectable , Inject , ForbiddenException , UnauthorizedException } from "@nestjs/common" ; import { RoleDto } from "../dto" ; import { PermissionName , RoleName , RoleWildcard } from "../../db" ; import { PermissionDiToken , PermissionService } from "../permission" ; import { PUBLIC_METADATA_TOKEN , AuthorizeMetadata , AUTHORIZE_METADATA_TOKEN } from "../decorators" ; export type PermissionWildcard = "*" ; export const PermissionWildcard = "*" ; @ Injectable ( ) export class AuthorizeGuard implements CanActivate { constructor ( private readonly reflector , @ Inject ( PermissionDiToken . PERMISSION_SERVICE ) private readonly permissionService ) { } public async canActivate ( context ) { const request = context . switchToHttp ( ) . getRequest ( ) ; const handler = context . getHandler ( ) ; const isPublic = this . reflector . get < boolean > ( PUBLIC_METADATA_TOKEN , handler ) ; if ( isPublic ) { return true ; } if ( ! isPublic && ! request . user ) { throw new UnauthorizedException ( ) ; } const methodMetadata = this . reflector . get < AuthorizeMetadata > ( AUTHORIZE_METADATA_TOKEN , handler ) ; const controllerMetadata = this . reflector . get < AuthorizeMetadata > ( AUTHORIZE_METADATA_TOKEN , context . getClass ( ) ) ; const metadata = methodMetadata || controllerMetadata ; if ( ! metadata ) { return ! ! request . user ; } const userRole = _ . get ( request , "user.role" ) ; if ( ! userRole ) { throw new ForbiddenException ( `Incorrect user data payload: no user role resolved` ) ; } if ( userRole . name === RoleName . SUPER_ADMIN ) { return true ; } const requiredPermissions = metadata [ RoleWildcard ] || metadata [ userRole . name ] ; if ( ! requiredPermissions ) { return false ; } if ( requiredPermissions === PermissionWildcard ) { return true ; } return this . permissionService . isAllowed ( request . user , requiredPermissions ) ; } }