Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use HasPermission in API controllers #2706

Open
dtslvr opened this issue Dec 2, 2023 · 9 comments
Open

Use HasPermission in API controllers #2706

dtslvr opened this issue Dec 2, 2023 · 9 comments
Assignees
Labels
enhancement New feature or request

Comments

@dtslvr
Copy link
Member

dtslvr commented Dec 2, 2023

With the groundwork of #2693 it is now possible to guard endpoints with the following code:

  @UseGuards(HasPermissionGuard)  // can be on the controller or handler
  @HasPermission('somePermissionKey') // on the handler

See comment by @underwater in #2693 (comment)

@dtslvr dtslvr added the enhancement New feature or request label Dec 2, 2023
@dtslvr
Copy link
Member Author

dtslvr commented Dec 2, 2023

@underwater are you interested in contributing that?

@underwater
Copy link
Contributor

Hi @dtslvr, I suppose you are referring to refactoring code that explicitly verifies permission in the controllers, with the usage of the guard / decorator. Yes, sure... I thought before starting though, to write a spec that is alongside the controller to allow me that the behavior around the controller is still the same ? I can do it for a simple controller like CacheController and make a p/r so you can see what describing, and give me your feedback.

@underwater
Copy link
Contributor

underwater commented Dec 3, 2023

good morning @dtslvr

Before starting, wanted your feedback on the below:

1 - I plan to register HasPermissionGuard globally (it won't impact any handlers that don't specifically request a specific permission)

2 - For controllers that impose the same permission on all handlers (example : admin.controller.ts), I could place the @hasPermission decorator at the class level,

3 - Conversely for those that have different permissions for each handler (tag.controller.ts), I can add @hasPermission at the handler level.

4 - for controllers that have checks for various other concerns in addition permission checking I plan to leave those parts of the code in place ... For example order.controller.ts, checks the order is valid and belongs to the same logged in user before allowing a delete.

// order.controller.ts
  @Delete(':id')
  @UseGuards(AuthGuard('jwt'))
  public async deleteOrder(@Param('id') id: string): Promise<OrderModel> {
    const order = await this.orderService.order({ id });

    if (
      !hasPermission(this.request.user.permissions, permissions.deleteOrder) ||
      !order ||
      order.userId !== this.request.user.id
    ) {
      throw new HttpException(
        getReasonPhrase(StatusCodes.FORBIDDEN),
        StatusCodes.FORBIDDEN
      );
    }

Do you agree with this approach ? If so, I can do the refactoring...

this will impact the below controllers

image

Your thoughts appreciated
P.S. I am travelling next 2 days, but will attend upon my return.

@dtslvr
Copy link
Member Author

dtslvr commented Dec 3, 2023

Thank you for this overview, @underwater.

  1. Okay, that makes it less verbose
  2. I would add @hasPermission explicitly for each endpoint, otherwise you need to think about the impact of all endpoints when something changes
  3. I think this is the way to go
  4. What do you think about this?
// order.controller.ts
  @Delete(':id')
  @HasPermission(permissions.deleteOrder)
  @UseGuards(AuthGuard('jwt'))
  public async deleteOrder(@Param('id') id: string): Promise<OrderModel> {
    const order = await this.orderService.order({ id });

    if (
      !order ||
      order.userId !== this.request.user.id
    ) {
      throw new HttpException(
        getReasonPhrase(StatusCodes.FORBIDDEN),
        StatusCodes.FORBIDDEN
      );
    }

@underwater
Copy link
Contributor

thanks for quick @dtslvr

(points 2,3) I agree about positioning of decorators, will do as you suggest.

(point 4) yes .... I wasn't clear in my initial message, but I intended to take out only that code relating to permission checking, and only keep the code relating to business rule and validation :-)

@underwater
Copy link
Contributor

@dtslvr just heads up that I will be absent for next 10 days due to medical reasons, and won't manage to work on this, but the permiter is clear, and I will do it upon my return.

@dtslvr
Copy link
Member Author

dtslvr commented Dec 6, 2023

Thanks for letting me know. Take care of yourself and get well soon, @underwater!

@underwater
Copy link
Contributor

Hi @dtslvr I am back, and will be looking at this over the weekend

@underwater
Copy link
Contributor

first stage of refactoring controllers to make use of @hasPermission() decorator Merged #2771

Still pending to do:

  • extending the Guard / Decorator to handle multiple permissions, to allow us complete the refactoring of those controllers that check multiple roles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants