nest-access-control icon indicating copy to clipboard operation
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.

Open Shiba-Kar opened this issue 3 years ago • 1 comments

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);
  }

Shiba-Kar avatar Mar 14 '22 11:03 Shiba-Kar

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 avatar Feb 25 '23 13:02 fasenderos

@fasenderos Thanks !!!

Shiba-Kar avatar Mar 31 '24 04:03 Shiba-Kar