dependency-injectionnestjsguard

How to pass reflector to Nest.js global guard?


I am new to nest.js and I have a question. I have a Roles Guard like this

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
import { Reflector } from '@nestjs/core';

@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {
  }

  canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
    const roles = this.reflector.get<string[]>('roles', context.getHandler());
    if (!roles) {
      return true;
    }
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    return user.role.some(role => !!roles.find(item => item === role));
  }

}

Now I want to use this guard as a global guard like this

app.useGlobalGuards(new RolesGuard())

But it says that I need to pass argument(the reflector) to the guard as I mentioned in the constructor, now will it be okay to initialize the reflector like this?

const reflector:Reflector = new Reflector();
app.useGlobalGuards(new RolesGuard(reflector))

Or is there a better way to do this?


Solution

  • On the official Nest JS fundamentals course, in lecture "54 Protect Routes with Guards", the instructor specifies it is not best practice to create instance of reflector yourself.

    A better way to resolve dependencies is to create a common module, and register your guard there. That way, reflector instance is resolved by nest runtime and you can also specify imports array for any other dependencies.

    import { Module } from '@nestjs/common';
    import { APP_GUARD } from '@nestjs/core';
    import { AuthTokenGuard } from './guards/auth-token.guard';
    import { ConfigModule } from '@nestjs/config';
    
    @Module({
      imports: [ConfigModule],
      providers: [
        {
          provide: APP_GUARD,
          useClass: AuthTokenGuard,
        },
      ],
    })
    export class CommonModule {}