import { EEnvConfig, ENextaPermission, ErrorMessages } from '@share/constant.config'; import { CanActivate, ExecutionContext, HttpException, HttpStatus, Injectable, SetMetadata, } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { AsyncLocalStorage } from 'async_hooks'; import { AuthContext, AuthType } from './interface'; import { ConfigService } from '@nestjs/config'; @Injectable() export class AuthGuard implements CanActivate { constructor() { } async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest(); if (!request.user) { throw new HttpException( { statusCode: HttpStatus.UNAUTHORIZED, message: ErrorMessages.INVALID_CREDENTIALS, }, HttpStatus.UNAUTHORIZED, ); } return true; } } export const ROLES_KEY = 'roles'; export const NextaRoles = (...roles: ENextaPermission[]) => SetMetadata(ROLES_KEY, roles); @Injectable() export class RolesGuard implements CanActivate { private readonly enableGuard: boolean; constructor( private reflector: Reflector, private readonly als: AsyncLocalStorage, private readonly configService: ConfigService, ) { this.enableGuard = this.configService.get(EEnvConfig.ENABLE_ROLE_GUARD) === 'true'; } canActivate(context: ExecutionContext): boolean { if (!this.enableGuard) return true; const requiredRoles = this.reflector.getAllAndOverride(ROLES_KEY, [ context.getHandler(), context.getClass(), ]); if (!requiredRoles) return true; const authContext = this.als.getStore(); if (authContext?.authType === AuthType.INTERNAL) return true; return requiredRoles.some((role) => authContext?.authorities?.includes(role.toString())); } }