
En el artículo anterior implementamos un manejador de roles y permisos, un servicio global para consumirlo y una directiva para usarlo con facilidad.
En este artículo nos centramos en gestionar permisos distintos para cada recurso de la aplicación.
Por ejemplo, un USER puede READ y ORDER pizza, pero solo puede READ pedidos.
Glosario:
- Definir el modelo
Permission - Refactorizar (
PermissionBasey sus clases hijas) - Refactorizar (servicio):
isGrantedahora controla permisos y recursos - Refactorizar (directiva): ahora recibe recurso y permiso como parámetros
- Demo en StackBlitz
1. Definir el modelo Permission
Necesitamos una estructura de datos que relacione recursos con permisos. Primero definimos los recursos que manejará la aplicación.
export enum Resource {
PASTA = 'PASTA',
PIZZA = 'PIZZA',
BILL = 'BILL'
}
Una vez definidos los recursos, definimos la estructura del permiso:
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;
}
}
Cada permiso agrupa una lista de acciones permitidas por recurso y usuario.
2. Refactorizar (PermissionBase y clases extendidas)
Adaptamos PermissionBase al nuevo modelo de permisos.
import { Permission } from '../permission';
export abstract class PermissionBase {
public permissions: Permission[];
constructor() {}
}
Ahora las clases hijas definen permisos por recurso:
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. Refactorizar (servicio): isGranted con recurso y permiso
¡Refactorizamos!
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. Refactorizar (directiva): recurso y permiso como parámetros
Adaptamos la directiva para recibir un Input compuesto por recurso y tipo de permiso.
@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();
}
}
Uso:
<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. Demo en StackBlitz
rjlopez-angular-permissions-part2 - StackBlitz
Publicado originalmente en dev.to.