atls / nestjs

NestJS Custom Workshop
BSD 3-Clause "New" or "Revised" License
33 stars 8 forks source link

Адаптер `keto-grpc` #289

Closed Nelfimov closed 8 months ago

Nelfimov commented 9 months ago

С чем связан запрос на фичу?

Необходимо добавить адаптер и гард для использования keto-grpc-client

Расскажите как вы это себе видите

Definition of done (критерий готовности)

Тесты проходят, пакет предоставляет гард, есть кастомизация УРЛа запросов

Приложите пример реализаций

No response

Приложите материалы задачи

No response

Nelfimov commented 9 months ago

@SlumberyDude посмотри пожалуйста тест в @atls/grpc-keto - не могу понять почему падает

SlumberyDude commented 9 months ago

@Nelfimov Нашел вот тут похожий кейс, что глобальную константу нестовую не нужно экспортировать, если убрать guardProvider из экспортируемых переменных, то ошибки не будет. Ну или создать под гард отдельную свою константу, а не APP_GUARD хотя скорее всего это будет уже не то.

Наверное глобальный гард можно не экспортировать, потому что в доке написано, что они распространяются на все приложение. (вот непонятно, где это приложение заканчивается) https://docs.nestjs.com/guards и будут работать для всего приложения наверное

Global guards are used across the whole application, for every controller and every route handler. In terms of dependency injection, global guards registered from outside of any module

When using this approach to perform dependency injection for the guard, note that regardless of the module where this construction is employed, the guard is, in fact, global.

Nelfimov commented 9 months ago

@SlumberyDude столкнулся с другой проблемой - в интеграционном тесте KetoGuard не видит свою зависимость KetoReadClientService, хотя она поставляется модулем.

Воспроизведение: yarn test integration client-read.test

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

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

Сам тест находится тут: /packages/grpc-keto/integration/test

TorinAsakura commented 9 months ago

@SlumberyDude столкнулся с другой проблемой - в интеграционном тесте KetoGuard не видит свою зависимость KetoReadClientService, хотя она поставляется модулем.

Воспроизведение: yarn test integration client-read.test

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

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

Сам тест находится тут: /packages/grpc-keto/integration/test

пересобери ярн

Nelfimov commented 9 months ago

Снос yarn.lock и пересборка не помогли.

После этого повалились все тайпчеки по репе из-за нефиксированных версий.

TorinAsakura commented 9 months ago

@Nelfimov папку кеш, а не ярн лок

Nelfimov commented 9 months ago

не помогло

SlumberyDude commented 9 months ago

@Nelfimov Проблема в том, что из модуля KetoModule гард экспортируется в виде

{
    provide: KETO_GUARD,
    useFactory: (reflector: Reflector, ketoReadClient: KetoReadClientService) =>
      new KetoGuard(reflector, ketoReadClient),
    inject: [KETO_READ_CLIENT],
},

То есть он привязывается к токену-константе KETO_GUARD

А потом уже в контроллере клиент (у нас KetoIntegrationController) использует @UseGuards(KetoGuard) что не прокатывает потому что экспортируется не KetoGuard, а KETO_GUARD. Вот ищу как это обойти, пока что не могу загуглить как экспортированный в виде токена гард потом использовать в декораторе @UseGuards. Обычно эти экспортированные в виде токенов-констант провайдеры инжектят в другие провайдеры через @Inject(OTHER_PROVIDER_TOKEN) otherProvider: OtherProvider, но тут другой случай.

SlumberyDude commented 9 months ago

@Nelfimov Если явно добавить CheckServiceClient, KetoReadClientService, KetoGuard в список провайдеров в кето модуль, то вроде ошибка импорта чинится,

return {
      global: options?.global ?? true,
      module: KetoModule,
      providers: [...optionsProvider, ...exportsProvider, CheckServiceClient, KetoReadClientService, KetoGuard],
      exports: [...exportsProvider]
}

Другого способа пока что не нашел

Nelfimov commented 8 months ago

@SlumberyDude сделал рефактор кода, добавил много чего в провайдеры. Сейчас ошибка такая:

Nest can't resolve dependencies of the KetoCheckClientService (?). Please make sure that the argument dependency at index [0] is available in the KetoModule context.

Речь о вот этом провайдере:

export class KetoCheckClientService extends CheckServiceClient {
  constructor(@Inject(KETO_MODULE_OPTIONS) private readonly options: KetoModuleOptions) {
    super(options.read, options.credentials)
  }
}

И что странно, KETO_MODULE_OPTIONS он якобы не находит, хотя они есть в модуле:

export const createKetoOptionsProvider = (options: KetoModuleOptions): Provider[] => [
  {
    provide: KETO_MODULE_OPTIONS,
    useValue: options,
  },
]

Можешь плиз посмотреть?

SlumberyDude commented 8 months ago

@Nelfimov Исправил провайдеры на вот это

```ts export const createKetoExportsProvider = (): Provider[] => [ { provide: KETO_CHECK_CLIENT, // useClass: KetoCheckClientService, useFactory: (options: KetoModuleOptions) => new KetoCheckClientService(options), inject: [KETO_MODULE_OPTIONS] }, { provide: KETO_WRITE_NATIVE_CLIENT, // useClass: KetoWriteNativeClientService, useFactory: (options: KetoModuleOptions) => new KetoWriteNativeClientService(options), inject: [KETO_MODULE_OPTIONS] }, { provide: KETO_READ_CLIENT, // useClass: KetoReadClientService, useFactory: (checkClientService: KetoCheckClientService) => new KetoReadClientService(checkClientService), inject: [KETO_WRITE_NATIVE_CLIENT] }, { provide: KETO_WRITE_CLIENT, // useClass: KetoWriteClientService, useFactory: (ketoWriteNativeClientService: KetoWriteNativeClientService) => new KetoWriteClientService(ketoWriteNativeClientService), inject: [KETO_CHECK_CLIENT] }, { provide: KETO_GUARD, useFactory: (reflector: Reflector, ketoReadClient: KetoReadClientService) => new KetoGuard(reflector, ketoReadClient), inject: [KETO_READ_CLIENT], }, ] ```

Прокатило, чтобы yarn test integration grpc-keto перестал выдавать ошибки связанные с зависимостями, но в решении я не уверен.

Nelfimov commented 8 months ago

Теперь будто прошлись по кругу и вернулись обратно:

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

@Module({
  imports: [
    KetoModule.register({
      read: 'http://localhost:4466',
      write: 'http://localhost:4467',
    }),
  ],
  controllers: [KetoIntegrationController],
})
export class KetoIntegrationModule {}
@Injectable()
export class KetoGuard implements CanActivate {
  constructor(
    private readonly reflector: Reflector,
    @Inject(KETO_READ_CLIENT) private readonly ketoReadClient: KetoReadClientService
  ) {}
...
SlumberyDude commented 8 months ago

@Nelfimov Может действительно было правильно (как изначально было) сделать guard провайдер как-то вроде

{
    provide: APP_GUARD,
    useFactory: (reflector: Reflector, ketoReadClient: KetoReadClientService) =>
      new KetoGuard(reflector, ketoReadClient),
    inject: [KETO_READ_CLIENT],
  }

Чтобы сделать его глобальным. Тогда вроде его не нужно экспортировать, а только записать в провайдеры. И убрать @UseGuards(KetoGuard) из контроллера KetoIntegrationController (потому что по идее глобальный гард должен работать и так - то есть без декоратора).

Нужно проверить, будет ли такой глобальный гард работать.

Nelfimov commented 8 months ago

Проверю, однако цель у этого адаптера сделать локальный гард чтобы покрывать только часть контроллера.

SlumberyDude commented 8 months ago

@Nelfimov А как в прошлый раз получилось преодолеть ошибку, когда такая же была? Ты говоришь мы сделали круг.

Nelfimov commented 8 months ago

Решил проблему - гарды нельзя экспортировать, иначе они не увидят скоуп модуля куда импортируются. Поэтому просто убрал гард из экспортируемых провайдеров.

Тут подробнее: https://github.com/nestjs/nest/issues/3856#issuecomment-575925668

SlumberyDude commented 8 months ago

@Nelfimov А если их не экспортировать, то тогда как ими пользоваться?

Nelfimov commented 8 months ago

Брать напрямую из пакета и использовать в UseGuards