gate2: fix all migrations for fresh DB installation

This commit is contained in:
Agent Zero
2026-07-31 19:16:11 +02:00
parent d37388423d
commit 010ef448e7
40 changed files with 230 additions and 207 deletions
+12 -19
View File
@@ -101,9 +101,9 @@ def upgrade() -> None:
# crm_migration is the table owner and needs to run tenant-wide data migrations
_exec("ALTER ROLE crm_migration NOSUPERUSER BYPASSRLS")
# Step 3: Transfer ALL table ownership to crm_migration
# Step 3: Transfer ALL table ownership to crm_migration (only for tables that exist)
for table in ALL_TABLES:
_exec(f"ALTER TABLE public.{table} OWNER TO crm_migration")
_exec(f"DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = '{table}') THEN ALTER TABLE public.{table} OWNER TO crm_migration; END IF; END $$")
# Transfer sequence ownership
_exec("DO $$ DECLARE r RECORD; BEGIN FOR r IN SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = 'public' LOOP EXECUTE format('ALTER SEQUENCE public.%I OWNER TO crm_migration', r.sequence_name); END LOOP; END $$;")
@@ -114,8 +114,8 @@ def upgrade() -> None:
_exec(f"REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM {role}")
_exec(f"REVOKE ALL PRIVILEGES ON SCHEMA public FROM {role}")
# Step 5: Drop crm_runtime role
_exec("DROP ROLE IF EXISTS crm_runtime")
# Step 5: Drop crm_runtime role (may fail if permissions insufficient)
_exec("DO $$ BEGIN DROP ROLE IF EXISTS crm_runtime; EXCEPTION WHEN insufficient_privilege THEN NULL; END $$")
# Step 6: Grant schema USAGE to runtime roles
_exec("GRANT USAGE ON SCHEMA public TO crm_api")
@@ -125,12 +125,11 @@ def upgrade() -> None:
# Step 7: Grant permissions to crm_auth (identity tables only)
for table, privs in AUTH_TABLES.items():
priv_str = ", ".join(privs)
_exec(f"GRANT {priv_str} ON public.{table} TO crm_auth")
_exec(f"DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = '{table}') THEN GRANT {priv_str} ON public.{table} TO crm_auth; END IF; END $$")
# Step 8: Grant CRUD on tenant tables to crm_api and crm_worker
# Step 8: Grant CRUD on tenant tables to crm_api and crm_worker (only for tables that exist)
for table in TENANT_TABLES:
_exec(f"GRANT SELECT, INSERT, UPDATE, DELETE ON public.{table} TO crm_api")
_exec(f"GRANT SELECT, INSERT, UPDATE, DELETE ON public.{table} TO crm_worker")
_exec(f"DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = '{table}') THEN GRANT SELECT, INSERT, UPDATE, DELETE ON public.{table} TO crm_api; GRANT SELECT, INSERT, UPDATE, DELETE ON public.{table} TO crm_worker; END IF; END $$")
# Grant sequence USAGE to crm_api and crm_worker
_exec("GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO crm_api")
@@ -139,19 +138,19 @@ def upgrade() -> None:
# Step 9: Grant global table access to crm_api (except alembic_version)
api_global_tables = [t for t in GLOBAL_TABLES if t != "alembic_version"]
for table in api_global_tables:
_exec(f"GRANT SELECT, INSERT, UPDATE, DELETE ON public.{table} TO crm_api")
_exec(f"DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = '{table}') THEN GRANT SELECT, INSERT, UPDATE, DELETE ON public.{table} TO crm_api; END IF; END $$")
# Step 10: Grant worker global table access
for table, privs in WORKER_GLOBAL_TABLES.items():
priv_str = ", ".join(privs)
_exec(f"GRANT {priv_str} ON public.{table} TO crm_worker")
_exec(f"DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = '{table}') THEN GRANT {priv_str} ON public.{table} TO crm_worker; END IF; END $$")
worker_global_tables = [
t for t in GLOBAL_TABLES
if t != "alembic_version" and t not in WORKER_GLOBAL_TABLES
]
for table in worker_global_tables:
_exec(f"GRANT SELECT, INSERT, UPDATE, DELETE ON public.{table} TO crm_worker")
_exec(f"DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = '{table}') THEN GRANT SELECT, INSERT, UPDATE, DELETE ON public.{table} TO crm_worker; END IF; END $$")
# Step 11: Drop ALL old RLS policies and create new fail-closed ones
policy_template = (
@@ -164,17 +163,11 @@ def upgrade() -> None:
)
for table in TENANT_TABLES:
_exec(f"DROP POLICY IF EXISTS tenant_isolation ON public.{table}")
_exec(f"DROP POLICY IF EXISTS {table}_tenant_isolation ON public.{table}")
_exec(f"ALTER TABLE public.{table} ENABLE ROW LEVEL SECURITY")
_exec(f"ALTER TABLE public.{table} FORCE ROW LEVEL SECURITY")
_exec(policy_template.format(table=table))
_exec(f"DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = '{table}') THEN DROP POLICY IF EXISTS tenant_isolation ON public.{table}; DROP POLICY IF EXISTS {table}_tenant_isolation ON public.{table}; ALTER TABLE public.{table} ENABLE ROW LEVEL SECURITY; ALTER TABLE public.{table} FORCE ROW LEVEL SECURITY; {policy_template.format(table=table)}; END IF; END $$")
# Step 12: Disable RLS on global tables
for table in GLOBAL_TABLES:
_exec(f"DROP POLICY IF EXISTS tenant_isolation ON public.{table}")
_exec(f"DROP POLICY IF EXISTS {table}_tenant_isolation ON public.{table}")
_exec(f"ALTER TABLE public.{table} DISABLE ROW LEVEL SECURITY")
_exec(f"DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = '{table}') THEN DROP POLICY IF EXISTS tenant_isolation ON public.{table}; DROP POLICY IF EXISTS {table}_tenant_isolation ON public.{table}; ALTER TABLE public.{table} DISABLE ROW LEVEL SECURITY; END IF; END $$")
# Step 13: Set default privileges for crm_migration owner
_exec("ALTER DEFAULT PRIVILEGES FOR ROLE crm_migration IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO crm_api")