Saltar al contenido

Introducción a App Builder - Apéndice D: Seguridad en App Builder (Avanzado)

Este es el cuarto y último apéndice de la serie de tutoriales Introducción a App Builder. Estos apéndices complementan las lecciones de la serie y proporcionan información más detallada sobre los conceptos presentados.

En esta lección, exploraremos la capa de seguridad de App Builder, el área donde controlamos quién puede acceder a nuestra aplicación y qué partes de sus datos cada usuario puede ver o cambiar.

Roles

Los roles son la forma en que App Builder organiza los permisos para una fuente de datos. Se puede otorgar a un rol permisos de Lectura, Inserción, Actualización y Eliminación en una tabla u objeto de negocio, y los usuarios obtienen sus roles indirectamente, a través de la pertenencia a uno o más grupos de seguridad. Los grupos organizan usuarios; los roles organizan permisos. Para una explicación detallada de cómo cada permiso afecta lo que un usuario puede ver y hacer, consulta Privilegios y permisos.

Creemos un conjunto de roles para nuestra fuente de datos Northwinds que reflejen funciones laborales comunes en una empresa: Superusuario, Solo lectura, Operaciones, Recursos Humanos y Ventas. Cada uno introduce una forma diferente de otorgar permisos, desde aceleradores amplios hasta control preciso, objeto por objeto.

Superusuario

Crea un rol de Superusuario siguiendo estos pasos:

  1. En App Workbench > Fuentes de datos, selecciona la fuente Northwinds (Default).

  2. En la sección Capa de lógica de negocio, haz clic en Roles. Se abre el diálogo Roles.

  3. Haz clic en + Superusuario. App Builder crea automáticamente un rol llamado Superusuario con permisos completos en cada tabla y objeto de negocio de la fuente de datos.

Consejo

+ Superusuario es un acelerador: en lugar de crear un rol y luego otorgar Lectura, Inserción, Actualización y Eliminación uno a uno en cada objeto, crea el rol y otorga los cuatro permisos en todo de una sola vez.

Solo lectura

Ahora, crea un rol de Solo lectura siguiendo estos pasos:

  1. Haz clic en + Rol.

  2. En el campo Nombre, ingresa Solo lectura.

  3. En el campo Descripción, ingresa una descripción como Acceso de solo visualización a todos los datos de Northwinds.

  4. Haz clic en Guardar.

  5. Expande el acordeón Tablas y haz clic en Otorgar lectura para dar al rol Solo lectura acceso de lectura a cada tabla de una sola vez.

  6. Expande el acordeón Objetos de negocio, luego haz clic en Otorgar lectura para hacer lo mismo con cada objeto de negocio.

Consejo

El diálogo Roles ofrece varios aceleradores para otorgar permisos en masa:

  • Otorgar lectura, y los botones equivalentes para Inserción, Actualización y Eliminación, otorgan ese permiso a cada tabla u objeto de negocio de una sola vez.
  • Otorgar al crear otorga automáticamente un nuevo permiso a un rol cada vez que se crea una nueva tabla u objeto de negocio, para que no tengas que volver al diálogo Roles cada vez que tu modelo de datos crece.
  • Las casillas de verificación Permisos predeterminados establecen qué permisos aplica Otorgar al crear de forma predeterminada.

Operaciones

El rol Operaciones gestiona el inventario principal, las relaciones con proveedores y el cumplimiento de pedidos que mantienen el negocio funcionando entre bastidores. Supervisa categorías de productos, actualiza precios y niveles de existencias, gestiona contactos de proveedores y asigna transportistas para entregar pedidos de clientes.

  1. Haz clic en + Rol.

  2. En el campo Nombre, ingresa Operaciones.

  3. Haz clic en Guardar.

  4. Haz clic en el icono Páginas en la fila Operaciones para otra forma de acelerar la creación de roles: en lugar de otorgar permisos tabla por tabla, seleccionas qué páginas necesita un rol, y App Builder otorga los permisos subyacentes de los que dependen esas páginas.

  5. Selecciona las páginas Proveedores, Proveedor, Transportistas, Transportista, Productos, Producto y Categorías, y otorga acceso completo (Lectura, Inserción, Actualización y Eliminación) a todas ellas.

  6. Selecciona las páginas Inicio, Clientes, Cliente, Pedidos, Pedido, Empleados y Empleado, y otorga solo acceso de Lectura a todas ellas, ya que Operaciones necesita ver estos datos sin poder cambiarlos.

HR

El rol HR gestiona registros de empleados, sus asignaciones regionales y la estructura organizativa. Requiere acceso preciso y granular en lugar de permisos amplios a nivel de tabla o página.

  1. Haz clic en + Role.

  2. En el campo Name, ingresa HR.

  3. Haz clic en Save.

  4. En el panel del rol, haz clic en + Permissions para agregar objetos específicos uno a la vez.

  5. Agrega las reglas Employee (Source), Region (Source), Region (List) y Employee (Network) para otorgar acceso completo a HR en cada una. Agregar un permiso de esta manera otorga acceso completo (Read, Insert, Update y Delete) de forma predeterminada.

Práctica: Crear el rol Sales

El rol Sales necesita gestionar clientes y pedidos, ver datos de productos, categorías, transportistas y empleados, y acceder a los reportes que hemos creado. No debe tener acceso a datos administrativos como proveedores o la tabla de parámetros.

Usando el mismo acelerador de icono Pages que utilizaste para Operations, crea un rol Sales con el siguiente acceso:

  • Acceso completo a las páginas Customers, Customer, Orders y Order.
  • Acceso de Read a las páginas Products, Product, Categories, Shippers, Shipper, Employees, Employee y Order Total by Employee.

No selecciones las páginas Suppliers, Supplier o Parameter, para que Sales no tenga acceso a ellas.

Grupos de aplicación

Una vez que existen los roles, los permisos se vuelven restrictivos de forma predeterminada: un usuario solo obtiene los permisos de un rol si sus grupos le otorgan ese rol. Como tu cuenta de usuario aún no está en ningún grupo, crear los roles anteriores te bloquea de tu propia aplicación a menos que los conectes a usuarios reales.

  1. En la página Roles, haz clic en Application Groups.

  2. Haz clic en Create.

  3. En el campo Name, usa el patrón [App Name] [Role], por ejemplo Northwinds Superuser. En el campo Description, describe quién pertenece al grupo.

  4. Haz clic en el icono de marca de verificación para guardar.

  5. En el panel Roles, haz clic en Grant junto al rol Superuser para conectarlo al grupo de aplicación Northwinds Superuser.

Importante

Prefiere grupos de aplicación sobre grupos regulares cuando el propósito de un grupo es específico de una aplicación. Los grupos de aplicación se distribuyen junto con la aplicación como parte de una versión (LP), por lo que se llevan automáticamente a entornos ascendentes como QA y Production. Los grupos regulares existen por entorno de App Builder y no se mueven con la aplicación. Consulta Users and groups para obtener más información sobre la diferencia.

Práctica: Crear los grupos de aplicación restantes

Repite los pasos anteriores para crear un grupo de aplicación para cada uno de los otros roles que creaste: Read Only, Operations, HR y Sales.

Finalmente, agrégate a ti mismo al grupo Northwinds Superuser para no perder acceso a la aplicación que has estado construyendo:

  1. Navega a IDE > User Management > Groups.

  2. Encuentra el grupo Northwinds Superuser y haz clic en + Membership.

  3. Selecciona tu usuario.

  4. Haz clic en el icono de marca de verificación para guardar.

Ahora deberías tener permisos completos nuevamente ya que tu usuario pertenece al grupo Northwinds Superuser, que te otorga el rol Superuser.

Reach

Reach es la implementación de App Builder de seguridad a nivel de fila. Mientras que los roles que acabamos de crear controlan qué operaciones puede realizar un usuario en un objeto de datos en su conjunto, Reach controla qué filas de ese objeto de datos puede ver o afectar un usuario en primer lugar. Reach se implementa mediante el motor de negocio de App Builder, por lo que funciona de la misma manera independientemente de la base de datos subyacente.

Reach se construye a partir de tres conceptos:

  • Reach rule: Una regla de negocio regular, como las que creamos en Appendix B, que determina qué segmentos de los datos puede acceder un usuario. Las reglas de Reach típicamente usan la función mvSQL who() para correlacionar el usuario actual con los datos que se le permite ver.

  • Token de Reach: La columna única seleccionada en una regla de Reach, identificada por el tipo de uso de columna Reach Token, que identifica un segmento de datos, como una región o una unidad de negocio.

  • Registro de Reach: La configuración que adjunta una regla de Reach a un objeto de datos, especificando qué columna en ese objeto de datos corresponde al token de la regla de Reach y, opcionalmente, a qué rol se aplica la restricción.

Recuerda de la Lección 5 que agregamos una columna RegionID a nuestra tabla Employee, y asignamos algunos empleados a la East Coast Region y otros a la West Coast Region. Usaremos esa misma configuración para restringir la página Employees de modo que cada usuario solo vea empleados de su propia región.

Primero, necesitamos una forma de identificar qué registro de empleado corresponde al usuario que ha iniciado sesión actualmente. Usaremos el UserID del empleado en lugar de su nombre de usuario, ya que un nombre de usuario puede cambiar con el tiempo mientras que un UserID permanece constante durante la vida útil de la cuenta.

  1. Vincula la fuente de datos integrada Vinyl (Sealed) a tu aplicación para que puedas usar sus objetos de datos públicos: en App Workbench > Data Sources, haz clic en + Data Source. Se abre el diálogo Add a Source to your application.

  2. Selecciona Link to existing source, luego busca y selecciona Vinyl (Sealed) en la lista de fuentes de datos existentes.

  3. Haz clic en Link Sources.

  4. Haz clic en Done.

Ahora, demos a la tabla Employee una columna coincidente.

  1. En App Workbench > Tables, busca la tabla Employee y ábrela.

  2. Haz clic en + Column.

  3. Dale a la nueva columna el nombre UserID. En la sección Data Types, asegúrate de que el campo Logical tenga Unique ID seleccionado, lo que establece automáticamente el campo Physical en UUID.

  4. Haz clic en Save.

  5. En App Workbench > Rules, busca la regla Employee (Source) y ábrela.

  6. En la pestaña Tables, busca la columna UserID y selecciona su casilla para incluirla.

En lugar de escribir este valor manualmente, agreguemos un control para que se pueda establecer a través de la interfaz de usuario, de la misma manera que lo necesitarías en un entorno real de producción.

  1. En App Workbench > Pages, busca la página Employee y ábrela.

  2. En el panel Page Panel Layout, haz clic en Controls.

  3. Haz clic en + Control.

  4. En el menú Column, selecciona UserID y haz clic en Next.

  5. En Source, selecciona User_Read, el objeto de datos público expuesto por la fuente de datos Vinyl (Sealed) que vinculaste arriba. La selección de Key (Column) debe ser UserId y la de Title (Column) debe ser UserName.

  6. Haz clic en Next y luego en Finish.

  7. Navega a la página Employees, abre cualquier empleado ya asignado a una región, y usa el nuevo campo para seleccionar el usuario con el que inicias sesión en App Builder.

Lecturas adicionales

User_Read es uno de varios objetos de datos públicos que App Builder pone a tu disposición para usar en tus reglas. Consulta User_Read y Access to public data objects para obtener más información.

Ahora, creemos la regla de Reach.

  1. En App Workbench > Rules, haz clic en + Rule.

  2. En el campo Name, ingresa Employee (Region Access).

  3. En el campo Purpose, selecciona Reach.

  4. En el campo Target, selecciona Employee.

  5. Haz clic en Create.

  6. En la pestaña Tables, selecciona RegionID y UserID, además de la columna de clave principal EmployeeID que ya está seleccionada.

  7. En la pestaña Where, haz clic en + Where Clause. En el campo Left Expression, ingresa E.UserID, en el campo Operator, selecciona =, y en el campo Right Expression, ingresa who('userid'). Haz clic en Save.

  8. En la pestaña Columns, haz doble clic en la columna RegionID. En la sección Advanced, establece su Column Usage Type en Reach Token. Haz clic en Save.

  9. Haz clic en Resultados en el panel Regla para confirmar que la regla devuelve una sola fila, que contiene la región del registro de empleado que seleccionaste anteriormente.

Finalmente, registremos esta regla Reach para que restrinja el objeto de negocio Empleado (Origen).

  1. En App Workbench > Reglas, busca y abre la regla Empleado (Origen).

  2. En el panel Regla, haz clic en Reach. Se abre el diálogo Reach.

  3. Haz clic en + Reach.

  4. En el campo Regla Reach, selecciona Empleado (Acceso por Región).

  5. En el campo Columna de Enlace, selecciona RegionID.

  6. Deja el campo Rol en blanco por ahora, para que la restricción se aplique a todos los usuarios, incluido el tuyo, mientras lo probamos. Asegúrate de que Activo esté marcado.

  7. Haz clic en Guardar.

Visita la vista previa de la página Empleados. Ahora solo deberías ver empleados que compartan una región con el registro de empleado que seleccionaste, en lugar de la lista completa.

Nota

En una aplicación real, probablemente no querrías que esta restricción afecte a los administradores. Ahora que confirmaste que la regla funciona, edita el registro Reach nuevamente y establece su campo Rol en el rol Ventas que creamos anteriormente. De esta manera, solo los usuarios cuyos grupos les otorguen el rol Ventas se ven restringidos por región, mientras que los usuarios con el rol Superusuario mantienen visibilidad completa.

Nota

Registrar una regla Reach en un objeto de negocio solo restringe ese objeto específico, no todas las reglas construidas sobre su tabla subyacente. Por ejemplo, la regla Empleado (Red) que construimos en el Apéndice C también consulta la tabla Empleado, pero como es un objeto de negocio separado de Empleado (Origen), no se ve restringida por una regla Reach registrada solo en Empleado (Origen). Para restringir todas las reglas construidas sobre una tabla, registra la regla Reach a nivel de tabla en lugar de en un objeto de negocio individual.

Hora de practicar: Extiende el acceso por región a clientes

Los empleados no son los únicos datos de Northwinds que podrían beneficiarse del acceso basado en regiones. Apliquemos la misma restricción a la tabla Cliente.

  1. Siguiendo los pasos utilizados anteriormente para la tabla Empleado, agrega una columna RegionID a la tabla Cliente, agrégala a la regla Cliente (Origen), y agrega un control de lista Región (proveniente de Región (Lista)) a la página emergente Cliente. Usa el nuevo control para asignar una región a algunos registros de cliente.

  2. Crea una nueva regla Reach llamada Cliente (Acceso por Región), con Propósito establecido en Reach y Destino establecido en Cliente. En la pestaña Tablas, haz clic en + Tablas para agregar la tabla Empleado, unida a Cliente en RegionID.

  3. Reutiliza la misma cláusula Donde y tipo de uso de columna Token Reach de la regla Empleado (Acceso por Región), esta vez seleccionando RegionID de la tabla Empleado. Combinado con la unión, la regla ahora devuelve solo clientes que comparten una región con el empleado actualmente conectado.

  4. Registra la nueva regla en el objeto de negocio Cliente (Origen), esta vez vinculándola a la columna RegionID propia de la tabla Cliente.

  5. Visita la vista previa de la página Clientes para confirmar que solo son visibles los clientes de tu región.

Consejo

En App Workbench, navega a la pestaña Roles. Seleccionar un rol de la cuadrícula muestra su diagrama de página a la derecha; las páginas con seguridad a nivel de fila aplicada muestran un icono de mano, lo que facilita ver de un vistazo cuáles de las páginas de ese rol se ven restringidas por Reach.

Lecturas adicionales

Este ejemplo solo toca la superficie de lo que Reach puede hacer. Para una descripción completa de los conceptos de Reach, escenarios admitidos y limitaciones, consulta Reach.

Bloqueo

El tipo de uso de columna Bloqueo impide que una fila se edite, se elimine, o ambas. A diferencia de los Roles, que se aplican a un objeto de datos completo, y Reach, que controla la visibilidad de filas, Bloqueo controla lo que un usuario puede hacer con una fila que ya puede ver. Un objeto de datos solo puede usar una columna Bloqueo, y su valor determina la restricción:

Valor de celda Descripción
1 Impide la edición de esa fila.
2 Impide la eliminación de esa fila.
3 Impide tanto la edición como la eliminación de la fila.
Cualquier otro valor No impide nada.

Se puede agregar una columna Block en dos niveles diferentes, y el lugar donde se agregue determina el alcance de la restricción. Agregarla a una tabla en la capa de datos aplica la restricción globalmente, en todos los lugares donde se utilicen los datos de esa tabla en toda la aplicación. Agregarla como una expresión en un objeto de negocio en la capa de lógica, como haremos a continuación, aplica la restricción solo donde se utiliza ese objeto de negocio específico.

En lugar de devolver estos números directamente, también se puede utilizar la función mvSQL Block(), que acepta valores más legibles como None, Edit, Delete y EditAndDelete.

Una vez que se envía un pedido, sus artículos de línea no deben cambiar más. Bloqueemos la edición y eliminación de filas OrderDetail para cualquier pedido que ya tenga una ShippedDate.

  1. En App Workbench > Rules, busca y abre la regla OrderDetail (Source).

  2. En la pestaña Tables, haz clic en + Tables y agrega la tabla Order.

  3. En la pestaña Joins, App Builder debería haber creado automáticamente una combinación interna entre OrderDetail y Order en OrderID. Si no lo hizo, créala.

  4. En la pestaña Columns, haz clic en + Column. En el campo Column or Expression, ingresa IIF(O.ShippedDate IS NOT NULL, Block(EditAndDelete), Block(None)). En el campo Alias, ingresa Block.

  5. Haz clic en Save.

  6. Haz doble clic en la nueva columna Block. En la sección Advanced, establece su Column Usage Type en Block. Haz clic en Save.

Visita la vista previa de la página Orders y selecciona un pedido que ya tenga una ShippedDate. En su panel Order Details, los iconos de edición y eliminación ya no deberían aparecer para ninguna fila. Selecciona un pedido que aún no se haya enviado, y esos iconos deberían estar disponibles como de costumbre.

Hora de practicar: Bloquea el pedido en sí

Los artículos de línea no son los únicos registros que no deben cambiar después del envío. Aplica la misma lógica directamente a la regla Order (Source): agrega una columna Block con la expresión IIF(ShippedDate IS NOT NULL, Block(EditAndDelete), Block(None)), y establece su Column Usage Type en Block. Como ShippedDate ya pertenece a la tabla Order, no se requiere ninguna combinación esta vez. Prueba tus resultados en la vista previa de la página Orders: los pedidos enviados ya no deberían mostrar sus propios iconos de edición y eliminación.

Capability bindings

Los capability bindings son un tipo de vinculación especializado que vincula el estado funcional de un panel secundario a los datos de un panel principal u objeto de datos de página. Se pueden utilizar para ocultar o deshabilitar controles, de manera similar a Block, pero con una ventaja clave: los capability bindings también pueden afectar el botón Create de un panel. Esto es algo que Block no puede hacer, ya que ese botón existe independientemente de cualquier fila específica.

Una columna vinculada por capacidad puede devolver diferentes valores para controlar el estado de un control vinculado:

Valor de celda Descripción
1 Oculta el control.
2 Deshabilita el control, dejándolo visible pero inutilizable.
Cualquier otro valor Revierte al comportamiento predeterminado del control.

Usemos esto para deshabilitar el botón Create en el panel Order Details siempre que su pedido principal ya se haya enviado, evitando que se agreguen nuevos artículos de línea a un envío que ya se ha realizado.

  1. En App Workbench > Rules, busca y abre la regla Order (Source).

  2. En la pestaña Columns, haz clic en + Column. En el campo Column or Expression, ingresa IIF(ShippedDate IS NOT NULL, 2, 0). En el campo Alias, ingresa LockNewDetails.

  3. Haz clic en Guardar.

  4. Abre la página Orders y selecciona Action Drawer > Live Designer.

  5. Haz clic en el icono de columna de vinculación en el panel Order Details. Se abre el diálogo Binding Columns:

    Binding columns

  6. Haz clic en + Binding y establece el campo Type en Capability.

  7. En el campo Parent, selecciona LockNewDetails.

  8. En el campo Intrinsic Event, selecciona Insert.

  9. Haz clic en Guardar.

Visita la vista previa de la página Orders y selecciona un pedido enviado. El botón Create en el panel Order Details ahora debe estar deshabilitado. Selecciona un pedido que no haya sido enviado y el botón debe ser clickeable nuevamente.

Hora de practicar: Ocultar en lugar de deshabilitar

Los enlaces de capacidad admiten otros estados además de deshabilitar un control. Un valor de 1 oculta completamente un control en lugar de deshabilitarlo. Cambia la expresión LockNewDetails a IIF(ShippedDate IS NOT NULL, 1, 0) y prueba tus resultados: el botón Create en el panel Order Details ahora debe desaparecer completamente en los pedidos enviados, en lugar de permanecer visible pero inutilizable.

Formato condicional

Los enlaces de bloque y capacidad cubren las formas integradas en que los usuarios interactúan con un registro: los iconos de edición y eliminación, y el botón Create de un panel. Sin embargo, cualquier botón conectado a un evento personalizado, como los botones Quantity Plus y Quantity Minus que agregamos en Appendix B, omite ambos. Ni el enlace de bloque ni el Intrinsic Event de un enlace de capacidad se aplican a un evento personalizado, por lo que estos botones siguen funcionando incluso en pedidos enviados, permitiendo a los usuarios cambiar una Quantity que ya no debería ser editable.

El formato condicional te permite ocultar o deshabilitar un control según el valor de cualquier columna, independientemente del evento al que esté conectado. Usémoslo para deshabilitar el botón Quantity Minus una vez que se haya enviado un pedido.

  1. Abre la página Orders y selecciona Action Drawer > Live Designer.

  2. Selecciona el botón que ejecuta el evento Quantity Minus.

  3. Haz clic en More > Styles.

  4. Haz clic en + Conditional formatting.

  5. En el campo Source Column, selecciona ShippedDate.

  6. En el campo Operator, selecciona Is not Null.

  7. En el campo State, selecciona Disabled.

  8. Haz clic en Guardar.

Visita la vista previa de la página Orders y selecciona un pedido enviado. El botón Quantity Minus ahora debe estar deshabilitado. Selecciona un pedido que no haya sido enviado y el botón debe ser clickeable nuevamente.

Hora de practicar: Extender el formato condicional

Repite los pasos anteriores para el botón que ejecuta el evento Quantity Plus.

Luego, aplica la misma restricción al botón Delete Order Details en el panel Orders, esta vez estableciendo su State en Hidden en lugar de Disabled, para que puedas ver cómo difieren los dos estados. Una vez que se haya enviado un pedido, el botón debe desaparecer completamente en lugar de permanecer visible pero inutilizable.

Aprendizaje adicional

Esto concluye este análisis profundo de los detalles de la capa de seguridad de App Builder. Si aún no lo has hecho, consulta Appendix A para un análisis más detallado de la capa de datos, Appendix B para la capa de negocio, o Appendix C para la capa de interfaz de usuario.

Para continuar aprendiendo sobre App Builder, visita Jitterbit University.