I need to secure a controller route using Guards, including IsAuthentifiedGuard, HasRoleGuard, and IsSafeGuard. I want the route to be accessible if at least one of these conditions is met:
- IsAuthentifiedGuard and HasRoleGuard pass
- IsSafeGuard passes
For example, the user should have access if authenticated AND has the necessary role, or if the call is considered "safe."
This is my OrGuard implementation:
@Injectable()
export class OrGuard implements CanActivate {
constructor(private readonly orGuards: CanActivate[][]) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const orGuardsPromises = await Promise.all(
this.orGuards.map(async andGuards => {
const andGuardPromises = await Promise.all(
andGuards.map(async guard => {
return guard.canActivate(context)
}),
)
return andGuardPromises.every(canActivate => canActivate === true)
}),
)
return orGuardsPromises.some(canActivate => canActivate === true)
}
}
And here's how it is applied in my controller:
@Controller('my_route')
export class MyController {
@Post('/')
@UseGuards(new OrGuard([[new IsAuthentifiedGuard(), new HasRoleGuard()], [new IsSafeGuard()]]))
async myRoute() {}
}
The issue arises when guards require dependencies like ConfigService.
Another approach could be:
@UseGuards(OrGuard)
@SetMetadata('orGuards', [[IsAuthentifiedGuard, HasRoleGuard], [IsSafeGuard]])
But I am struggling to instantiate these guards within OrGuard with all their required dependencies. Any suggestions?