nest-access-control
nest-access-control copied to clipboard
Have two roles ADMIN , USER . ADMIN can manipulate all the resources but the User can readAny and update only its own resources .How can I achieve this.
import { RolesBuilder } from "nest-access-control";
import { Role } from "@prisma/client";
export const roles: RolesBuilder = new RolesBuilder();
roles
.grant(Role.USER).createOwn('users').deleteOwn('users').readAny('users').updateOwn('users')
.grant(Role.ADMIN).extend(Role.USER).updateAny('users').deleteAny('users');
@UseRoles({ possession: 'any', action: 'update', resource: "users" })
@Patch(':id')
update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto, @UserRoles() userRoles: any) {
console.log(userRoles);
return this.userService.update(id, updateUserDto);
}
You have to change the possession to own so both ADMIN and USER can call the endpoint
@UseRoles({ possession: 'own', action: 'update', resource: "users" })
Then in the controller get the user that is making the request (usually with a decorator) and check if it is an ADMIN and update accordingly
## get-user-from-req.decorator.ts
export const @GetUserFromReq = createParamDecorator(
(param: string, ctx: ExecutionContext): User | Partial<User> => {
const request = ctx.switchToHttp().getRequest();
const { user } = request;
return param ? (user?.[param] as Partial<User>) : (user as User);
},
);
## users.controller.ts
@UseRoles({ possession: 'own', action: 'update', resource: "users" })
@Patch(':id')
update(
@Param('id') id: string,
@Body() updateUserDto: UpdateUserDto,
@UserRoles() userRoles: any,
@GetUserFromReq() user: User
) {
// check if the user that is making the request is ADMIN
const isAdmin = userRoles.includes(Role.ADMIN)
if (isAdmin) {
// If ADMIN update every user
return this.userService.update(id, updateUserDto);
}
// If NOT ADMIN update only itself
if (id !== user.id) throw new ForbiddenException()
return this.userService.update({id: user.id}, updateUserDto);
}
@fasenderos Thanks !!!