From faa9d14844952f72f572482be094a1ba63f72061 Mon Sep 17 00:00:00 2001 From: intergrav Date: Sun, 2 Aug 2026 02:23:09 -0400 Subject: [PATCH] fix: auth problems --- src/App.svelte | 4 ++++ src/lib/auth.svelte.ts | 13 +++++-------- src/lib/client.svelte.ts | 23 +++++++++++++++++------ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/App.svelte b/src/App.svelte index baceb35..ba14a34 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -51,6 +51,10 @@ let lastMode = offlineManager.isOfflineMode; $effect(() => { const currentMode = offlineManager.isOfflineMode; if (lastMode === currentMode) return; + if (!currentMode && auth.busy) { + lastMode = currentMode; + return; + } if (!currentMode) { if (auth.loggedIn) { diff --git a/src/lib/auth.svelte.ts b/src/lib/auth.svelte.ts index 79f6a00..238d872 100644 --- a/src/lib/auth.svelte.ts +++ b/src/lib/auth.svelte.ts @@ -104,6 +104,7 @@ export const login = async ( try { await tryAuth("token"); } catch (err) { + if (isNetworkError(err)) throw err; console.warn("token auth failed, trying cleartext:", err); await tryAuth("password"); } @@ -113,7 +114,9 @@ export const login = async ( } else { await api.forcePing(); } + offlineManager.setConnected(); await detectExtensions(); + await offlineManager.autoSyncQueuedRequests(); if (authMode === "apikey" && extensions.has("apikeyauthentication")) { try { @@ -129,7 +132,6 @@ export const login = async ( const admin = await loadSessionData(username); persistCredentials(); - offlineManager.setConnected(); Object.assign(auth, { server, user: username, loggedIn: true, admin }); return true; } catch (err) { @@ -142,15 +144,10 @@ export const login = async ( }; export const logout = async () => { - localStorage.clear(); + localStorage.removeItem("tinysub_credentials"); try { await offlineManager.wipeOfflineData(); offlineManager.closeOfflineStore(); - if (indexedDB.databases) { - for (const database of await indexedDB.databases()) { - if (database.name) indexedDB.deleteDatabase(database.name); - } - } } catch (err) { console.error("failed to wipe local cache on logout:", err); } @@ -158,7 +155,7 @@ export const logout = async () => { }; export const isOwner = (owner?: string | null) => - !owner || !auth.user || owner.toLowerCase() === auth.user.toLowerCase(); + !owner || (!!auth.user && owner.toLowerCase() === auth.user.toLowerCase()); export const reconnectSession = async () => { try { diff --git a/src/lib/client.svelte.ts b/src/lib/client.svelte.ts index df44682..3859e2c 100644 --- a/src/lib/client.svelte.ts +++ b/src/lib/client.svelte.ts @@ -223,11 +223,15 @@ const getParams = (params: Record = {}) => { let isOpenSubsonic = false; -export const isNetworkError = (err: unknown) => - err instanceof TypeError || - String(err).includes("Failed to fetch") || - String(err).includes("NetworkError") || - String(err).includes("ERR_INTERNET_DISCONNECTED"); +export const isNetworkError = (err: unknown) => { + const message = String(err); + return ( + message.includes("Failed to fetch") || + message.includes("Load failed") || + message.includes("NetworkError") || + message.includes("ERR_INTERNET_DISCONNECTED") + ); +}; const request = async ( method: string, @@ -248,7 +252,14 @@ const request = async ( } : {}, ); - const data = (await response.json())["subsonic-response"]; + if (!response.ok) { + throw new Error(`server returned HTTP ${response.status}`); + } + const body = await response.json(); + const data = body?.["subsonic-response"]; + if (!data || typeof data !== "object" || typeof data.status !== "string") { + throw new Error("invalid Subsonic response"); + } if (data.status === "failed") throw data.error?.message || "API error"; isOpenSubsonic = !!data.openSubsonic; return data; -- 2.51.2