Skip to main content

APP_USER_PERMISSIONS – Guía de uso

Este documento explica cómo recuperar los permisos del usuario para el módulo activo desde el storageMap usando la clave APP_USER_PERMISSIONS, disponible en cualquier Microfrontend Remoto.


tip

Los permisos de usuario (APP_USER_PERMISSIONS) representan los grants (permisos de acción) asignados al usuario en el ítem de menú que está navegando actualmente. Se actualizan automáticamente en cada cambio de ruta por el shell principal.

¿Cómo se puebla APP_USER_PERMISSIONS?

El shell principal (ContentLayoutComponent) es responsable de guardar esta información. Al detectar una navegación, busca en el árbol de menú el nodo cuyo path coincide con la ruta activa y persiste sus grants bajo la clave APP_USER_PERMISSIONS.

// Flujo interno del shell (solo referencia — no copiar en remotes)
// content-layout.component.ts → handleSavePermissionsByModule()
const grants = targetItem?.grants ?? null;
if (grants?.length) {
this.storageVm.setStorageMap('APP_USER_PERMISSIONS', grants);
}
// grants: IGrants[]

La estructura almacenada es un arreglo de objetos con la forma:

interface IGrants {
/** ID del permiso */
grantId: number;
/** Nombre del permiso */
grantName: string;
/** Identificador/valor del permiso (ej. 'CREATE', 'READ', 'DELETE') */
grantValue: string;
/** ID del rol asociado */
roleId: number;
/** Nombre del rol asociado */
roleName: string;
}

// Ejemplo de valor almacenado:
// [
// { grantId: 1, grantName: 'Crear', grantValue: 'CREATE', roleId: 10, roleName: 'ADMIN' },
// { grantId: 2, grantName: 'Leer', grantValue: 'READ', roleId: 10, roleName: 'ADMIN' },
// ]

📁 Importaciones necesarias

En tu componente o servicio importa AlpuraStorageViewModel desde la librería @alpura/commons.

// En tu componente.ts o servicio.ts
import { AlpuraStorageViewModel } from "@alpura/commons";

🧩 Ejemplo de uso | Recuperar todos los permisos del usuario

export class MyComponent implements OnInit {
/**
* Servicio de gestión de almacenamiento.
* Inyecta `AlpuraStorageViewModel` para controlar los tipos de almacenamiento
* de datos mediante localstorage, session storage, storage(map) y cookie.
*
* @readonly
* @type {AlpuraStorageViewModel}
*/
private readonly storageVm = inject(AlpuraStorageViewModel);

/**
* Ciclo de vida de Angular.
* Se invoca getStorageMap() con la clave 'APP_USER_PERMISSIONS' para obtener
* el arreglo de grants del usuario en el módulo activo.
*/
ngOnInit(): void {
const userPermissions = this.storageVm.getStorageMap('APP_USER_PERMISSIONS') as
| Array<{ grantId: number; grantName: string; grantValue: string; roleId: number; roleName: string }>
| null;

console.log('[PERMISSIONS]:', userPermissions);
// Ejemplo de resultado:
// [{ grantId: 1, grantName: 'Crear', grantValue: 'CREATE', roleId: 10, roleName: 'ADMIN' }]
}
}

🧩 Ejemplo de uso | Verificar si el usuario tiene un permiso específico

Los valores posibles de grantValue están definidos en el enum PermissionActionEnum:

Valor enumgrantValue
PermissionActionEnum.Create'CREATE'
PermissionActionEnum.Read'READ'
PermissionActionEnum.Edit'EDIT'
PermissionActionEnum.Delete'DELETE'
PermissionActionEnum.Approval'APPROVAL'
PermissionActionEnum.Generate'GENERATE'
PermissionActionEnum.All'ALL'
export class MyComponent implements OnInit {
/**
* @readonly
* @type {AlpuraStorageViewModel}
*/
private readonly storageVm = inject(AlpuraStorageViewModel);

/**
* Ciclo de vida de Angular.
* Se usa hasPermission() para verificar si el usuario posee una acción concreta.
*/
ngOnInit(): void {
const canCreate = this.hasPermission('CREATE');
const canDelete = this.hasPermission('DELETE');
}

/**
* Verifica si el usuario tiene un permiso (grantValue) específico dentro de `APP_USER_PERMISSIONS`.
*
* Origen de datos:
* - Lee el arreglo `APP_USER_PERMISSIONS` desde el `storageMap` (vía `AlpuraStorageViewModel`).
*
* Reglas:
* - Si `APP_USER_PERMISSIONS` no existe o está vacío, retorna `false`.
* - Si el arreglo contiene un grant con `grantValue === 'ALL'`, retorna `true` para cualquier acción.
* - La comparación es insensible a mayúsculas/minúsculas.
*
* @param {string} action Valor del permiso a verificar (ej. `'CREATE'`, `'DELETE'`).
* @returns {boolean} `true` si el usuario posee el permiso, `false` en caso contrario.
*
* @example
* const canEdit = this.hasPermission('EDIT');
* // canEdit => true | false
*/
public hasPermission(action: string): boolean {
const permissions = this.storageVm.getStorageMap('APP_USER_PERMISSIONS') as
| Array<{ grantValue: string }>
| null;

if (!permissions?.length) return false;

const normalizedAction = action.toUpperCase();

return permissions.some(
(p) =>
p.grantValue?.toUpperCase() === 'ALL' ||
p.grantValue?.toUpperCase() === normalizedAction
);
}
}

⚠️ Consideraciones importantes

PuntoDetalle
Momento de disponibilidadAPP_USER_PERMISSIONS se llena después de que el shell resuelve la ruta activa. Si lo lees en el constructor, puede estar vacío. Usa ngOnInit o espera a que el shell haya completado la navegación.
Scope del datoLos permisos cambian en cada navegación: corresponden al ítem de menú activo, no son permisos globales de toda la app.
Permisos globalesSi necesitas las acciones disponibles a nivel global de la aplicación, usa la clave APP_GLOBAL_PERMISSIONS en su lugar (contiene el enum PermissionActionEnum).
Sin grants en el menúSi el ítem de menú activo no tiene grants configurados, la clave APP_USER_PERMISSIONS no se actualiza y puede conservar el valor del módulo anterior o estar vacía.
Tipo de datoEl valor es Array<IGrants>. Siempre castea con seguridad antes de usar.

🚀 Resultado esperado

Esta implementación permite a los Microfrontends Remotos leer los permisos del usuario para el módulo activo y aplicar reglas de negocio como mostrar/ocultar botones de acción (Crear, Editar, Eliminar), habilitar flujos de aprobación o restringir vistas, sin realizar llamadas adicionales al backend.


📬 Soporte

Para dudas o mejoras, puedes contactar al equipo de arquitectura.