Files
2026-03-19 18:06:44 +01:00

154 lines
5.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""RLS completa su tutte le tabelle applicative + ruolo pechub_app
Revision ID: 0006
Revises: 0005
Create Date: 2026-03-19 00:00:00.000000
Aggiunge:
- ENABLE ROW LEVEL SECURITY + policy USING (tenant_id = ...) su tutte le
tabelle applicative che mancavano (attachments, send_jobs, archival_batches,
archival_dips, labels, mailbox_permissions, virtual_boxes,
notification_channels, notification_rules, notification_log, tenant_settings)
- Crea il ruolo PostgreSQL applicativo 'pechub_app' (non-superuser) con
GRANT SELECT/INSERT/UPDATE/DELETE su tutte le tabelle.
Il ruolo viene usato dalla connessione applicativa (DATABASE_URL) mentre
Alembic continua ad usare l'utente superuser (DATABASE_URL_SYNC).
Nota: la migrazione usa DO $$ BEGIN ... EXCEPTION WHEN ... END $$ per
rendere idempotente la creazione del ruolo e delle policy.
"""
from alembic import op
revision = "0006"
down_revision = "0005"
branch_labels = None
depends_on = None
# Tabelle con tenant_id che devono avere RLS (escluse quelle già gestite in 0001)
_RLS_TABLES = [
"attachments",
"send_jobs",
"archival_batches",
"archival_dips",
"labels",
"mailbox_permissions",
"virtual_boxes",
"notification_channels",
"notification_rules",
"notification_log",
"tenant_settings",
]
# Tutte le tabelle su cui pechub_app ha SELECT/INSERT/UPDATE/DELETE
_ALL_APP_TABLES = [
"tenants",
"users",
"refresh_tokens",
"mailboxes",
"messages",
"attachments",
"send_jobs",
"archival_batches",
"archival_batch_messages",
"archival_dips",
"labels",
"message_labels",
"mailbox_permissions",
"virtual_boxes",
"virtual_box_rules",
"virtual_box_assignments",
"virtual_box_mailboxes",
"notification_channels",
"notification_rules",
"notification_log",
"audit_log",
"tenant_settings",
]
def upgrade() -> None:
# ── 1. Abilita RLS + policy su tabelle mancanti ───────────────────────────
for table in _RLS_TABLES:
op.execute(f"ALTER TABLE {table} ENABLE ROW LEVEL SECURITY")
# Politica idempotente: elimina la policy se esiste e la ricrea
op.execute(
f"""
DO $$
BEGIN
-- Elimina policy esistente (se presente da un run precedente)
DROP POLICY IF EXISTS {table}_tenant_isolation ON {table};
-- Crea la nuova policy
CREATE POLICY {table}_tenant_isolation ON {table}
USING (
tenant_id = NULLIF(
current_setting('app.current_tenant_id', TRUE), ''
)::UUID
);
END
$$;
"""
)
# ── 2. Crea ruolo applicativo pechub_app (non-superuser) ──────────────────
op.execute(
"""
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_roles WHERE rolname = 'pechub_app'
) THEN
CREATE USER pechub_app WITH PASSWORD 'pechub_app_password'
NOSUPERUSER NOCREATEDB NOCREATEROLE;
RAISE NOTICE 'Ruolo pechub_app creato';
ELSE
RAISE NOTICE 'Ruolo pechub_app già esistente skip';
END IF;
END
$$;
"""
)
# ── 3. Permessi al ruolo applicativo ──────────────────────────────────────
op.execute("GRANT CONNECT ON DATABASE pechub TO pechub_app")
op.execute("GRANT USAGE ON SCHEMA public TO pechub_app")
for table in _ALL_APP_TABLES:
op.execute(
f"GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE {table} TO pechub_app"
)
# Sequenze (per BIGSERIAL come audit_log.id)
op.execute("GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO pechub_app")
# Default privileges: le tabelle create nelle migrazioni future ricevono
# automaticamente i permessi per pechub_app
op.execute(
"""
ALTER DEFAULT PRIVILEGES FOR ROLE pechub IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO pechub_app;
"""
)
op.execute(
"""
ALTER DEFAULT PRIVILEGES FOR ROLE pechub IN SCHEMA public
GRANT USAGE, SELECT ON SEQUENCES TO pechub_app;
"""
)
def downgrade() -> None:
# Rimuovi policy e disabilita RLS
for table in _RLS_TABLES:
op.execute(
f"DROP POLICY IF EXISTS {table}_tenant_isolation ON {table}"
)
op.execute(f"ALTER TABLE {table} DISABLE ROW LEVEL SECURITY")
# Revoca permessi e rimuovi ruolo
op.execute("REVOKE ALL ON ALL TABLES IN SCHEMA public FROM pechub_app")
op.execute("REVOKE ALL ON ALL SEQUENCES IN SCHEMA public FROM pechub_app")
op.execute("REVOKE USAGE ON SCHEMA public FROM pechub_app")
op.execute("REVOKE CONNECT ON DATABASE pechub FROM pechub_app")
op.execute("DROP USER IF EXISTS pechub_app")