toondaey / nestjs-oauth2-server

A Nestjs wrapper for OAuth2 server.
MIT License
51 stars 15 forks source link

How do I inject dependencies into my model? #72

Open thalysonalexr opened 3 years ago

thalysonalexr commented 3 years ago

How do I inject dependencies into my model? I tried it with injectable, but it looks like he totally ignores it when deco with his model decorator!??

toondaey commented 3 years ago

Hello @thalysonalexr , can you provide code snippets? This will better help proffer a solution.

thalysonalexr commented 3 years ago

Okay, I have the following code:

@OAuth2Model()
@Injectable()
export class OAuth2ModelService implements RequestAuthenticationModel {
  constructor(private readonly configService: ConfigService) {}
}

as you can see, I'm passing the @ Injectable decorator so that the nest inject via constructor my dependency onConfigService. I would like to use some of the environment with this module, instead of using directly with process.env as I did when implementing ... When trying to use this way, something simply causes nest to ignore ... Is there any solution for me to can use the decorator of OAuth2Model in a nest provider?

Thanks for the feedback!

alitnk commented 2 years ago

Hey! having the same problem injecting Prisma service into the model service, any ideas?

thalysonalexr commented 2 years ago

Hey guys,

I think I would have to revise the lib and implement the solution. In my case I needed to inject a typeorm repository and use configService. So manually I used process.env and getRepository method.

helsonxiao commented 2 years ago

Hey guys,

I think I would have to revise the lib and implement the solution. In my case I needed to inject a typeorm repository and use configService. So manually I used process.env and getRepository method.

The problem is caused by nested modules. @OAuth2Model provider is got by reflector inside ModelProviderModule, thus we cannot import modules for it. I will try to fix it in the next week.

helsonxiao commented 2 years ago

Update: After digging into the codebase, I'm using this workaround.

import * as OAuth2Server from 'oauth2-server';
import { ServerOptions } from 'oauth2-server';
import {
  OAuth2ServerTokenGuard,
  OAuth2ServerAuthorizationGuard,
  OAuth2ServerAuthenticationGuard,
} from '@t00nday/nestjs-oauth2-server/dist/guards';
import { IOAuth2ServerModuleOptions } from '@t00nday/nestjs-oauth2-server/dist/interfaces';
import {
  OAUTH2_SERVER,
  OAUTH2_SERVER_MODEL_PROVIDER,
  OAUTH2_SERVER_OPTIONS_TOKEN,
} from '@t00nday/nestjs-oauth2-server/dist/oauth2-server.constants';

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from 'src/user/entities/user.entity';
import { OAuth2User } from './entities/oauth2-user.entity';
import { OAuth2Controller } from './oauth2.controller';
import { OAuth2Model } from './oauth2.model';
import { OAuth2Service } from './oauth2.service';

@Module({
  imports: [
    TypeOrmModule.forFeature([
      OAuth2User,
      User,
    ]),
  ],
  providers: [
    OAuth2Service,
    {
      provide: OAUTH2_SERVER_OPTIONS_TOKEN,
      useValue: {},
    },
    {
      provide: OAUTH2_SERVER_MODEL_PROVIDER,
      useClass: OAuth2Model,
    },
    {
      provide: OAUTH2_SERVER,
      useFactory: (
        options: IOAuth2ServerModuleOptions,
        model: ServerOptions['model'],
      ): OAuth2Server =>
        new OAuth2Server(Object.assign({}, options, { model })),
      inject: [OAUTH2_SERVER_OPTIONS_TOKEN, OAUTH2_SERVER_MODEL_PROVIDER],
    },
    OAuth2ServerTokenGuard,
    OAuth2ServerAuthorizationGuard,
    OAuth2ServerAuthenticationGuard,
  ],
  controllers: [OAuth2Controller],
})
export class OAuth2Module {}

Now, OAuth2Service is injectable in OAuth2Model.

Also, OAuth2ServerModule is no more needed in your app.module.ts because providers have been already imported above.

// just remove this line!
import { OAuth2ServerModule } from '@t00nday/nestjs-oauth2-server';
helsonxiao commented 2 years ago

I'd like to propose a new but breaking API for this feature.

Update: This is available on npm now. Just install it by npm install @boyuai/nestjs-oauth2-server.

How do we use it?

import { Module } from '@nestjs/common';
import { OAuth2ServerModule } from '@boyuai/nestjs-oauth2-server';
import { OAuth2Controller } from './oauth2.controller';
import { OAuth2ServiceModule } from './oauth2-service.module';
import { OAuth2Model } from './oauth2.model';

@Module({
  imports: [
    OAuth2ServiceModule,
    OAuth2ServerModule.forRoot({
      imports: [OAuth2ServiceModule], // import anything you want to use in modelClass
      modelClass: OAuth2Model,
    }),
  ],
  controllers: [OAuth2Controller],
})
export class OAuth2Module {}

And you have to implement your own OAuth2Model.

@Injectable() // We don't use `@OAuth2Model()` any more.
export class OAuth2Model
  implements RequestAuthenticationModel, AuthorizationCodeModel
{
  private readonly logger = new Logger(OAuth2Model.name);

  constructor(
    private readonly redisService: RedisService,
    private readonly oauth2Service: OAuth2Service,
  ) {}

  // ...
  // methods for oauth2 server
}