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'
}

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

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() {}
}

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

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

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

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>

5. Stackblitz demo implementation

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade