DEV Community

Raúl Julián López Caña
Raúl Julián López Caña

Posted on • Originally published at Medium on

Angular permissions based on roles | Part 2. Permissions for multiple resources

In the previous article, a roles and permits handler, a global service to consume the handler and a directive for easy use have been implemented.

In this article, we will focus on solving the problem of managing different permissions for each resource of the application.

For example, a USER can READ, and ORDER pizza, but can only READ orders.

Glossary:

  1. Define the model Permission
  2. Refactor(PermissionBase and its extended classes)
  3. Refactor(Service): isGranted now controls permissions and resources
  4. Refactor(Directive): now receives resource and permission as parameter
  5. Stackblitz demo

1. Define the model Permission

We need to define a new data structure that relates resources with permissions. For this, we will first define the permissions that the application will handle.

export enum Resource {
  PASTA = 'PASTA',
  PIZZA = 'PIZZA',
  BILL = 'BILL'
}
Enter fullscreen mode Exit fullscreen mode

Once the resources are established, we can define the permission’s structure:

import { Resource } from './resource';
import { PermissionType } from './permission-type';

export class Permission {
  public resource: Resource;
  public permissions: PermissionType[];

  constructor(resource: Resource, permissions: PermissionType[]) {
    this.resource = resource;
    this.permissions = permissions;
  }
}
Enter fullscreen mode Exit fullscreen mode

Each permission will handle a list of permissions for each resource and user.

2. Refactor(PermissionBase and its extended classes)

We will adapt the new PermissionBase class to handle the new permissions.

import { Permission } from '../permission';

export abstract class PermissionBase {
  public permissions: Permission[];

  constructor() {}
}
Enter fullscreen mode Exit fullscreen mode

Now, extended class permissions are defined for each resource:

import { PermissionType } from '../permission-type';
import { Resource } from '../resource';
import { PermissionBase } from './base.permissions';
import {Permission } from '../permission';

export class UserPermission extends PermissionBase {
  constructor() {
    super();
    this.permissions = [
      new Permission(Resource.BILL, [
        PermissionType.READ,
        PermissionType.ORDER
      ]),
      new Permission(Resource.PASTA, [
        PermissionType.READ,
        PermissionType.ORDER
      ]),
      new Permission(Resource.PIZZA, [
        PermissionType.READ,
        PermissionType.ORDER
      ])
    ];
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Refactor(Service): isGranted now controls permissions and resources

Let’s refactor!

isGranted(resource: Resource, permission: PermissionType) {
  for (const res of this.permissions.permissions) {
    if (resource == res.resource) {
      for (const perm of res.permissions) {
        if (perm == permission) {
          return true;
        }
      }
    }
  }
  return false;
}
Enter fullscreen mode Exit fullscreen mode

4. Refactor(Directive): now receives resource and permission as parameter

We adapt the directive so that it receives an Input parameter, composed of a resource and a type of permission.

@Input() set appIsGranted(permission: Array<string>) {  
  this.isGranted(  
    permission[0] as Resource,  
    permission[1] as PermissionType  
  );  
}

private isGranted(resource: Resource, permissionType: PermissionType) {
  if (this.permissionManagerS.isGranted(resource, permissionType)) {
    this.viewContainer.createEmbeddedView(this.templateRef);
  } else {
    this.viewContainer.clear();
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, we can easily use like:

<div *appIsGranted="['PIZZA', 'CREATE']">
  // This block will only be shown to granted users
</div>

<my-component *appIsGranted="['PASTA', 'DELETE']">
  // This component will only be shown to granted users
</my-component>
Enter fullscreen mode Exit fullscreen mode

5. Stackblitz demo implementation

rjlopez-angular-permissions-part2 - StackBlitz

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

SurveyJS custom survey software

JavaScript Form Builder UI Component

Generate dynamic JSON-driven forms directly in your JavaScript app (Angular, React, Vue.js, jQuery) with a fully customizable drag-and-drop form builder. Easily integrate with any backend system and retain full ownership over your data, with no user or form submission limits.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay