From 6631615bef7cb288af1577c0398af0f31387573c Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Thu, 6 Aug 2026 00:56:19 +0200 Subject: [PATCH] =?UTF-8?q?fix(migration):=20exclude=20login=20tables=20fr?= =?UTF-8?q?om=20RLS=20in=200108=20=E2=80=94=20RLS=20blocks=20crm=5Fauth=20?= =?UTF-8?q?login?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LOGIN_TABLES (users, user_tenants, tenants, sessions, password_reset_tokens) added to skip list. RLS on these tables blocked crm_auth from reading users during login → 401 Invalid email or password. crm_auth grants applied directly (no RLS) matching 0085 AUTH_TABLES. ⚠️ LOGIN-TABELLEN DÜRFEN KEIN RLS BEKOMMEN — RLS blockiert crm_auth beim Login. Siehe 0085 AUTH_TABLES für die korrekten Grants. --- .../0108_enable_rls_for_all_tenant_tables.py | 59 +++++++++++++------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/alembic/versions/0108_enable_rls_for_all_tenant_tables.py b/alembic/versions/0108_enable_rls_for_all_tenant_tables.py index e44e580..f010b51 100644 --- a/alembic/versions/0108_enable_rls_for_all_tenant_tables.py +++ b/alembic/versions/0108_enable_rls_for_all_tenant_tables.py @@ -15,7 +15,10 @@ has a ``tenant_id`` column but does **not** yet have RLS enabled, then: 5. Grants the appropriate permissions to ``crm_auth`` on login tables (users, user_tenants, tenants, sessions, password_reset_tokens). -Global tables without tenant isolation requirements are skipped. +Global tables and login tables without tenant isolation requirements are skipped. + +⚠️ LOGIN-TABELLEN DÜRFEN KEIN RLS BEKOMMEN — RLS blockiert crm_auth beim Login. +Siehe 0085 AUTH_TABLES für die korrekten Grants. Revision ID: 0108 Revises: 0107 @@ -40,8 +43,20 @@ GLOBAL_TABLES = [ "notification_types", ] -# Login / identity tables that DO have tenant_id and need RLS, but also need -# crm_auth to keep the permissions defined in migration 0085. +# ⚠️ LOGIN-TABELLEN DÜRFEN KEIN RLS BEKOMMEN — RLS blockiert crm_auth beim Login. +# Siehe 0085 AUTH_TABLES für die korrekten Grants. +# These tables have tenant_id but must NOT get RLS because crm_auth (the login +# role) is not included in the RLS policy. RLS on these tables blocks the +# login flow (crm_auth cannot read users → 401 Invalid email or password). +LOGIN_TABLES = [ + "users", + "user_tenants", + "tenants", + "sessions", + "password_reset_tokens", +] + +# Permissions that crm_auth needs on login tables (matching 0085 AUTH_TABLES) AUTH_TABLES = { "users": ["SELECT"], "user_tenants": ["SELECT"], @@ -58,7 +73,7 @@ def _exec(sql: str) -> None: def upgrade() -> None: # ------------------------------------------------------------------ # # Dynamic discovery + RLS activation for every tenant table that # - # was created after migration 0085 and therefore lacks RLS. # + # was created after migration 0085 and therefore lacks RLS. # # ------------------------------------------------------------------ # _exec(""" @@ -66,7 +81,6 @@ DO $$ DECLARE r RECORD; policy_sql TEXT; - auth_sql TEXT; BEGIN FOR r IN SELECT t.table_name @@ -82,7 +96,14 @@ BEGIN 'plugin_migrations', 'marketplace_listings', 'sequences', - 'notification_types' + 'notification_types', + -- ⚠️ LOGIN-TABELLEN DÜRFEN KEIN RLS BEKOMMEN — RLS blockiert + -- crm_auth beim Login. Siehe 0085 AUTH_TABLES. + 'users', + 'user_tenants', + 'tenants', + 'sessions', + 'password_reset_tokens' ) AND NOT EXISTS ( SELECT 1 @@ -116,23 +137,23 @@ BEGIN -- Grant CRUD to crm_api and crm_worker EXECUTE format('GRANT SELECT, INSERT, UPDATE, DELETE ON public.%I TO crm_api', r.table_name); EXECUTE format('GRANT SELECT, INSERT, UPDATE, DELETE ON public.%I TO crm_worker', r.table_name); - - -- Grant crm_auth permissions on login tables (matching 0085 AUTH_TABLES) - IF r.table_name = 'users' THEN - GRANT SELECT ON public.users TO crm_auth; - ELSIF r.table_name = 'user_tenants' THEN - GRANT SELECT ON public.user_tenants TO crm_auth; - ELSIF r.table_name = 'tenants' THEN - GRANT SELECT ON public.tenants TO crm_auth; - ELSIF r.table_name = 'password_reset_tokens' THEN - GRANT SELECT, INSERT, UPDATE, DELETE ON public.password_reset_tokens TO crm_auth; - ELSIF r.table_name = 'sessions' THEN - GRANT SELECT, INSERT, UPDATE, DELETE ON public.sessions TO crm_auth; - END IF; END LOOP; END $$; """) + # ------------------------------------------------------------------ # + # crm_auth grants on login tables (NO RLS on these tables!) # + # ⚠️ LOGIN-TABELLEN DÜRFEN KEIN RLS BEKOMMEN — RLS blockiert # + # crm_auth beim Login. Siehe 0085 AUTH_TABLES für die korrekten Grants.# + # ------------------------------------------------------------------ # + for table, privs in AUTH_TABLES.items(): + priv_str = ", ".join(privs) + _exec( + f"DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables " + f"WHERE table_schema = 'public' AND table_name = '{table}') " + f"THEN GRANT {priv_str} ON public.{table} TO crm_auth; END IF; END $$" + ) + def downgrade() -> None: pass