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 se controla quién puede acceder a nuestra aplicación y qué partes de sus datos puede ver o cambiar cada usuario.

Roles

Los roles son la forma en que App Builder organiza los permisos para una fuente de datos. Se pueden otorgar permisos de Lectura, Inserción, Actualización y Eliminación a un rol 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. Consulta Roles para obtener una explicación completa de qué es un rol, o Privilegios y permisos para saber cómo cada permiso afecta lo que un usuario puede ver y hacer.

Creemos un conjunto de roles para nuestra fuente de datos Northwinds que reflejen funciones de trabajo 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 un control preciso objeto por objeto.

Superusuario

Crea un rol de Superusuario siguiendo estos pasos:

  1. En App Workbench > Data Sources, selecciona la fuente Northwinds (Default).

  2. En la sección Business Logic Layer, haz clic en Roles. Se abre el diálogo Roles.

  3. Haz clic en + Superuser. 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

+ Superuser es un acelerador: en lugar de crear un rol y luego otorgar permisos de Lectura, Inserción, Actualización y Eliminación uno a uno, 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 + Role.

  2. En el campo Name, ingresa Read Only.

  3. En el campo Description, ingresa una descripción como View-only access to all Northwinds data.

  4. Haz clic en Save.

  5. Expande el acordeón Tables y haz clic en Grant Read para otorgar acceso de lectura al rol Solo lectura en cada tabla de una sola vez.

  6. Expande el acordeón Business Objects, luego haz clic en Grant Read para hacer lo mismo con cada objeto de negocio.

Consejo

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

  • Grant Full otorga cada permiso (Lectura, Inserción, Actualización y Eliminación) en cada tabla u objeto de negocio de una sola vez, y Grant Read otorga permiso de lectura de la misma manera.
  • Grant on Create otorga automáticamente un nuevo permiso a un rol cuando se crea una tabla u objeto de negocio nueva, para que no tengas que volver al diálogo Roles cada vez que crece tu modelo de datos.
  • Las casillas de verificación Default Permissions establecen qué permisos aplica Grant on Create automáticamente y qué permisos otorga Grant Default a tablas y objetos de negocio existentes.
  • Revoke All elimina cada permiso que tiene el rol en cada tabla u objeto de negocio existente de una sola vez.

Consulta Table and business object permissions para la referencia completa.

Operaciones

El rol de 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 + Role.

  2. En el campo Name, ingresa Operations.

  3. Haz clic en Save.

  4. Haz clic en el icono Pages en la fila Operations 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 Suppliers, Supplier, Shippers, Shipper, Products, Product y Categories, y otorga acceso completo (Read, Insert, Update y Delete) a todas ellas.

  6. Selecciona las páginas Home, Customers, Customer, Orders, Order, Employees y Employee, y otorga solo acceso de Read a todas ellas, ya que Operations necesita ver estos datos sin poder modificarlos.

HR

El rol HR gestiona los registros de empleados, sus asignaciones regionales y la estructura organizativa de la empresa. 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 + Permission 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. Al agregar un permiso de esta manera, se otorga acceso completo (Read, Insert, Update y Delete) por defecto.

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.

Utilizando el mismo acelerador del icono Pages que usaste 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 ni Parameter, para que Sales no tenga acceso a ellas.

Application Groups

Una vez que existen los roles, los permisos se vuelven restrictivos por defecto: un usuario solo obtiene los permisos del rol si sus grupos se lo otorgan. Como tu propia cuenta de usuario aún no está en ningún grupo, crear los roles anteriores te bloquearía el acceso a tu propia aplicación a menos que los conectes a usuarios reales. Consulta Cómo los roles afectan el acceso a la aplicación para entender por qué sucede esto.

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

  2. Haz clic en Create.

  3. En el campo Name, utiliza 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 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 los grupos de aplicación sobre los grupos normales cuando el propósito del 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 trasladan automáticamente a entornos ascendentes como QA y Production. Los grupos normales existen por entorno de App Builder y no se mueven con la aplicación. Consulta Usuarios y grupos para obtener más información sobre las diferencias.

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égatte a ti mismo al grupo Northwinds Superuser para no perder el 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 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 conjunto, Reach controla qué filas de ese objeto de datos puede ver o afectar un usuario en primer lugar. Reach se implementa a través del motor empresarial 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:

  • Regla de Reach: Una regla de negocio común, como las que creamos en Apéndice B, que determina cuáles segmentos de los datos puede acceder un usuario. Las reglas de Reach típicamente usan la función mvSQL who() para correlacionar al usuario actual con los datos que puede 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 cuál columna en ese objeto de datos corresponde al token de la regla de Reach, y, opcionalmente, cuál rol 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 cuál registro de empleado corresponde al usuario actualmente conectado. 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 de la cuenta.

  1. Vincula la fuente de datos Vinyl (Sealed) integrada a tu aplicación para poder 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 encuentra 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, encuentra la tabla Employee y abrela.

  2. Haz clic en + Column.

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

  4. Haz clic en Save.

  5. En App Workbench > Rules, encuentra la regla Employee (Source) y abrela.

  6. En la pestaña Tables, encuentra la columna UserID y selecciona su casilla de verificación para incluirla.

En lugar de escribir este valor manualmente, agreguemos un control para que pueda establecerse a través de la UI, de la misma manera que lo harías en un entorno real y de producción.

  1. En App Workbench > Pages, encuentra la página Employee y abrela.

  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 Key (Column) debe ser UserId y Title (Column) debe ser UserName.

  6. Haz clic en Next, 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 recomendadas

User_Read es uno de varios objetos de datos públicos que App Builder pone disponibles para usar en tus reglas. Consulta User_Read y Access to public data objects para aprender más.

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 Results en el panel Rule para confirmar que la regla devuelve una sola fila, que contiene la región del registro de empleado que seleccionaste anteriormente.

Por último, registremos esta regla Reach para que restrinja el objeto de negocio Employee (Source).

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

  2. En el panel Rule, haz clic en More > Edge Case. Se abre el diálogo Edge Case Settings.

  3. Haz clic en Reach. Se abre el diálogo Reach Registration.

  4. Haz clic en Create.

  5. En el campo Rule, selecciona Employee (Region Access).

  6. En el campo Binding Column, selecciona RegionID.

  7. Deja el campo Role en blanco por ahora, para que la restricción se aplique a todos los usuarios, incluyéndote a ti, mientras lo probamos. Asegúrate de que Active esté marcado.

  8. Haz clic en Save.

Visita la vista previa de la página Employees. 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 Role en el rol Sales que creamos anteriormente. De esta manera, solo los usuarios cuyos grupos les otorguen el rol Sales se ven restringidos por región, mientras que los usuarios con el rol Superuser conservan 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 Employee (Network) que construimos en Appendix C también consulta la tabla Employee, pero como es un objeto de negocio separado de Employee (Source), no se ve restringida por una regla Reach registrada solo en Employee (Source). 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.

Práctica: 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 Customer.

  1. Siguiendo los pasos utilizados anteriormente para la tabla Employee, agrega una columna RegionID a la tabla Customer, agrégala a la regla Customer (Source), y agrega un control de lista Region (obtenido de Region (List)) a la página emergente Customer. Usa el nuevo control para asignar una región a algunos registros de clientes.

  2. Crea una nueva regla Reach llamada Customer (Region Access), con Purpose establecido en Reach y Target establecido en Customer. En la pestaña Tables, haz clic en + Tables para agregar la tabla Employee, unida a Customer en RegionID.

  3. Reutiliza la misma Where clause y tipo de uso de columna Reach Token de la regla Employee (Region Access), esta vez seleccionando RegionID de la tabla Employee. Combinado con la unión, la regla ahora devuelve solo clientes que comparten una región con el empleado conectado actualmente.

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

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

Consejo

En App Workbench, navega a la pestaña Roles. Al seleccionar un rol de la cuadrícula se 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 están 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 compatibles y limitaciones, consulta Reach.

Block

El tipo de uso de columna Block evita que una fila se edite, se elimine o ambas cosas. A diferencia de los roles, que se aplican a un objeto de datos completo, y Reach, que controla la visibilidad de las filas, Block controla qué puede hacer un usuario en una fila que ya puede ver. Un objeto de datos solo puede utilizar una columna Block, y su valor determina la restricción:

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

Puedes agregar una columna Block en dos niveles diferentes, y el lugar donde la agregues determina hasta dónde llega la restricción. Si la agregas a una tabla en la capa de datos, la restricción se aplica globalmente, en todos los lugares donde se utilicen los datos de esa tabla en toda la aplicación. Si la agregas como expresión en un objeto de negocio en la capa de lógica, como haremos a continuación, la restricción se aplica solo donde se utiliza ese objeto de negocio específico.

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

Una vez que un pedido se envía, sus artículos de línea no deberían 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 ya una unión interna entre OrderDetail y Order en OrderID. Si no lo ha hecho, 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, BlockOption(EditAndDelete), BlockOption(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 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 deberían 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, BlockOption(EditAndDelete), BlockOption(None)), y establece su Column Usage Type en Block. Dado que ShippedDate ya pertenece a la tabla Order, esta vez no se requiere ninguna unión. 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 especializada 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 desactivar controles, de forma 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 a capability puede devolver diferentes valores para controlar el estado de un control vinculado:

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

Usaremos esto para desactivar el botón Crear en el panel Detalles del Pedido siempre que su pedido padre ya haya sido enviado, evitando que se agreguen nuevos artículos de línea a un envío que ya salió.

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

  2. En la pestaña Columnas, haz clic en + Columna. En el campo Columna o Expresión, 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 enlace 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 Crear en el panel Order Details ahora debería estar desactivado. Selecciona un pedido que no haya sido enviado y el botón debería ser clickeable de nuevo.

Momento de practicar: Ocultar en lugar de desactivar

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

Formato condicional

Los enlaces Block y de 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 Crear de un panel. Sin embargo, cualquier botón conectado a un evento personalizado, como los botones Quantity Plus y Quantity Minus que agregamos en el Apéndice B, evita ambos. Ni Block 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 que los usuarios cambien una Quantity que ya no debería ser editable.

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

Sin embargo, la columna ShippedDate pertenece a la tabla Order, no a OrderDetail, y el ejercicio de Block anterior solo la referenció dentro de una expresión en lugar de agregarla como columna por derecho propio. Dado que el botón Quantity Minus se encuentra en el panel Order Details, que se obtiene de OrderDetail (Source), primero agrega ShippedDate a esa regla para que esté disponible para el formato condicional.

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

  2. En la pestaña Tables, busca la tabla Order, ya unida durante el ejercicio de Block anterior, y selecciona la casilla para su columna ShippedDate.

  3. Haz clic en Guardar.

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

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

  6. Haz clic en More > Styles.

  7. Haz clic en + Conditional Formatting.

  8. En el campo Source Column, selecciona ShippedDate.

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

  10. En el campo State, selecciona Disabled.

  11. Haz clic en Guardar.

Visita la vista previa de la página Orders y selecciona un pedido enviado. El botón Quantity Minus ahora debería estar desactivado. Selecciona un pedido que no haya sido enviado y el botón debería ser clickeable de nuevo.

Momento de practicar: Ampliar 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 configurando su State en Hidden en lugar de Disabled, para que puedas ver cómo difieren estos dos estados. Una vez que un pedido se ha enviado, el botón debería desaparecer por completo en lugar de permanecer visible pero no funcional.

Continuar aprendiendo

Con 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 el Apéndice A para examinar más de cerca la capa de datos, el Apéndice B para la capa de negocios, o el Apéndice C para la capa de IU.

Para continuar aprendiendo sobre App Builder, visita Jitterbit University.