I'm trying to come up with a somewhat reusable guard and it looks like I need to pass a string param to a guard. Is it achievable in nestjs?
We use NestJs interceptors and guards daily, and most often we do not need to wrap them into factories, but every once in a while we need to pass an argument statically to them when we decorate some controller or some controller’s method. Let’s say that we need to send some metrics, KPI, to track usage of our app.
So that means there most be @Body on event function that would need this form of Authoriztion. The only ways possible to pass data from a Guard to a Controller is to either attach the data to a field on the request or to use some sort of metadata reflection, which may become more challenging than it is worth.
It is best practice to validate the correctness of any data sent into a web application. To automatically validate incoming requests, Nest provides several pipes available right out-of-the-box: The ValidationPipe makes use of the powerful class-validator package and its declarative validation decorators.
The guard is there to return true or false (or an async variant of it) so that the system knows whether or not to continue the request or return an error code. > And in your controller you could then pull req.myData ...
It sounds like you are looking to use a mixin
, a function that returns a class. I'm not sure what kind of parameter you're passing, but the idea is
export const RoleGuard = (role: string) => {
class RoleGuardMixin implements CanActivate {
canActivate(context: ExecutionContext) {
// do something with context and role
return true;
}
}
const guard = mixin(RoleGuardMixin);
return guard;
}
mixin
as a function is imported from @nestjs/common
and is a wrapper function that applies the @Injectable()
decorator to the class
Now to use the guard, you need to do something like @UseGuards(RoleGuard('admin'))
It seems impossible to use mixin in Guard in NestJs. It will throw Exported variable 'RoleGuard' has or is using private name 'RoleGuardMixin'.
Actually, you may use setMetadata to pass in the parameters one by one, then get it from the Guard using reflector from from '@nestjs/core'.
@Injectable()
export class RoleGuard implements CanActivate {
constructor(
private reflector: Reflector,
) {}
canActivate(context: ExecutionContext) {
const roleName = this.reflector.get<string>('roleName', context.getHandler());
return true;
}
}
@Get()
@SetMetadata('roleName', 'developer')
async testRoleGuard() {
return true;
}
Or you may define a decorator to pass the parameter in.
export const RoleName = (roleName: string) => SetMetadata('roleName', roleName);
@Get()
@RoleName('developer')
async testRoleGuard() {
return true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With