Hi,
Right now dependency injection is not possible in global pipes,guards,filters and interceptors (#230),
is there any way to set globality inside decorator?
@Guard({global:true}) //or @Guard(true)
export class AuthGuard implements CanActivate{
constructor(private authService: AuthService) {
}
}
Hey @mkzaker if it's use as a global you must inject it as a normal parameter of the constructor :
constructor(authService: AuthServie)
and the other side provide the authService
at the instanciation.
Because in the global your not related to a module and then you can't use the IoC pattern
Yes, @adrien2p is right. The AuthGuard would need to be injected to use DI; in other words, it needs to be provided in a module where AuthService
is also provided.
hey everybody and thanks a lot for your replies, but i suggest you change the method of defining globals for being able to use ioc .
best regards.
Hi @mkzaker,
Global guards, interceptors etc. live outside any module, so they can't inject anything. It won't be possible because we don't have a 'global scope'. 馃檪
In authorized.guard.ts
I've tried both
constructor(@Inject('AuthService') private readonly authService:AuthService) {
}
constructor(private readonly authService:AuthService) {
}
But as @kamilmysliwiec mentioned, of course injection will not work, because there is no global scope.
So what's the best approach when a guard verifies authorization and needs to access an authentication service that verifies a role by using the user service to get the data from?
@michaelfreund middlewares are loosely coupled from modules, thus it may be better to use them instead. If you prefer to use guards, you need to guarantee an access to the AuthService
. You can export this service from the AuthModule
, and then import this module wherever you want to use your guard.
I have exported the AuthService in the AuthModule. However, I get an error message when I start the application.
app.ts Expected 1 arguments, but got 0.
authorized.guard.ts
constructor(private readonly authService:AuthService) {
console.log('----- auth service -----', this.authService);
}
Obviously because constructor of AuthorizedGuard is missing the AuthService which is not provided
app.ts
nest.useGlobalGuards(new RoleGuard(reflector), new AuthorizedGuard(/* auth service not provided */));
I guess it's a bad idea to do something like
nest.useGlobalGuards(new RoleGuard(reflector), new AuthorizedGuard(
new AuthService()
));
Also AuthService relies on UserService. So I would end up with something stupid like
nest.useGlobalGuards(new RoleGuard(reflector), new AuthorizedGuard(
new AuthService(
new UserService()
);
));
Which anyway won't work.
I've followed your suggestion of using middleware for this thing. AuthMiddleware now handles JWT verification, queries user and roles from the database and attaches them to the request object. So the RoleGuard can do his job by evaluating the provided roles.
Global guards, interceptors etc. live outside any module, so they can't inject anything. It won't be possible because we don't have a 'global scope'.
How about treating global guards, interceptors, etc.
as part of root application module?
Why not make everything global? Have providers available to all child modules? That way you can use guards and interceptors as providers
That would require some rearchitecting but I think this is a feature people generally want.
I think since 4.5.0 you can handle injection for any global thing like this:
const app = await NestFactory.create(App);
const apiExceptionFilter = app.get<ApiExceptionFilter>(ApiExceptionFilter);
app.useGlobalFilters(apiExceptionFilter);
await app.listen(port);
works for me with exeption filter, didn't try it with guards, but should be the same
I got this solution form #302
I have to say, the way you have to configure global stuff is so weird, comparing to how nice other things are architected
as @br0wn suggested, it would be much better to have the top module have all global stuff
and all child modules just inherits it, like @wbhob suggested
I think since 4.5.0 you can handle injection for any global thing like this:
const app = await NestFactory.create(App); const apiExceptionFilter = app.get<ApiExceptionFilter>(ApiExceptionFilter); app.useGlobalFilters(apiExceptionFilter); await app.listen(port);
works for me with exeption filter, didn't try it with guards, but should be the same
I got this solution form #302
this worked for me:
const reflector = app.get
app.useGlobalGuards(new AuthGuard(reflector));
Don't know what version they added this feature, but now it's beautiful and works like it should to match the whole Nest design.
To add global pipes, guards or interceptors, Use injection with special injection token.
Example how to add global guards:
import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
@Module({
providers: [
{
provide: APP_GUARD,
useClass: RolesGuard,
},
],
})
export class ApplicationModule {}
You can read more aboutit in the docs, in the section "Binding Guards"
https://docs.nestjs.com/guards
Well done Nest team !!!
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
I have to say, the way you have to configure global stuff is so weird, comparing to how nice other things are architected
as @br0wn suggested, it would be much better to have the top module have all global stuff
and all child modules just inherits it, like @wbhob suggested