Issue
I'm trying to create a guard factory in order to create a guard based on given params and ran into an issue.
I built the following factory
@Injectable()
export class GateKeeperFactory {
public static guards = []
static forRoute(allow: boolean) {
@Injectable()
class GateKeeperCustomGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
return allow
}
}
const result = GateKeeperCustomGuard
GateKeeperFactory.guards.push(result)
return result
}
}
and added the following to my app.module.ts
providers: [GateKeeperFactory, ...GateKeeperFactory.guards],
To test this I created the following controllers
@Controller('/test1')
export class Test1Controller {
@Get('1')
@UseGuards(GateKeeperFactory.forRoute(false))
test1() {
return { in: true }
}
@Get('2')
@UseGuards(GateKeeperFactory.forRoute(true))
test2() {
return { in: true }
}
}
@UseGuards(GateKeeperFactory.forRoute(false))
@Controller('/test2')
export class Test2Controller {
@Get('1')
test1() {
return { in: true }
}
}
The issue is that all 3 routes are either blocked or all 3 are unblocked
I can assume that the allow
param is shared between the guards for some reason I'm missing (I verified that 3 different guards are created)
Note 1:
according to the guide I know they offer a different approach of passing parameters to guards by using SetMetadata
which at this point I want to avoid
Note 2:
Trying to add a constructor to the guards and using them as instances led to the error: [ExceptionHandler] metatype is not a constructor
when loading the server
Solution
It sounds like what you're really looing for is what's called a mixin, a function that returns a class with a closure that allows the class to use the mixin's parameters. This is how Nest creates it's Passport AuthGuard()
, btw. To take from your example above and tweak it a bit, you'd do something like this:
import { CanActivate, ExecutionContext, mixin } from '@nestjs/common';
export function GateKeeper(allow: boolean) {
class GateKeeperCustomGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
return allow
}
}
return mixin(GateKeeperCustomGuard) as CanActivate;
}
And now you should be able to use the guard like @UseGuards(GateKeeper(true))
Answered By - Jay McDoniel
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.