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:
- Define the model Permission
- Refactor(PermissionBase and its extended classes)
- Refactor(Service): isGranted now controls permissions and resources
- Refactor(Directive): now receives resource and permission as parameter
- 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>
Top comments (0)