npm package: @gecosuy/angular-auth
Description: Librería para el manejo de autenticación y permisos (basados en roles y funcionalidades) de la forma standard para aplicaciones de API REST de Gecos
Latest version: 21.0.0

# angular-auth

# Introducción

Librería para el manejo de autenticación y permisos (basados en roles y funcionalidades) de la forma standard para aplicaciones de API REST de Gecos.

[Aquí](https://drive.google.com/file/d/1vo78f3hF9H7lESQsrZRjrzT6EKACkCnc/view?usp=sharing) se puede ver el modelo de dominio.

Se cubre una realidad donde la aplicación podría ser multi-tenant y además podría ser multi-empresa dentro de cada tenant.

Se basa en los siguientes conceptos:

**Perfiles**  
Existen 3 tipos de perfiles de usuario:

-   Sistema: roles asociados a administración del sistema general (como ser CRUD de tenant, etc.)
-   Tenant: roles asociados a administración de un tenant (com oser CRUD de empresas, alta de usuarios para trabajar con las empresas, etc.)
-   Empresa: roles asociados a operar con las empresas (con una a la vez)

**Roles**  
Los roles son agrupadores de funcionalidades.  
Cada rol pertenece a un determinado perfil y solo uno.

**Funcionalidades**  
Las funcionalidades indican acciones sobre el sistema.  
Cada funcionalidad pertenece a un determinado perfil y puede estar agregada en varios roles (roles de ese mismo perfil).

**Usuarios**  
Cada usuario tiene un conjunto de roles.  
Además cada usuario puede tener un conjunto de funcionalidades asignadas propiamente para cada perfil.

# Uso

## Importación

Como primer paso se debe importar el `AuthModule` en el AppModule de la app cliente.

Luego se debe proveer la configuración al módulo por medio de un provider del estilo:

```typescript
{
    provide: ANGULAR_AUTH_CONFIG,
    useFactory: getAuthConfig
}
```

Teniendo definida la función `getAuthConfig` que debe retornar una función que retorne un objeto `AuthConfig`, ver mas detalle en la documentación de este objeto.

El módulo requiere un fetcheo de metadata de permisos en el load de la app (cuando el usuario esta logueado), para ello en la app cliente se debe definir una función a ejecutar en el load de la app (`APP_INITIALIZER` de Angular) de la siguiente forma:

```typescript
{
    provide: APP_INITIALIZER,
    useFactory: (auth: AuthService, permissions: PermissionService) => () => auth.isLoggedIn() ? permissions.init() : undefined,
    deps: [AuthService, PermissionService],
    multi: true
}
```

Por último, en el `AppRoutingModule` se debe llamar al `registerAppRoutingModule` de la siguiente forma para indicarle a la librería cuales son las rutas configuradas en la app para que luego se pueda tener disponible la consulta de permisos sobre las rutas:

```typescript
export class AppRoutingModule {
    constructor(private permission: PermissionService) {
        this.permission.registerAppRoutingModule(routes);
    }
}
```

## Uso de AuthService

Este service ofrece principalmente los siguientes servicios:

### login

Permite hacer el login de un usuario. Se puede llamar con usuario/contraseña o token. Cuando se pasa el token no se hace llamada al backend.

Cuando se llama sin pasar extra data entonces si el usuario tiene un solo "perfil" posible se loguea normalmente en servidor y se retorna undefined indicando la situación,
en cambio si el usuario tiene multiples "perfiles" posibles entonces se requiere seleccionar un tipo de perfil antes de loguearse, por lo que se requiere interaccion
del usuario y luego una segunda llamada pasando extra data. En este caso se retorna un `AuthLoginResponse` indicando los diferentes "perfiles" del usuario para que se
muestre una interfaz donde el usuario elija uno.

Cuando se llama pasando extra data conteniendo los parametros que determinan el perfil elegido entonces siempre se retorna undefined porque en estos casos ya se tiene
el "perfil" con el que se quiere loguear al usuario y el login en servidor debería realizarse correctamente.

En el caso que se retorna undefined porque no se debe elegir perfil entonces el usuario queda logueado y se emite valor en el Observable `loggedUser$`.

### logout

Realiza el logout, con algunas opciones que customizan el comportamiento:

-   excludeInformApi: determina si se debe informar o no al backend
-   excludeReload: indica si se debe recargar la pagina o no (se recarga en la url root '')
-   backUrl: indica la url a la que redireccionar luego de que el usuario se loguea de nuevo. Se coloca como queryParam en la url al hacer logout.

Se borra el token del `localStorage` y se emite valor `undefined` en el Observable `loggedUser$` indicando que ya no hay usuario logueado.

### loggedUser

Se expone un Obervable `loggedUser$` que emite valores cada vez que hay un cambio en el usuario logueado.
El valor es un objeto `AuthLoggedUser` con info del usuario, la info que puede ser extraida solamente del token.

Además se tiene un campo `loggedUser` que se puede consultar para obtener un snapshot del usuario logueado.

## Uso de PermissionService

Este es un Service para manejar el permisado.

Tiene métodos directas para determinar si el usuario logueado tiene un determinado rol o una determinada funcionalidad,
pero además tiene métodos para chequear permisos sobre módulos y rutas de la app, que es realizado tomando como base
también los roles y funcionaldiades del usuario, pero obteniendo los roles y/o funcionaldiades requeridas de la metadata
definida en las rutas de la app.
A continuación se describen las 3 formas en que se puede utilizar este service.

### Directo

Corresponde al uso directamente invocando sus métodos desde los puntos de código donde se requieran chequeos.
Básicamente se tienen funcionaldiades para chequear permisos para:

-   un determinado módulo
-   una determinada ruta en particular
-   un determinado permiso (rol o funcionalidad) en particular

### Guarda PermissionGuard

Otra forma de uso es mediante la guarda `PermissionGuard` adjuntada a rutas, indicando roles o funcionalidades requeridas.

Esta metadata en las rutas es definida en el campo 'data' que Angular ofrece para ello en la definición de las `Routes`.
Dentro de ese data se pueden definir los siguientes campos en las rutas:

-   `expectedProfiles`: define IDs de perfiles que el usuario debe cumplir para permitir la ruta
-   `expectedRoles`: define IDs de roles que el usuario debe cumplir para permitir la ruta
-   `expectedFuncionalities`: define IDs de funcionalidades que el usuario debe cumplir para permitir la ruta

Si se definen ambos campos, se considera un OR de las condiciones.

### Directiva \*hasPermission

Otra forma de uso es por medio de la directiva `*hasPermission` para condicionar elementos en los templates.
Básicamente su uso es idéntico al \*ngIf de Angular. En este caso se condiciona una porción de HTML a que el usuario tenga el permiso requerido.

## Uso del SendTokenInterceptor

Este es un interceptor para adjutnar el token en los header de todos los request enviados a la API.

Para configurarlo en la app se debe agregar el siguiente provider en el `AppModule`:

```typescript
{
    provide: HTTP_INTERCEPTORS,
    useClass: SendTokenInterceptor,
    multi: true
}
```