[ ] Regression
[ ] Bug report
[ x ] Feature request
[ x ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
At the moment @SetMetadata() only works with methods. It would be neat if it would work with controllers as well. Especially for CRUD functionality where we might want metadata set on a on the entire controller scope without having to mock every single method.
example
@SetMetadata('roles', ['admin', 'editor'])
@Crud(establishment)
@Controller('establishment'){
}
@SetMetadata()
works with controllers. I'd rather create an issue in the nestjsx
repo (perhaps, @Crud()
decorator is not compatible with this feature).
Thanks @kamilmysliwiec
I'll redirect the issue.
@kamilmysliwiec When you say it works with controllers, do you mean controller methods?
As pointed out here https://github.com/nestjsx/crud/issues/71, @SetMetadata
only seems to work in the scope of individual methods and not the entire controller.
When you say it works with controllers, do you mean controller methods?
I meant that it works with controllers. Controller metadata is different than this one registered on top of methods (has to be reflected using reflector.getClass()
not reflector.getHandler()
).
Hey people as @kamilmysliwiec says and for anyone faced this issue. I succeed by doing this:
// Crud Controller
@UseGuards(AuthGuard(), RoleGuard)
@Roles(["admin"]) // Here the class decorator
@Crud({
model: { type: Product },
routes: { getManyBase: { decorators: [Roles(["seller"])] } }, // Here a method decorator
})
@Controller("products")
export class ProductsController implements CrudController<Product> {
constructor(public service: ProductsService) {}
Now you decorator look like this:
export const Roles = (roles: string[]) => ReflectMetadata("roles", roles);
Then you're Role guard could look like this:
@Injectable()
export class RoleGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const roles =
this.reflector.get<string[]>("roles", context.getHandler()) || [];
const rolesClass =
this.reflector.get<string[]>("roles", context.getClass()) || [];
const req = context.switchToHttp().getRequest();
if (!roles.length && !rolesClass.length) {
return true;
}
const allRoles = [...roles, ...rolesClass];
const user: User = req.user;
if (!user) {
throw new InternalServerErrorException(
"Cannot verify user authorization",
);
}
if (!user.roles.some(role => allRoles.includes(role.name))) {
throw new UnauthorizedException("You have not enough permission");
}
return true;
}
}
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
I meant that it works with controllers. Controller metadata is different than this one registered on top of methods (has to be reflected using
reflector.getClass()
notreflector.getHandler()
).