Manager de Roles & Usuarios: Integración con Back-End

Funcionalidad 

A continuación presentamos como integrarse con el backend de Roles&Usuarios así como su librería que engloba una serie de funcionalidades que podrían ser útiles a lo largo del desarrollo de microservicios que necesiten hacer uso del lo configurado en el módulo de Roles y Usuarios.

Esta librería ayuda al usuario a simplificar su código además de ahorrar tiempo de programación que se suele invertir en funcionalidades frecuentes con la administración de roles y usuarios. De este modo, mediante a la importación de esta librería externa, se proporcionan al usuario dichas funcionalidades implementadas en la aplicación.

Alternativas

Esta guía de uso está pensada para la integración directamente con el back-end usando las interfaces que la solución nos aporta para facilitar este propósito. Esencialmente se dan dos alternativas de integración que se verán a continuación.

Altair

Se trata de un cliente para GraphQL que nos facilita el uso de las peticiones a través de la documentación. Con la facilidad de un buscador y un simple click se pueden ir cargando los datos de las peticiones para que solo necesiten ser modificadas, sin necesidad de hacerlas manualmente.

Es la solución que nosotros recomendamos accesible a través del siguiente enlace (en desarrollo): https://dev.architecture.onesait.com/multi-user-roles/altair.

Playground

Se trata de un cliente algo más básico que Altair. Incluye también la documentación para consultar las operaciones que se pueden realizar pero no nos facilita de igual forma su uso. Toda operación realizable con Altair puede hacerse también con esta alternativa.

El enlace para acceder en desarrollo es el siguiente: https://dev.architecture.onesait.com/multi-user-roles/gui

Integración usando Altair

En la siguiente imagen se explican para que sirvan los diferentes iconos que aparecen en la interfaz de Altair.

Configuración previa

Las peticiones que se realizan en el módulo de roles y usuarios han de hacerse autenticados contra Keycloak, para ello es necesario obtener un token JWT y usarlo en la cabecera 'Authorization' de las peticiones GraphQL que se vayan a hacer. Otra forma de hacerlo es creando un script que se lance antes de la petición usando la opción "Pre-request Editor" que nos facilita Altair. Se adjunta ejemplo en la siguiente plantilla:

Plantilla de ejemplo de script

Plantilla de ejemplo de script

const nowInSeconds = () => Date.now() / 1000; const tokenExpiry = localStorage.getItem("token_expiry") || 0; if (nowInSeconds() >= Number(tokenExpiry)) { // If the token expiry time has passed, fetch a new token from your auth server again (take note of the await) const user_name = 'USUARIO_VALIDO_KEYCLOAK' const user_password = 'PASSWORD_USUARIO_VALIDO_KEYCLOAK' bodyString = 'grant_type=password&scope=openid&username='+user_name+'&password='+user_password const res2 = await altair.helpers.request('POST', 'https://dev.connectedassets.onesait.com/auth/realms/onesaitplatform/protocol/openid-connect/token',{ 'body': bodyString, headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization': 'Basic CODIFICACION_BASE_64_CLIENTID_Y_SECRETID' } }); const access_token=res2['access_token'] localStorage.setItem("token", access_token); localStorage.setItem("token_expiry", nowInSeconds() + res2["expires_in"]); } // Retrieve the token from localStorage const token = localStorage.getItem("token"); altair.helpers.setEnvironment('access_token', token);

 

Como podemos observar hay algunas variables a rellenar, que son:

  • USUARIO_VALIDO_KEYCLOAK: usuario válido en Keycloak. Ejemplo: transversal

  • PASSWORD_USUARIO_VALIDO_KEYCLOAK: contraseña del usuario. Ejemplo: ***********

  • CODIFICACION_BASE_64_CLIENTID_Y_SECRETID: clientId:secretId del Realm de Keycloak codificadios en Base64. Cadena válida: VXNlclJvbGU6b25lc2FpdHBsYXRmb3Jt

Y por último añadir la cabecera usando la variable en la que guardamos el token JWT con el script anterior:

Hay que tener en cuenta también que en la primera ejecución de Altair es posible que haya definida una variable 'undefined'. Es necesario eliminarla para poder hacer peticiones.

Consideraciones

Cuando se usa la documentación con Altair es posible, a través de un simple click, desplazar la petición a la columna correspondiente como puede verse en la siguiente imagen.

En algunas peticiones como la anterior aparecen varios campos en rojo, que son campos que no están contemplados como devolución. Estos campos son necesarios eliminarlos para poder realizar la petición correctamente.

Tambien se puede observar que existe un argumento llamado input, y se trata de un argumento con varios campos. Si se hace click sobre él se puede ver más en detalle como se debe rellenar, como se puede observar en la siguiente imagen.

Una vez esté todo completado simplemente habría que lanzar la petición por medio de 'Send Request'.

Resumen de operaciones

En esta sección se comentarán las principales operaciones a buscar en la documentación para asi simplificar la integración con roles y usuarios.

Producto

Operación

Nombre de operación en GraphQL

Obtener todos los productos

products

Obtener producto

product

Crear producto

createProduct

Editar producto

updateProduct

Eliminar producto

deleteProduct

Proyecto

Operación

Nombre de operación en GraphQL

Obtener todos los proyectos

projects

Obtener proyecto

project

Crear proyecto

createProject

Editar proyecto

updateProject

Eliminar proyecto

deleteProject

Módulo

Operación

Nombre de operación en GraphQL

Obtener todos los módulos

Producto: modulesProduct

Proyecto: modulesProject

Crear módulo

Producto: createModuleProduct

Proyecto: createModuleProject

Editar módulo

updateModule

Obtener todos los submódulos

Producto: submodulesProduct

Proyecto: submodulesProject

Crear submódulo

Producto: createSubmoduleProduct

Proyecto: createSubmoduleProject

Eliminar módulo

deleteModule

Eliminar submódulo

deletesubmodule

Permisos

Operación

Nombre de operación en GraphQL

Obtener permisos

 

Crear permiso

createPermission

Editar permiso

updatePermission

Eliminar permiso

deletePermission

Rol

Operación

Nombre de operación en GraphQL

Obtener roles

Producto: rolesProduct

Proyecto: rolesProject

Obtener rol

role

Crear rol

Producto: createRoleProduct

Proyecto: createRoleProject

Editar rol

updateRole

Añadir permisos a un rol

roleAddPermissions

Editar permisos de un rol

roleSetPermissions

Borrar permisos de un rol

roleDeletePermissions

Eliminar rol

deleteRole

Usuarios

Operación

Nombre de operación en GraphQL

Obtener usuarios

users

Obtener usuario

user

Crear usuario

createUser

Editar usuario

updateUser

Borrar usuario

deleteUser

Integración con la librería de permisos

Roles & Usuarios dispone de gestión de permisos sobre los roles, y es posible integrar una librería para autorizar las peticiones sobre los permisos asignados a determinados roles. Para ello se hace uso de la librería que interpreta el token JWT generado y obtiene y analiza los permisos  sobre el proyecto.

Actualmente la librería de permisos está en su versión más temprana: 0.0.1-SNAPSHOT. Para integrarla dentro de nuestras dependencias de maven simplemente habría que incluir lo siguiente:

Dependencia de maven

Dependencia de maven

 

<dependencies> ... <dependency> <groupId>com.minsait.onesait.architecture</groupId> <artifactId>onesait-multi-user-role-lib</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> ... </dependencies>

Uso de la librería

Se integra directamente con Spring Security a través de su anotación @PreAuthorize, a continuación se muestran los distintos usos implementados en la librería.

Método

Descripción

Ejemplo de uso

existsModule(String)

Verifica si el token contiene el módulo indicado

@PreAuthorize("existsModule('m_nombreModulo')")

existsAnyModule(String, String...)

Verifica si el token contiene alguno de los módulos indicados

@PreAuthorize("existsAnyModule('m_nombreModulo1','m_nombreModulo2')")

existsAllModules(String, String...)

Verifica que el token contenga todos los módulos indicados

@PreAuthorize("existsAllModules('m_nombreModulo1','m_nombreModulo2')")

existsSubmodule(String)

Verifica si el token contiene el submódulo indicado

@PreAuthorize("existsSubmodule('m_nombreModulo/m_nombreSubmodulo')")

existsAnySubmodule(String, String...)

Verifica si el token contiene alguno de los submódulos indicados

@PreAuthorize("existsAnySubmodule('m_nombreModulo1/m_nombreSubmodulo1','m_nombreModulo2/m_nombreSubmodulo2')")

existsAllModules(String, String...)

Verifica que el token contenga todos los módulos indicados

@PreAuthorize("existsAllSubmodules('m_nombreModulo1/m_nombreSubmodulo1','m_nombreModulo2/m_nombreSubmodulo2')")

hasRootPermission(String)

Verifica que el token contenga el permiso a nivel general

@PreAuthorize("hasRootPermission('p_ADMIN')")

hasAnyRootPermission(String, String...)

Verifica que el token contenga alguno de los permisos indicados a nivel general

@PreAuthorize("hasAnyRootPermission('p_EDIT','p_VIEW')")

hasAllRootPermissions(String, String...)

Verifica que el token contenga alguno de los permisos indicados a nivel general

@PreAuthorize("hasAllRootPermissions('p_EDIT','p_VIEW')")

hasPathPermission(String)

Verifica que el token contenga el permiso indicado a nivel de módulo o submódulo

@PreAuthorize("hasPathPermission('m_Assets/m_Enumerations/p_VIEW')")

hasAnyPathPermissions(String, String...)

Verifica que el token contenga alguno de los permisos indicados a nivel de módulo o submódulo

@PreAuthorize("hasAnyPathPermissions('m_Assets/m_Enumerations/p_VIEW', 'm_Assets/m_Enumerations/p_EDIT')")

hasAllPathPermissions(String, String...)

Verifica que el token contenga todos los permisos indicados a nivel de módulo o submódulo

@PreAuthorize("hasAllPathPermissions('m_Assets/m_Enumerations/p_VIEW', 'm_Assets/m_Enumerations/p_EDIT')")

hasLevelPermission(String, String)

Verifica que el token contenga el permiso indicado dentro del módulo o submódulo indicado

@PreAuthorize("hasLevelPermission('m_Assets/m_Enumerations','p_VIEW')")

hasAnyLevelPermission(String, String, String...)

Verifica que el token contenga alguno de los permisos indicados dentro del módulo o submódulo indicado

@PreAuthorize("hasAnyLevelPermission('m_Assets/m_Enumerations','p_VIEW', 'p_EDIT')")

hasAllLevelPermissions(String, String, String...)

Verifica que el token contenga todos los permisos indicados dentro del módulo o submódulo indicado

@PreAuthorize("hasAllLevelPermission('m_Assets/m_Enumerations','p_VIEW', 'p_EDIT')")