just when I thought I do understand how the modules work and starting to play with guards which leads me to this error in full
Error: Nest can't resolve dependencies of the CanModifyGuard (UsersService, ?). Please make sure that the argument TelevisionsService at index [1] is available in the UsersModule context.
Potential solutions:
- If TelevisionsService is a provider, is it part of the current UsersModule?
- If TelevisionsService is exported from a separate @Module, is that module imported within UsersModule?
@Module({
imports: [ /* the Module containing TelevisionsService */ ]
})
CanModifyGuard
was fine when the guard is using only TelevisionsService
, once I added the UsersService
and add the guard into the UsersController
The error above popped up.
Wonder if I can have another pair of eyes where I am setting this wrong?
app.module.ts
import { MiddlewareConsumer, Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose';
import { ConfigModule } from '@nestjs/config';
import { UsersModule } from './resources/users/users.module';
import { AuthModule } from './resources/auth/auth.module';
import { CommonModule } from './resources/common/common.module';
import { TelevisionsModule } from './resources/televisions/televisions.module';
import { CurrentUserMiddleware } from './common/middlewares/current-user.middleware';
@Module({
imports: [
ConfigModule.forRoot(),
MongooseModule.forRoot(process.env.DATABASE_URL),
UsersModule,
AuthModule,
CommonModule,
TelevisionsModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(CurrentUserMiddleware).forRoutes('*');
}
}
can-modify.guard.ts
import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { TelevisionsService } from '../../resources/televisions/televisions.service';
import { UsersService } from '../../resources/users/users.service';
@Injectable()
export class CanModifyGuard implements CanActivate {
constructor(
private readonly usersService: UsersService,
private readonly televisionsService: TelevisionsService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
//logics here
}
}
users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { MongooseModule } from '@nestjs/mongoose';
import { User, UserSchema } from './user.entity';
@Module({
imports: [
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
],
exports: [UsersService],
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
televisions.module.ts
import { Module } from '@nestjs/common';
import { TelevisionsController } from './televisions.controller';
import { TelevisionsService } from './televisions.service';
import { MongooseModule } from '@nestjs/mongoose';
import { Television, TelevisionSchema } from './television.entity';
import { UsersModule } from '../users/users.module';
@Module({
imports: [
MongooseModule.forFeature([
{ name: Television.name, schema: TelevisionSchema },
]),
UsersModule,
],
exports: [TelevisionsService],
controllers: [TelevisionsController],
providers: [TelevisionsService],
})
export class TelevisionsModule {}
auth.module.ts
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { UsersModule } from '../users/users.module';
import { ConfigModule } from '@nestjs/config';
import authConfig from './config/auth.config';
@Module({
imports: [UsersModule, ConfigModule.forFeature(authConfig)],
controllers: [AuthController],
providers: [AuthService],
})
export class AuthModule {}
common.module.ts (dont think this file would have any effect but just in case)
import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { AuthorizationRolesGuard } from '../../common/guards/authorization-roles.guard';
@Module({
providers: [
{
provide: APP_GUARD,
useClass: AuthorizationRolesGuard,
},
],
})
export class CommonModule {}
In order to use the guard, I added the guard to the specific route @UseGuards(CanModifyGuard)
and again, it is working fine when I added this guard into television controller but once I added it to user controller the error pops up.
As the error mentioned for potential solutions even though UsersModule
is not using any of the TelevisionsService
I still imported TelevisionsModule
into UsersModule
but no luck on getting this fix...and instead I would get another error and said potential cause A circular dependency between modules. Use forwardRef() to avoid it.
I read the doc about it and also tried using forwardRef()
but still didn't fix it. I might have put the forwardRef()
in the wrong place because I am not sure where I should use it.
Thank you in advance for any suggestions or advices.
CodePudding user response:
If I'm understanding your set up correctly, you have a circular dependency on the modules, so you need to forwardRef
the imports for those. Using these modules should fix your issue:
user.module.ts
@Module({
imports: [
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
forwardRef(() => TelvisionsModule),
],
exports: [UsersService],
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
televisons.module.ts
@Module({
imports: [
MongooseModule.forFeature([
{ name: Television.name, schema: TelevisionSchema },
]),
forwardRef(() => UsersModule),
],
exports: [TelevisionsService],
controllers: [TelevisionsController],
providers: [TelevisionsService],
})
export class TelevisionsModule {}