New projects created: - michangarrito (marketplace mobile) - template-saas (SaaS template) - clinica-dental (dental ERP) - clinica-veterinaria (veterinary ERP) Architecture updates: - Move catalog from core/ to shared/ - Add MCP servers structure and templates - Add git management scripts - Update SUBREPOSITORIOS.md with 15 new repos - Update .gitignore for new projects Repository infrastructure: - 4 main repositories - 11 subrepositorios - Gitea remotes configured 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
243 lines
5.4 KiB
Markdown
243 lines
5.4 KiB
Markdown
# 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`
|
|
- `shared/catalog/multi-tenancy/`
|
|
- PostgreSQL RLS Documentation
|
|
|
|
---
|
|
|
|
*Knowledge Base - Workspace v1*
|