Ir al contenido

Seguridad

Zentto implementa un modelo de seguridad por capas que cubre autenticacion, autorizacion granular (RBAC), auditoria automatica y controles de precio/aprobacion.

1. POST /v1/auth/login { username, password }
2. API verifica credenciales contra sec.User (bcrypt en Node.js)
3. Si valido, genera JWT con claims del usuario
4. Cliente almacena JWT y lo envia en header Authorization

El token incluye los siguientes claims:

ClaimDescripcion
userIdID del usuario
usernameNombre de usuario
companyIdEmpresa activa
branchIdSucursal activa
isAdminFlag de administrador
rolesArray de roles asignados

La verificacion de passwords se realiza en Node.js usando bcrypt, no en SQL. La tabla sec.User almacena el hash bcrypt del password.

const isValid = await bcrypt.compare(plainPassword, user.PasswordHash);

El endpoint POST /v1/auth/refresh permite renovar el JWT sin re-autenticar, siempre que el token actual no haya expirado.

Todas las rutas bajo /v1/* (excepto /v1/auth/login) requieren JWT valido. El middleware de autenticacion verifica:

  1. Presencia del header Authorization: Bearer <token>
  2. Validez del JWT (firma + expiracion)
  3. Existencia del usuario en BD

El sistema RBAC se basa en tres tablas principales:

sec.Permission -- Catalogo de permisos (ModuleCode.ActionCode)
sec.RolePermission -- Permisos asignados a cada rol
sec.UserPermissionOverride -- Overrides especificos por usuario

Cada permiso sigue el formato {ModuleCode}.{ActionCode}. El catalogo cubre 15 modulos con 8 acciones cada uno:

ModuleCodeModulo
ventasVentas y facturacion
comprasCompras
inventarioInventario
bancosBancos y finanzas
contabilidadContabilidad
nominaNomina
rrhhRecursos humanos
posPunto de venta
restauranteRestaurante
auditoriaAuditoria
crmCRM
manufacturaManufactura
flotaFlota
logisticaLogistica
permisosAdministracion de permisos
ActionCodeDescripcion
VIEWVer/listar registros
CREATECrear nuevos registros
EDITEditar registros existentes
DELETEEliminar registros
VOIDAnular documentos
APPROVEAprobar documentos/solicitudes
EXPORTExportar datos
ADMINAdministracion del modulo

El middleware RBAC resuelve permisos con la siguiente prioridad:

1. Si el usuario es admin --> PERMITIR (siempre)
2. Si existe Override usuario --> usar ese valor
3. Si existe RolePermission --> usar valor del rol
4. Si no hay configuracion --> PERMITIR (graceful degradation)

Zentto ofrece dos formas de aplicar RBAC:

1. requirePermission(module, action) — Por ruta

Sección titulada «1. requirePermission(module, action) — Por ruta»
import { requirePermission } from "../../middleware/rbac.js";
router.post("/", requirePermission("ventas", "CREATE"), async (req, res) => {
// Solo usuarios con permiso ventas.CREATE llegan aqui
});

Resuelve modulo y accion automaticamente desde el path y metodo HTTP:

  • POST /v1/ventas/... verifica ventas.CREATE
  • PUT /v1/inventario/... verifica inventario.EDIT
  • POST /v1/contabilidad/.../anular verifica contabilidad.VOID

El autoRbac solo verifica en metodos que modifican datos (POST/PUT/PATCH/DELETE). Los GET pasan sin verificacion.

Los resultados de verificacion se cachean en memoria con TTL de 5 minutos para evitar consultas repetitivas a la BD.

La gestion de permisos se realiza desde /v1/permisos:

GET /v1/permisos/permisos -- Catalogo completo
GET /v1/permisos/roles/:roleId/permisos -- Permisos de un rol
POST /v1/permisos/roles/:roleId/permisos/bulk -- Asignar permisos masivamente
POST /v1/permisos/usuarios/:userId/permisos/override -- Override por usuario
GET /v1/permisos/usuarios/:userId/verificar/:code -- Verificar permiso especifico

El middleware de auditoria intercepta automaticamente todas las operaciones POST, PUT, PATCH y DELETE exitosas y registra en audit.AuditLog.

Caracteristicas:

  • Best-effort: nunca bloquea la respuesta al cliente
  • Fire-and-forget: usa setImmediate() para no impactar latencia
  • Solo exitosas: solo registra respuestas con status 2xx
  • Auto-resolucion: detecta modulo, entidad, accion e ID automaticamente
CampoDescripcionEjemplo
UserIdID del usuario42
UserNameNombre de usuarioadmin
ModuleNameModulo afectadoventas
EntityNameEntidaddocumentos-venta
EntityIdID de la entidadFAC-0001
ActionTypeTipo de accionCREATE, UPDATE, DELETE, VOID
SummaryResumen legibleCREATE documentos-venta #FAC-0001
NewValuesBody del request (truncado a 2000 chars){"customerId": 5, ...}
IPAddressIP del cliente192.168.1.100

No se auditan operaciones en:

  • /health — health checks
  • /sistema/notificaciones — polling de notificaciones
  • /auditoria/ — evitar recursion
  • /config, /settings — configuracion
  • /auth/refresh — renovacion de token
GET /v1/auditoria/logs?module=ventas&from=2026-01-01&to=2026-03-31
GET /v1/auditoria/logs?userId=42&actionType=DELETE

El sistema permite configurar restricciones de descuento y precio por rol o usuario:

RestriccionDescripcion
MaxDiscountPercentDescuento maximo permitido (ej: 15%)
MinPricePercentPrecio minimo como % del precio lista (ej: 85%)
MaxCreditLimitLimite de credito maximo otorgable
RequiresApprovalAboveMonto a partir del cual requiere aprobacion
GET /v1/permisos/precios -- Listar restricciones
POST /v1/permisos/precios -- Crear/actualizar restriccion
GET /v1/permisos/precios/verificar/:userId -- Verificar restriccion del usuario
1. Vendedor aplica descuento del 20%
2. Frontend consulta /v1/permisos/precios/verificar/:userId
3. Si MaxDiscountPercent = 15% --> bloquear o solicitar aprobacion
4. Si RequiresApprovalAbove y monto > umbral --> crear solicitud de aprobacion

Para operaciones que superan los umbrales configurados, se activa un flujo de aprobacion:

Configuracion en sec.ApprovalRule:

CampoDescripcion
ModuleCodeModulo (ej: ventas)
DocumentTypeTipo de documento (ej: FACTURA)
MinAmountMonto minimo para activar la regla
MaxAmountMonto maximo (opcional)
RequiredRoleIdRol requerido para aprobar
ApprovalLevelsNiveles de aprobacion requeridos
PENDING --> APPROVED
--> REJECTED
  1. El sistema detecta que la operacion requiere aprobacion
  2. Crea una solicitud con estado PENDING
  3. Un usuario con el rol requerido aprueba o rechaza
  4. Si se aprueba, la operacion procede
GET /v1/permisos/aprobaciones -- Listar solicitudes
POST /v1/permisos/aprobaciones -- Crear solicitud
GET /v1/permisos/aprobaciones/:id -- Detalle
POST /v1/permisos/aprobaciones/:id/accion -- Aprobar/rechazar

La documentacion de la API (Swagger/OpenAPI) esta protegida con Basic Auth separado del JWT, para permitir acceso a desarrolladores sin necesidad de un usuario del sistema.

CapaMecanismoScope
AutenticacionJWT + bcryptTodas las rutas /v1/*
AutorizacionRBAC (Permission + Role + Override)Operaciones de escritura
AuditoriaMiddleware automatico best-effortPOST/PUT/PATCH/DELETE exitosos
RestriccionesPrice restrictions + approval workflowsDescuentos y montos altos
Multi-tenantCompanyId + BranchId en JWTAislamiento de datos