From 1846a00d07c9c678bcadd4f806d88850dd24a28c Mon Sep 17 00:00:00 2001 From: karim Date: Sat, 30 May 2026 14:57:52 +0200 Subject: [PATCH] fix(cloud): API-Fehler nicht als 'leere Instanz' werten MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit listStudios() gab bei Kong/API-Fehler [] zurück, was App.jsx als '0 Studios' interpretierte und faelschlich den Init-/Registrierungs-Screen zeigte (statt Login). Nach Reload war Kong wieder da -> Login. Daher das 'beim Ausloggen kommt Init'-Symptom. - supabase-adapter.listStudios(): wirft jetzt statt [] zu verschlucken - App.jsx: catch setzt cloudStudios=null + cloudUnreachable=true - Routing-Guard zeigt CloudSetup nur bei !cloudUnreachable && length===0 Co-Authored-By: Claude Opus 4.8 --- src/App.jsx | 19 ++++++++++++++----- src/storage/supabase-adapter.js | 11 +++++++---- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 65cc816..940c819 100755 --- a/src/App.jsx +++ b/src/App.jsx @@ -61,6 +61,10 @@ export default function App() { // Cloud-spezifisch: Liste der Studios auf der Instanz (für Erst-Setup-Check). // null = noch nicht geladen; Array = geladen. const [cloudStudios, setCloudStudios] = useState(null); + // true, wenn listStudios() fehlschlug (Kong/API nicht erreichbar). Wird + // genutzt, um NICHT fälschlich den Init-/Registrierungs-Screen zu zeigen — + // ein API-Fehler ist nicht dasselbe wie "Instanz hat 0 Studios". + const [cloudUnreachable, setCloudUnreachable] = useState(false); // Passwort-Reset-Flow: Supabase löst beim Klick auf Reset-Link in der Mail // ein PASSWORD_RECOVERY-Event aus → wir zeigen dann das Reset-Formular. const [passwordRecovery, setPasswordRecovery] = useState(false); @@ -87,13 +91,15 @@ export default function App() { console.error("Cloud-Resume load failed:", e); } } - // Studios der Instanz holen — entscheidet später, ob CloudSetup oder Login zeigt + // Studios der Instanz holen — entscheidet später, ob CloudSetup oder Login zeigt. + // Bei Fehler (Kong/API down): NICHT [] setzen (das hieße "Instanz leer" → + // fälschlich Init-Screen). Stattdessen Unreachable-Flag → Login bleibt. try { const list = await storage.listStudios?.(); - if (!cancelled) setCloudStudios(list || []); + if (!cancelled) { setCloudStudios(list || []); setCloudUnreachable(false); } } catch (e) { console.error("listStudios failed:", e); - if (!cancelled) setCloudStudios([]); + if (!cancelled) { setCloudStudios(null); setCloudUnreachable(true); } } if (!cancelled) setLoading(false); return; @@ -499,7 +505,10 @@ export default function App() { // ohne Login läuft (sonst kommt man bei einem fehlerhaften Setup-Screen nie // an ein neueres Build, das den Bug fixt). if (!currentUser) { - if (isCloudBackend && cloudStudios !== null && cloudStudios.length === 0) { + // Init-/Registrierungs-Screen NUR wenn der API-Call erfolgreich war UND + // wirklich 0 Studios lieferte. Bei !cloudUnreachable ausgeschlossen, dass + // ein Kong/API-Fehler (cloudStudios === null) hier fälschlich Init zeigt. + if (isCloudBackend && !cloudUnreachable && cloudStudios !== null && cloudStudios.length === 0) { const cloudUrl = localStorage.getItem("rapport_cloud_url") || ""; return <> @@ -507,7 +516,7 @@ export default function App() { ; } return <> - + ; } diff --git a/src/storage/supabase-adapter.js b/src/storage/supabase-adapter.js index c5b88d9..ad7465b 100644 --- a/src/storage/supabase-adapter.js +++ b/src/storage/supabase-adapter.js @@ -125,10 +125,13 @@ export class SupabaseAdapter { // Kein Auth nötig (RPC läuft als SECURITY DEFINER). async listStudios() { const { data, error } = await this.client.rpc("list_studios"); - if (error) { - console.error("listStudios:", error.message); - return []; - } + // WICHTIG: Fehler NICHT zu [] verschlucken. Ein leeres Array bedeutet + // "Instanz hat 0 Studios" → das Frontend zeigt dann den Registrierungs-/ + // Init-Screen. Ein Netzwerk-/API-Fehler (Kong down, Port 8000 nicht + // erreichbar) ist aber NICHT dasselbe wie "leer" — würden wir hier [] + // zurückgeben, landet ein eingeloggter User nach Reload fälschlich im + // Init-Flow. Daher: werfen und den Caller entscheiden lassen. + if (error) throw new Error("listStudios: " + error.message); return data || []; }