# Patron RLS Policies **Categoria:** Patterns **Version:** 1.0.0 **Origen:** projects/gamilit, projects/erp-core **Fecha:** 2025-12-27 --- ## Descripcion Patrones estandarizados para implementar Row-Level Security (RLS) en PostgreSQL. ## Politicas Base ### 1. Tenant Isolation (Aislamiento por tenant) ```sql -- Template basico CREATE POLICY tenant_isolation ON {schema}.{table} FOR ALL USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID); ``` ### 2. Tenant + Owner (Aislamiento por tenant y propietario) ```sql -- Solo el creador puede ver/modificar CREATE POLICY owner_only ON {schema}.{table} FOR ALL USING ( tenant_id = current_setting('app.current_tenant_id', true)::UUID AND created_by = current_setting('app.current_user_id', true)::UUID ); ``` ### 3. Tenant + Role Based (Basado en roles) ```sql -- Admins ven todo, usuarios ven lo suyo CREATE POLICY role_based ON {schema}.{table} FOR ALL USING ( tenant_id = current_setting('app.current_tenant_id', true)::UUID AND ( current_setting('app.current_user_role', true) = 'admin' OR created_by = current_setting('app.current_user_id', true)::UUID ) ); ``` ### 4. Soft Delete Protection ```sql -- No mostrar registros eliminados CREATE POLICY soft_delete ON {schema}.{table} FOR SELECT USING ( tenant_id = current_setting('app.current_tenant_id', true)::UUID AND deleted_at IS NULL ); -- Admins pueden ver eliminados CREATE POLICY admin_see_deleted ON {schema}.{table} FOR SELECT USING ( tenant_id = current_setting('app.current_tenant_id', true)::UUID AND current_setting('app.current_user_role', true) = 'admin' ); ``` ### 5. Hierarchical Access (Acceso jerarquico) ```sql -- Managers ven datos de su equipo CREATE POLICY hierarchical ON {schema}.{table} FOR SELECT USING ( tenant_id = current_setting('app.current_tenant_id', true)::UUID AND ( created_by = current_setting('app.current_user_id', true)::UUID OR created_by IN ( SELECT id FROM auth.users WHERE manager_id = current_setting('app.current_user_id', true)::UUID ) ) ); ``` ## Patrones por Operacion ### SELECT (Lectura) ```sql CREATE POLICY read_own ON {table} FOR SELECT USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID); ``` ### INSERT (Creacion) ```sql CREATE POLICY insert_own ON {table} FOR INSERT WITH CHECK ( tenant_id = current_setting('app.current_tenant_id', true)::UUID AND created_by = current_setting('app.current_user_id', true)::UUID ); ``` ### UPDATE (Modificacion) ```sql CREATE POLICY update_own ON {table} FOR UPDATE USING ( tenant_id = current_setting('app.current_tenant_id', true)::UUID AND created_by = current_setting('app.current_user_id', true)::UUID ) WITH CHECK ( tenant_id = current_setting('app.current_tenant_id', true)::UUID ); ``` ### DELETE (Eliminacion) ```sql -- Solo admins pueden eliminar CREATE POLICY delete_admin_only ON {table} FOR DELETE USING ( tenant_id = current_setting('app.current_tenant_id', true)::UUID AND current_setting('app.current_user_role', true) = 'admin' ); ``` ## Casos Especiales ### Tablas de Configuracion Global ```sql -- Sin RLS, acceso publico de lectura ALTER TABLE config.settings DISABLE ROW LEVEL SECURITY; -- O con politica permisiva CREATE POLICY public_read ON config.settings FOR SELECT USING (true); ``` ### Tablas de Audit (Solo insert) ```sql -- Solo permitir INSERT, nunca UPDATE/DELETE CREATE POLICY audit_insert_only ON audit.logs FOR INSERT WITH CHECK (true); -- Bloquear todo lo demas CREATE POLICY audit_no_modify ON audit.logs FOR UPDATE USING (false); CREATE POLICY audit_no_delete ON audit.logs FOR DELETE USING (false); ``` ### Cross-Tenant Access (Super Admin) ```sql -- Super admin puede ver todos los tenants CREATE POLICY super_admin_access ON {table} FOR ALL USING ( current_setting('app.is_super_admin', true)::BOOLEAN = true OR tenant_id = current_setting('app.current_tenant_id', true)::UUID ); ``` ## Script de Generacion ```sql -- Funcion para aplicar politicas estandar CREATE OR REPLACE FUNCTION apply_standard_rls( p_schema TEXT, p_table TEXT ) RETURNS VOID AS $$ BEGIN -- Habilitar RLS EXECUTE format('ALTER TABLE %I.%I ENABLE ROW LEVEL SECURITY', p_schema, p_table); -- Politica de tenant isolation EXECUTE format( 'CREATE POLICY tenant_isolation ON %I.%I FOR ALL USING (tenant_id = current_setting(''app.current_tenant_id'', true)::UUID)', p_schema, p_table ); RAISE NOTICE 'RLS applied to %.%', p_schema, p_table; END; $$ LANGUAGE plpgsql; -- Uso: SELECT apply_standard_rls('my_schema', 'my_table'); ``` ## Validacion ```sql -- Verificar que RLS esta activo SELECT schemaname, tablename, rowsecurity FROM pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema') ORDER BY schemaname, tablename; -- Verificar politicas existentes SELECT schemaname, tablename, policyname, permissive, roles, cmd, qual FROM pg_policies ORDER BY schemaname, tablename; ``` ## Referencias - `architecture/PATRON-MULTI-TENANT.md` - `core/catalog/multi-tenancy/` - PostgreSQL RLS Documentation --- *Knowledge Base - Workspace v1*