From 1dbb56752c3b25dc6ee24cde8e6ed311be6f581b Mon Sep 17 00:00:00 2001 From: Mitchell R Date: Wed, 27 May 2026 02:10:56 +0200 Subject: [PATCH] fix: tenant switch auto-copies global admin into tenant users MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit isSetupComplete() now checks public.global_admins — if a global admin exists but tenant has no local users, copies admin into tenant's users table and marks setup complete. Prevents setup wizard on tenant switch. Co-Authored-By: Claude Opus 4.6 (1M context) --- server/src/shared/db/repository.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/server/src/shared/db/repository.ts b/server/src/shared/db/repository.ts index bd2cd5a..97436b9 100644 --- a/server/src/shared/db/repository.ts +++ b/server/src/shared/db/repository.ts @@ -260,7 +260,24 @@ export class Repository { } async isSetupComplete(): Promise { - return (await this.getSetupState()).is_complete && (await this.countUsers()) > 0; + const state = await this.getSetupState(); + if (state.is_complete) return true; + if ((await this.countUsers()) > 0) return true; + // No local users — copy global admin into tenant if one exists. + const ga = await this._get<{ id: string; username: string; password_hash: string }>( + "SELECT id, username, password_hash FROM public.global_admins WHERE is_active = true LIMIT 1", + ).catch(() => undefined); + if (ga) { + await this._run( + `INSERT INTO users (id, username, password_hash, role, is_active) + VALUES (?, ?, ?, 'admin', true) + ON CONFLICT (id) DO NOTHING`, + [ga.id, ga.username, ga.password_hash], + ); + await this.markSetupComplete(); + return true; + } + return false; } async markSetupComplete(): Promise {