Гнездо не может разрешить зависимости охранника, заключенного в декоратор - PullRequest
1 голос
/ 24 марта 2019

Я пытаюсь внедрить провайдера в охранник, который обернут в декоратор, но Nest не может разрешить зависимости, выдавая мне следующую ошибку:

[ExceptionHandler] Nest can't resolve dependencies of the SecuredGuard (Reflector, ?). Please make sure that the argument at index [1] is available in the SecuredGuard context.

Основная цельМой подход заключается в том, чтобы избежать использования двух отдельных декораторов, таких как:


@Controller()
export class AppController {

  @Get()
  @Secured('admin')
  @UseGuards(SecuredGuard)
  getHello(): string {
    return this.appService.getHello();
  }

}

И вместо этого вставить @UseGuards(SecuredGuard) в мой собственный декоратор @Secured('admin'), чтобы получилось так:

@Controller()
export class AppController {

  @Get()
  @Secured('admin')
  getHello(): string {
    return this.appService.getHello();
  }

}

Вот как я реализую свой пользовательский декоратор:

export function Secured(...roles: string[]){ 

    const setMetadata = ReflectMetadata('roles', roles)
    const setupGuard = UseGuards(SecuredGuard)

    return (target: any, key?: string, descriptor?: any) => {
        setMetadata(target, key, descriptor);
        setupGuard(target, key, descriptor);
    }

}

И это мой SecuredGuard, AuthService - это зависимость, которая не может быть разрешена:

@Injectable()
export class SecuredGuard implements CanActivate {

  constructor(
    private readonly _reflector: Reflector,
    private readonly _authService: AuthService
  ) { }

  async canActivate(context: ExecutionContext): Promise<boolean> {...}
}

Оба secured.guard.ts и secured.decorator.ts являются частью secured.module.ts

@Module({
    imports: [
        SecuredGuard,
        AuthModule
    ],
    exports: [
        SecuredGuard
    ],
    providers: [
        AuthService
    ]
})
export class SecuredModule {}

, который использует AuthService, экспортируемый из auth.module.ts

@Module({
  controllers: [
    AuthController
  ],
  providers: [
    AuthService
  ],
  imports: [
    EmailModule
  ],
  exports: [
    AuthService
  ]
})
export class AuthModule { }

И secured.module.ts импортируется app.module.ts

@Module({
  imports: [
    SecuredModule
  ],
  controllers: [
    AppController
  ],
  providers: [
    AppService
  ],
})
export class AppModule { }

Я не знаю, использую ли я соответствующий подход, или даже если это возможно, что я пытаюсь сделать, любые подсказки были бы действительно признательны!

1 Ответ

0 голосов
/ 24 марта 2019

В общем, ваше решение, кажется, работает, посмотрите следующий пример:

Edit custom-decorator-injection


Однако в объявлениях вашего модуля есть некоторые ошибки:

1) В вашем AppModule AuthService недоступен, поскольку AuthModule не импортируется напрямую или не экспортируется SecuredModule. Вот почему вы получаете ошибку.

2) Вам не нужно объявлять своих охранников в каком-либо модуле, они просто будут доступны по всему миру. Поместите только модули в ваш массив imports.

3) Вы предоставляете AuthService несколько раз, поэтому у вас будут разные его экземпляры. Вы должны предоставить его только один раз, а затем только export (или реэкспортировать) вашего провайдера, но не предоставлять его снова.

4) ReflectMetadata устарело в v6; используйте SetMetadata вместо.

...