I'm trying to create a guard that takes parameters and also uses a global service (prismaService
).
The dependency injection works as expected for a normal guard, but to create a guard that accepts parameters I'm using mixins.
export const UserGuard = (table: Prisma.ModelName, field: string) => {
class RoleGuardMixin implements CanActivate {
constructor(prismaService: PrismaService) {}
async canActivate(context: ExecutionContext) {
const subject = await this.prismaService[table];
return true;
}
}
const guard = mixin(RoleGuardMixin);
return guard;
};
In this case the PrismaService isn't found (I believe because the mixin is a pure function that returns a class). Is there a way to get nestjs to inject PrismaService after the guard is called? Can services be injected into classes?
CodePudding user response:
you missed the @Injectable()
annotation:
export const UserGuard = (table: Prisma.ModelName, field: string) => {
@Injectable() // <<<<<<<
class RoleGuardMixin implements CanActivate {
constructor(private prismaService: PrismaService) {}
// ^ or 'public' or 'protected'
async canActivate(context: ExecutionContext) {
const subject = await this.prismaService[table];
return true;
}
}
const guard = mixin(RoleGuardMixin);
return guard;
};
or, using @Inject()
export const UserGuard = (table: Prisma.ModelName, field: string) => {
class RoleGuardMixin implements CanActivate {
constructor(@Inject(PrismaService) private prismaService: PrismaService) {}
async canActivate(context: ExecutionContext) {
const subject = await this.prismaService[table];
return true;
}
}
const guard = mixin(RoleGuardMixin);
return guard;
};
CodePudding user response:
Thanks to @Micael for the answer.
What is needed is to decorate the RoleGuardMixin
with the @Injectable
decorator.
export const UserGuard = (table: any, field: string) => {
@Injectable()
class RoleGuardMixin implements CanActivate {
constructor(public prismaService: PrismaService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const subject = this.prismaService[table].findUnique({
where: { id: request.params.id }
});
return request.user.id === subject[field];
}
const guard = mixin(RoleGuardMixin);
return guard;
};