Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to inject component into global guards,filters,pipes and interceptors? #244

Closed
mkzaker opened this issue Nov 14, 2017 · 16 comments
Closed

Comments

@mkzaker
Copy link

mkzaker commented Nov 14, 2017

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) {
      }
}
@adrien2p
Copy link

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

@wbhob
Copy link
Contributor

wbhob commented Nov 14, 2017

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.

@m-yazdani
Copy link

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.

@kamilmysliwiec
Copy link
Member

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'. 🙂

@michaelfreund
Copy link

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?

@kamilmysliwiec
Copy link
Member

@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.

@michaelfreund
Copy link

michaelfreund commented Nov 26, 2017

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.

@michaelfreund
Copy link

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.

@br0wn
Copy link

br0wn commented Dec 13, 2017

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?

@wbhob
Copy link
Contributor

wbhob commented Dec 13, 2017

Why not make everything global? Have providers available to all child modules? That way you can use guards and interceptors as providers

@wbhob
Copy link
Contributor

wbhob commented Dec 13, 2017

That would require some rearchitecting but I think this is a feature people generally want.

@myflowpl
Copy link

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

@myflowpl
Copy link

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

@ferenc-radius
Copy link

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(Reflector);
app.useGlobalGuards(new AuthGuard(reflector));

@myflowpl
Copy link

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 !!!

@lock
Copy link

lock bot commented Sep 24, 2019

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.

@lock lock bot locked as resolved and limited conversation to collaborators Sep 24, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

9 participants