v1.7.21
Volver al índiceVersión anterior publicada: 1.7.20 (1 de octubre de 2026)
Backend: .NET 10 + IIS / Linux nginx
Frontend: Angular 21
Versión dedicada a la seguridad y al acceso a los datos. Cierra los hallazgos de una revisión de seguridad completa del framework y lleva OData al mismo nivel de permisos que el CRUD. En resumen:
enableCookieAuthenticationacepta un tercer valor,"signed": cookie firmada por el servidor, varias sesiones por usuario, cierre de sesión por sesión individual;- OData aplica los permisos de route y de columna, las restricciones de fila del usuario y escribe pasando por el CRUD del framework;
- los tokens personales permiten conectar Power BI, Excel y scripts a los endpoints OData;
- la opción "secure upload" de las columnas de upload vuelve a proteger los archivos de la columna;
- la modificación y la eliminación respetan la restricción por usuario también en el CRUD de la interfaz;
- los errores muestran al usuario un mensaje traducido con un código de seguimiento, los detalles técnicos solo al superadmin.
Los cambios en el esquema de los metadatos se aplican solos al arrancar. Las funcionalidades se verificaron con los tests end-to-end en SQL Server, MySQL, PostgreSQL y Oracle, en los tres modos de enableCookieAuthentication.
🔐 Autenticación y sesiones
- Tres modos.
enableCookieAuthenticationvalefalse,trueo"signed". Confalseel usuario es el que declara la cookie del navegador: solo para desarrollo. Al arrancar un mensaje[security]lo indica, el editor AppSettings lo describe y pide confirmación al guardar. Un valor no reconocido vale como"signed", con aviso en el log. "signed". El servidor firma la cookiek-user(HMAC-SHA256, caducidad dentro de la firma): una cookie modificada o caducada vale como ausente. El mismo usuario puede tener varias sesiones abiertas, cada una con su identificador.- Cierre de sesión y revocación. El cierre de sesión cierra solo la sesión desde la que se hace, incluidas las copias de la cookie. El cierre de sesión de un usuario hecho por un administrador, el restablecimiento y el cambio de contraseña cierran todas las sesiones de ese usuario en su empresa.
- Duración máxima. Con
signedSessionMaxLifetimeHours(24 por defecto,0= sin límite) una sesión firmada caduca a esa edad desde el inicio de sesión, aunque se use de forma continua. - Clave de firma.
cookie-signing-keyse genera en el primer arranque y se guarda enappsettings.json. Al arrancar el log muestra la huella de la clave (nunca la clave) y avisa si la clave no se ha guardado. - Llamadas verificadas en el servidor. Con
falsela cookie ya no lleva privilegios falsificados (administrador, rol, empresa): el usuario se vuelve a leer de la base de datos.
🔗 OData
- Permisos. Cada entity set requiere el permiso de lectura sobre la route. Una columna denegada al usuario y citada en
$select,$filter,$orderbyo$expandresponde 403; si no, vuelve vacía. - Restricciones de fila. La consulta parte del mismo SELECT que el CRUD con la restricción por usuario, rol o empresa, el filtro por defecto y la eliminación lógica.
$filter,$orderby,$skip,$topy$countse aplican fuera y solo pueden restringir:or 1 eq 1no amplía el resultado. $expand. Admitido hacia routes legibles sin restricciones de fila ni eliminación lógica; 403 en los demás casos.- Escrituras.
POST,PATCHyDELETEpasan porinsertRecord,updateRecordydeleteRecord: permisos, columnas no modificables, triggers, campos de registro, change log, workflows y eliminación lógica valen como desde la interfaz. Una fila oculta al usuario responde 404. - Multiempresa. La conexión de datos es la de la empresa del usuario, como en el CRUD.
- Descubrimiento.
/odata,/odata/$metadatay/odata/openapi.jsonrequieren la sesión. ConodataPublicMetadata=truevuelven a ser públicos; los datos siguen protegidos. - Tokens personales. Con
apiTokensEnabled=truecada usuario crea desde el menú de usuario ("Tokens de API") tokenswuic_pat_…con nombre, caducidad (90 días por defecto, máximoapiTokenMaxLifetimeDays) y permiso de solo lectura o también de escritura. Solo valen en/odata, con los permisos del propietario. Power BI y Excel los usan como contraseña con credenciales "Basic"; los scripts conAuthorization: Bearer. El token se ve una sola vez; el superadmin ve y revoca los de todos.
🛡️ Seguridad
Hardening best-effort en toda la superficie: controles sobre los valores que terminan en las consultas (ordenaciones, operadores, agregados, claves, filtros numéricos) alineados en los cuatro proveedores; rutas de upload y de informes confinadas en sus carpetas; funciones de administración (diseñador de informes, eliminación y scaffolding de informes, reordenación de columnas, reinicio, scaffold OData) reservadas al superadmin verificado en la base de datos; correos de los workflows solo de quien puede ejecutar el workflow; datos de ejemplo de las herramientas para asistentes de IA solo al superadmin y nunca con columnas de credenciales; protecciones sobre usuarios y roles ligadas a la tabla, no al nombre de la route; clave pública de la licencia incorporada en el paquete.
📎 Upload
- "Secure upload" por columna. Los archivos de una columna con
upload_securesolo se leen con una sesión válida y con la columna visible para el usuario, tanto desde/uploadcomo desde/api/UploadImage. Los archivos de las demás columnas siguen siendo públicos. Las columnas que guardan el archivo en la base de datos están protegidas por/api/UploadImage. - Nombres de archivo. Se aceptan los nombres con puntos internos (
factura-acme.com.pdf); siguen rechazándose los nombres con extensiones ejecutables por el servidor aunque estén en medio (foto.aspx.png).
🚦 Errores
Al usuario le llega un mensaje traducido con un código de seguimiento (botón "Copiar código" en el diálogo de error). El mismo código se registra con la pila completa en _error__logs. SQL, pilas y mensajes internos solo llegan al superadmin. Las traducciones de los nuevos mensajes de error se añaden solas al arrancar.
🐛 Correcciones destacadas
- Restricción por usuario en modificación y eliminación. El UPDATE y el DELETE del CRUD solo contenían la clave: conociendo el id, un usuario podía modificar la fila de otro. Ahora la fila debe estar entre las que el usuario ve; si no, 403
errors.auth.route_read_forbidden. - Filtro por defecto con filtros en OR. Con el operador OR el filtro por defecto de la route desaparecía y la grid mostraba las filas que debía ocultar. Ahora se mantiene en AND.
- Oracle. Booleanos escritos como 1/0 también en columnas con tipo UI booleano, en los filtros y en los parámetros de los procedimientos almacenados; funciones distinguidas de los procedimientos en el esquema correcto; OData sobre el esquema de datos incluso con el usuario
SYSTEM(antes, errores ORA-00942 intermitentes). - PostgreSQL y Oracle. La inserción con una clave identity no enviada por el cliente ya no falla; los informes aplican los permisos y los filtros del usuario como en SQL Server y MySQL.
- Primer arranque en IIS. La configuración inicial ya no devuelve un 500 tras una instalación correcta: las migraciones se completan al reiniciarse el worker.
- Spreadsheet y sincronización. Con un filtro activo, la modificación y la eliminación afectaban a la fila equivocada; una selección más allá de la página ya no alcanza los registros de las páginas siguientes; el guardado por lotes del kanban y la sincronización sin conexión solo reintentan lo que ha fallado.
- Menú. La barra aparece con las etiquetas ya traducidas, sin mostrar por un instante las claves.
📦 Paquetes actualizados
| Paquete | De | A |
|---|---|---|
WuicCore |
1.7.20 | 1.7.21 |
Wuic.Webcore |
1.7.20 | 1.7.21 |
WuicOData |
1.7.20 | 1.7.21 |
RuntimeEfCore |
1.7.20 | 1.7.21 |
Wuic.MySqlProvider |
1.7.20 | 1.7.21 |
Wuic.PostgresProvider |
1.7.20 | 1.7.21 |
Wuic.OracleProvider |
1.7.20 | 1.7.21 |
wuic-framework-lib (npm) |
1.7.20 | 1.7.21 |
🔧 Actualizaciones operativas recomendadas
- Modo de la cookie: en producción, configurar
enableCookieAuthenticationcomo"signed"(otrue);falsees solo para desarrollo. - Varias instancias detrás de un balanceador: copiar la misma
cookie-signing-keyen todas las instancias; con claves distintas una sesión solo vale en la instancia que la creó. Comprobar en el log que la huella coincide. - Clientes OData: los clientes que leían
$metadatasin sesión deben autenticarse, o configurarodataPublicMetadata=true. Las escrituras OData ahora ejecutan los triggers y el registro del CRUD y, en las routes con eliminación lógica, marcan el indicador en lugar de eliminar la fila. md_service_apply_default_filter: obsoleto. El filtro por defecto se aplica siempre, también vía OData.- Licencia: la sustitución de la huella de la máquina solo se configura con la variable de entorno
WUIC_LICENSE_MACHINE_FINGERPRINT; las claveslicense-machine-fingerprint-overrideylicense-public-key-pemdeappsettings.jsonse ignoran. - Tokens API: para conectar Power BI, Excel o scripts, configurar
apiTokensEnabled=true(y opcionalmenteapiTokenMaxLifetimeDays) desde el editor AppSettings.