#Should guards be imported via modules?

14 messages · Page 1 of 1 (latest)

agile pelican
#

Hi,
I am upgrading nestjs to latest in my project and I'm having some Nest can't resolve dependencies of the AuthGuard-related issues.

Basically I have an AuthModule like this

@Module({
  imports: [
   // ...
   TypeOrmCustomRepositoryModule.forCustomRepository([
      UserRepository,
    ]),
  ],
  providers: [
    // ...
    AuthGuard,
  ],
  exports: [
    // ...
    AuthGuard,
  ],
})

And in other modules, if I want to use my AuthGuard I'm importing AuthModule in imports array. Then I use AuthGuard in controllers.

This gives me error

Potential solutions:
- Is XYModule a valid NestJS module?
- If UserRepository is a provider, is it part of the current XYModule?
- If UserRepository is exported from a separate @Module, is that module imported within DynamicTagsModule?
  @Module({
    imports: [ /* the Module containing UserRepository */ ]
  })```

I suspect that this is not what I'm supposed to do as using Authguard with `@UseGuards` does not seem to be injected like other providers/services.

Now I could go add UserRepository to imports of other modules but I don't think that is the right way.

So my question is what is the proper way to use AuthGuard? Import via modules or use directly as provider?
#

It seems to be instantiating new AuthGuards but using the exported providers from AuthModule to do so, not using the exported AuthGuard in the module

night rover
#

Enhacers don't work like regular providers and they should not be put in the providers array. If they are, Nest will still create an instace of them (like regular providers), but they won't be bound anywhere, so it's useless to do so.

When you bind an enhancer using @UseXXX, then that tells Nest to actually instantiate the enhancer and it will look for its dependecies in the module in which it is USED.

#

That means - if you're using an enhancer on a controller in some module, that module must have access to all the dependencies that the enhancer needs

agile pelican
#

Got it. So basically don't put Guards into providers

night rover
#

Basically yes

agile pelican
#

I guess guards are generally meant to be global scoped. I made a decision early not to do that which may not have been the greatest idea as now I'm scattering @UseGuards throughout my code base but overall it doesn't matter that much

night rover
#

There is a way to use it the way you intend - which should be IMO the defaul way, because it doesn't break encaplsulation (you don't need to expose all dependencies)

#

I have been using this little trick to use exported enhancers in providers:

export function ProvidedGuard(token: any) {
  class ProvidedGuard implements CanActivate {
    constructor(@Inject(token) private readonly provided: CanActivate) {}
    canActivate(context: ExecutionContext){
      return this.provided.canActivate(context);
    }
  }
return ProvidedGuard
}
#

and use it like so @UseGuards(ProvidedGuard(AuthGuard))

#

The ProvidedGuard mixin will construct a class that injects an existing guard by its injection token - this only requires you to export the guard and not all its dependencies

#

and you can wrap the decorator to simplify its registration, too

const UseProvidedGuard = (token: any) => UseGuards(ProvidedGuard(token))
agile pelican
#

I see. For now I have a solution for my repo but this is useful

#

Fyi, I havent found this info regarding enhancers anywhere in the docs so that may be useful to know