5.5 KiB
5.5 KiB
RF-MGN-001-008: Record Rules (Row Level Security)
Módulo: MGN-001 - Fundamentos Prioridad: P1 (Post-MVP) Story Points: 13 Estado: Definido Fecha: 2025-11-23
Descripción
El sistema debe implementar Record Rules (RLS - Row Level Security) para filtrar automáticamente registros según reglas definidas por rol. Un usuario solo ve/edita registros que cumplen las reglas de sus roles.
Actores
- Actor Principal: Administrador de Sistema (define reglas)
- Actores Secundarios: Usuario (consume reglas automáticamente)
Precondiciones
- Sistema RBAC debe estar implementado (RF-MGN-001-002)
- PostgreSQL RLS debe estar habilitado en tablas
- Usuario debe estar autenticado
Flujo Principal
- Administrador accede a módulo de Record Rules
- Administrador selecciona modelo (ej: sale.order)
- Administrador selecciona rol (ej: Vendedor)
- Administrador define regla SQL (ej: "assigned_to_id = get_current_user_id()")
- Administrador define operaciones: read, create, update, delete
- Sistema crea registro en auth.record_rules
- Sistema genera RLS policy en PostgreSQL:
CREATE POLICY vendedor_ve_sus_ordenes ON sales.orders FOR SELECT TO vendedor_role USING (assigned_to_id = get_current_user_id()); - Usuario con rol Vendedor consulta sale.orders
- PostgreSQL aplica RLS policy automáticamente
- Usuario solo ve sus propias órdenes (filtrado a nivel DB)
Flujos Alternativos
FA-1: Múltiples Roles con Reglas Diferentes
- Usuario tiene roles: Vendedor + Supervisor
- Vendedor: ve solo sus órdenes (assigned_to_id = user_id)
- Supervisor: ve órdenes de su equipo (team_id IN user.teams)
- Sistema aplica OR entre reglas (usuario ve unión de ambas)
FA-2: Regla Compleja con JOINs
- Administrador define regla que requiere JOIN
- Ejemplo: "Ver proyectos de empresas donde usuario tiene acceso"
project_id IN ( SELECT p.id FROM projects p JOIN user_companies uc ON uc.company_id = p.company_id WHERE uc.user_id = get_current_user_id() ) - Sistema valida sintaxis SQL
- Sistema crea RLS policy con subquery
FA-3: Bypass de RLS para Administrador
- Usuario con rol Administrator
- Sistema NO aplica RLS (administrador ve todo)
- RLS policy tiene cláusula:
OR has_role('administrator')
FA-4: Regla Inválida
- Administrador define regla con SQL inválido
- Sistema valida sintaxis SQL antes de guardar
- Sistema retorna error 400: "Sintaxis SQL inválida"
FA-5: Desactivación Temporal de Regla
- Administrador desactiva regla (status='inactive')
- Sistema elimina RLS policy de PostgreSQL
- Rol afectado pasa a no tener restricciones (o aplica otras reglas activas)
Reglas de Negocio
- RN-1: Cada rol puede tener múltiples record rules por modelo
- RN-2: Record rules se aplican con OR (unión): usuario ve registros que cumplen alguna regla
- RN-3: Administrador bypasea RLS (ve todos los registros)
- RN-4: Reglas pueden definirse para: read, create, update, delete (independientes)
- RN-5: Funciones SQL permitidas: get_current_user_id(), get_current_tenant_id(), has_role()
- RN-6: RLS se aplica a nivel PostgreSQL (no bypasseable desde código)
- RN-7: Reglas heredadas: hijo hereda reglas del padre (rol herencia)
Criterios de Aceptación
- Administrador puede definir record rules con expresiones SQL
- Sistema valida sintaxis SQL antes de guardar regla
- PostgreSQL RLS se aplica automáticamente en queries
- Usuario solo ve registros que cumplen reglas de sus roles
- Múltiples reglas se combinan con OR (unión)
- Administrador bypasea RLS (ve todos los registros)
- Reglas pueden aplicarse a read, create, update, delete
- Funciones SQL get_current_user_id() y get_current_tenant_id() funcionan
- Herencia de roles incluye herencia de record rules
- Desactivación de regla elimina RLS policy
Entidades Involucradas
- Principales:
- auth.record_rules (role_id, model_id, rule_sql, operations, status)
- auth.roles (roles con reglas)
- auth.models (modelos con RLS)
- Relacionadas:
- PostgreSQL RLS Policies (nivel DB)
Referencias
Notas Técnicas
- Patrón Odoo: Similar a ir.rule (record rules de Odoo)
- PostgreSQL RLS:
-- Habilitar RLS en tabla ALTER TABLE sales.orders ENABLE ROW LEVEL SECURITY; -- Crear policy CREATE POLICY vendedor_ve_sus_ordenes ON sales.orders FOR SELECT TO vendedor_role USING (assigned_to_id = current_setting('app.current_user_id')::INTEGER); - Funciones Contextuales:
CREATE OR REPLACE FUNCTION get_current_user_id() RETURNS INTEGER AS $$ BEGIN RETURN current_setting('app.current_user_id')::INTEGER; END; $$ LANGUAGE plpgsql; - Set Context en Request:
await this.db.query( `SELECT set_config('app.current_user_id', $1, false)`, [req.user.id] ); - Performance: Índices en columnas usadas en reglas (assigned_to_id, team_id, etc.)
- Testing: Casos de prueba por rol para validar RLS
Dependencias
- RF Dependientes:
- RF-MGN-001-001 (Autenticación)
- RF-MGN-001-002 (Roles)
- Bloqueante para: Módulos que requieren filtrado por usuario (CRM, Ventas, Proyectos)