From 47aa42ed09b16312609ecbc29fa2f86ca84e3490 Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Fri, 7 Aug 2026 00:29:59 +0200 Subject: [PATCH] fix(prestart): dynamic owner_id fix for all plugin tables Instead of a static list, find ALL tables with tenant_id but without owner_id and add the column. This catches all plugin tables that were created after core migration 0054 ran. --- prestart.sh | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/prestart.sh b/prestart.sh index f9f42b4..ce8cd05 100644 --- a/prestart.sh +++ b/prestart.sh @@ -5,7 +5,8 @@ # Responsibilities: # 1. Run Alembic DB migrations (alembic upgrade head) using the migration user. # 2. Set passwords for all application DB roles (crm_api, crm_auth, crm_worker, crm_migration). -# 3. Start uvicorn as PID 1 (so signals like SIGTERM are forwarded correctly). +# 3. Add owner_id to plugin tables that were created after core migration 0054. +# 4. Start uvicorn as PID 1 (so signals like SIGTERM are forwarded correctly). # # Notes: # - `set -e` ensures the container crashes loudly if migrations fail. @@ -102,7 +103,7 @@ fi echo "[prestart] Adding owner_id to plugin tables if missing..." python3 -c " -import asyncio, os, re +import asyncio, os from sqlalchemy.ext.asyncio import create_async_engine from sqlalchemy import text @@ -112,30 +113,35 @@ async def fix_owner_id(): print('[prestart] WARNING: No DB URL for owner_id fix') return engine = create_async_engine(db_url) - # Tables that should have owner_id (from core migration 0054) - tables = ['files', 'folders', 'calendar_entries', 'calendars', 'tasks', 'subtasks'] try: async with engine.begin() as conn: + # Find all tables with tenant_id but without owner_id + result = await conn.execute(text(\"\"\" + SELECT t.table_name + FROM information_schema.tables t + JOIN information_schema.columns c ON t.table_name = c.table_name + WHERE t.table_schema = 'public' + AND c.column_name = 'tenant_id' + AND t.table_type = 'BASE TABLE' + AND NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = t.table_name AND column_name = 'owner_id' + ) + ORDER BY t.table_name + \"\"\")) + tables = [row[0] for row in result.fetchall()] for table in tables: - # Check if table exists - exists = await conn.execute(text( - \"SELECT 1 FROM information_schema.tables WHERE table_name = :t\" - ), {\"t\": table}) - if exists.fetchone() is None: - continue - # Check if owner_id column exists - has_col = await conn.execute(text( - \"SELECT 1 FROM information_schema.columns WHERE table_name = :t AND column_name = 'owner_id'\" - ), {\"t\": table}) - if has_col.fetchone() is None: - await conn.execute(text( - f\"ALTER TABLE {table} ADD COLUMN IF NOT EXISTS owner_id UUID REFERENCES users(id) ON DELETE SET NULL\" - )) - await conn.execute(text( - f\"CREATE INDEX IF NOT EXISTS ix_{table}_owner ON {table} (owner_id)\" - )) - print(f'[prestart] Added owner_id to {table}') - print('[prestart] owner_id fix completed.') + await conn.execute(text( + f'ALTER TABLE {table} ADD COLUMN IF NOT EXISTS owner_id UUID REFERENCES users(id) ON DELETE SET NULL' + )) + await conn.execute(text( + f'CREATE INDEX IF NOT EXISTS ix_{table}_owner ON {table} (owner_id)' + )) + print(f'[prestart] Added owner_id to {table}') + if not tables: + print('[prestart] All tables already have owner_id.') + else: + print(f'[prestart] Added owner_id to {len(tables)} tables.') except Exception as e: print(f'[prestart] WARNING: owner_id fix failed: {e}') finally: