More authorization checks

Some more checks to ensure that users can do only what they're allowed to.

To finish the topic of authorization, let's just add some more checks. Specifically:

  • A user can receive an update(), remove() or recover() only from himself

  • An order can be paid only by the user who owns it

  • A regular user can only soft delete his account

First, go to the UsersController and, in the three aforementioned routes, extract the user from the request and pass it along to the service method. Remember to also add this parameter to the namesake methods in the service.

@User() user: RequestUser,

Now, before going to the service, let's create the file auth -> util -> authorization.util. Here, we'll create a function to compare the id of the current user with a required id. If they're not the same, access will be denied. The purpose of this function is to verify if a user is acting on himself or on something which he owns.

export const compareUserId = (userId: number, requiredId: number) => {
  if (userId !== requiredId) {
    throw new ForbiddenException('Forbidden resource');
  }
};

Then, in the UsersService, at the start of those three methods, we'll simply check if the user is an ADMIN, in which case he should have unrestricted access. If not, we then compare his id.

if (currentUser.role !== Role.ADMIN) {
  compareUserId(currentUser.id, id);
}

In the case of making a payment, we have to check if the order is owned by the user who is paying it. In the payOrder() route in the PaymentsController, we shall perform the same step done just above. That is, to extract the user from the request and pass it along to the method call below, and also add this parameter to the method in the service.

In the PaymentsService, when fetching the order, also bring his customer in the relations to be able to make the comparison. Then, make it after checking if the order exists.

compareUserId(currentUser.id, order.customer.id);

Finally, let's enforce that a regular user can only soft delete his account. In the remove() method in the UsersService, we already check if the user is not an ADMIN. There, after comparing his id, check the deletion type.

if (!soft) {
  throw new ForbiddenException('Forbidden resource');
}

The main content of this module has been concluded. We'll now just see a last feature and a fix.

Commit - Validating user authorization inside service

Last updated