6.4 KiB
MODELO DE DOMINIO: Autenticación y Autorización
Módulos: MGN-001 (Fundamentos), MGN-002 (Empresas) Fecha: 2025-11-24 Referencia Odoo: base, auth_signup Referencia Gamilit: auth_management schema
Diagrama de Entidades (Texto UML)
[Tenant]
- id: UUID (PK)
- name: String
- subdomain: String
- schema_name: String
- status: ENUM (active, suspended)
- settings: JSONB
1 <----> * [Company]
1 <----> * [User]
[Company]
- id: UUID (PK)
- tenant_id: UUID (FK)
- name: String
- tax_id: String
- currency_id: UUID (FK)
- settings: JSONB
1 <----> * [User]
[User]
- id: UUID (PK)
- tenant_id: UUID (FK)
- email: String (UNIQUE per tenant)
- password_hash: String
- full_name: String
- status: ENUM (active, inactive, suspended)
- is_superuser: Boolean
* <----> * [Role] (through UserRole)
1 <----> * [Session]
[Role]
- id: UUID (PK)
- tenant_id: UUID (FK)
- name: String
- code: String
- description: Text
* <----> * [Permission] (through RolePermission)
[Permission]
- id: UUID (PK)
- resource: String (ej: 'purchase_orders')
- action: ENUM (create, read, update, delete, approve)
- description: Text
[Session]
- id: UUID (PK)
- user_id: UUID (FK)
- token: String
- expires_at: Timestamp
- ip_address: String
- user_agent: String
[UserRole] (many-to-many)
- user_id: UUID (FK)
- role_id: UUID (FK)
[RolePermission] (many-to-many)
- role_id: UUID (FK)
- permission_id: UUID (FK)
Entidades Principales
1. Tenant (Multi-Tenancy)
Descripción: Representa un tenant (empresa matriz o grupo). Cada tenant tiene su propio schema PostgreSQL.
Atributos:
id: Identificador úniconame: Nombre del tenantsubdomain: Subdominio (ej: 'acme' → acme.erp.com)schema_name: Nombre del schema PostgreSQL (ej: 'tenant_acme')status: Estado (active, suspended)settings: Configuración JSON (logo, tema, etc.)
Relaciones:
- 1 Tenant → N Companies
- 1 Tenant → N Users
Patrón Odoo: Similar a res.company pero en un nivel superior Patrón Gamilit: Implementado con schema-level isolation
RLS Policy:
-- Usuarios solo ven su tenant
CREATE POLICY tenant_isolation ON tenants
USING (id = get_current_tenant_id());
2. Company (Empresa)
Descripción: Empresa dentro de un tenant. Permite multi-empresa.
Atributos:
id: UUIDtenant_id: Tenant propietarioname: Nombre empresatax_id: RFC/Tax IDcurrency_id: Moneda por defectosettings: JSONB (dirección, contacto, etc.)
Relaciones:
- N Companies → 1 Tenant
- 1 Company → N Users (usuarios pueden estar en múltiples empresas)
Patrón Odoo: res.company Validaciones:
- Un tenant debe tener al menos 1 company
- tax_id único por tenant
3. User (Usuario)
Descripción: Usuario del sistema con roles y permisos.
Atributos:
id: UUIDtenant_id: Tenant propietarioemail: Email (único por tenant)password_hash: bcrypt hashfull_name: Nombre completostatus: active, inactive, suspendedis_superuser: Admin total del tenant
Relaciones:
- N Users → 1 Tenant
- N Users ←→ N Roles (many-to-many)
- 1 User → N Sessions
Patrón Odoo: res.users Patrón Gamilit: auth.users con tenant_id
Validaciones:
- email único por tenant (no global)
- password mínimo 8 caracteres
- is_superuser requiere aprobación
RLS Policy:
CREATE POLICY users_own_tenant ON users
USING (tenant_id = get_current_tenant_id());
4. Role (Rol)
Descripción: Rol con permisos asignados (RBAC).
Atributos:
id: UUIDtenant_id: Tenant propietarioname: Nombre del rolcode: Código único (ej: 'admin', 'buyer')description: Descripción
Relaciones:
- N Roles → 1 Tenant
- N Roles ←→ N Permissions
Patrón Odoo: res.groups Roles predefinidos:
admin: Administrador del tenantmanager: Gerente (full access transaccional)user: Usuario normalreadonly: Solo lectura
5. Permission (Permiso)
Descripción: Permiso granular sobre recursos.
Atributos:
id: UUIDresource: Recurso (tabla/endpoint) (ej: 'purchase_orders')action: create, read, update, delete, approve, cancel
Ejemplo de permisos:
Resource: purchase_orders
Actions: create, read, update, delete, approve
Patrón Odoo: ir.model.access + ir.rule Implementación: Validado en backend + RLS policies en BD
6. Session (Sesión)
Descripción: Sesión JWT de usuario.
Atributos:
id: UUIDuser_id: Usuario propietariotoken: JWT tokenexpires_at: Expiraciónip_address: IP de origenuser_agent: Navegador
Patrón Gamilit: auth.sessions
Reglas de Negocio
RN-AUTH-001: Multi-Tenancy Obligatorio
- TODO usuario pertenece a exactamente 1 tenant
- TODO dato transaccional tiene tenant_id
- Aislamiento completo entre tenants (schema-level)
RN-AUTH-002: RBAC Granular
- Usuario puede tener múltiples roles
- Permisos se calculan como UNION de permisos de roles
- is_superuser bypassa todos los checks
RN-AUTH-003: Sesiones JWT
- Expiración: 8 horas
- Refresh token: 30 días
- Invalidación: Logout o expiración
RN-AUTH-004: Passwords Seguros
- Mínimo 8 caracteres
- Debe incluir: mayúscula, minúscula, número
- bcrypt hash (cost factor 12)
Casos de Uso Principales
- UC-AUTH-001: Login de usuario
- UC-AUTH-002: Registro de nuevo tenant
- UC-AUTH-003: Asignar rol a usuario
- UC-AUTH-004: Validar permisos para acción
- UC-AUTH-005: Reset password
- UC-AUTH-006: Cambiar de empresa (multi-company)
Validaciones y Constraints
-- Email único por tenant
UNIQUE (tenant_id, email)
-- Status válidos
CHECK (status IN ('active', 'inactive', 'suspended'))
-- Al menos 1 admin por tenant
-- (trigger custom)
-- Session expiration
CHECK (expires_at > created_at)
Índices Requeridos
CREATE INDEX idx_users_tenant_id ON auth.users(tenant_id);
CREATE INDEX idx_users_email ON auth.users(email);
CREATE INDEX idx_sessions_user_id ON auth.sessions(user_id);
CREATE INDEX idx_sessions_token ON auth.sessions(token);
CREATE INDEX idx_user_roles_user_id ON auth.user_roles(user_id);