From 422f9f0482b9ad621b9c5c50fcb21c0743dc46f1 Mon Sep 17 00:00:00 2001 From: Tim Disney Date: Tue, 24 Feb 2026 12:02:46 -0800 Subject: [PATCH] prompt to re-login on scope upgrade --- src/lib/services/api.ts | 9 +++++++ src/lib/stores/auth.svelte.ts | 13 +++++++++++ src/routes/+layout.svelte | 44 +++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/src/lib/services/api.ts b/src/lib/services/api.ts index a79abac..3eafde9 100644 --- a/src/lib/services/api.ts +++ b/src/lib/services/api.ts @@ -45,12 +45,18 @@ export class UrlSaveLimitError extends Error { class ApiClient { private onUnauthorized: (() => void) | null = null; + private onScopeUpgradeRequired: (() => void) | null = null; // Set callback for when 401 is received (session invalid) setOnUnauthorized(callback: () => void) { this.onUnauthorized = callback; } + // Set callback for when 403 scope_upgrade_required is received + setOnScopeUpgradeRequired(callback: () => void) { + this.onScopeUpgradeRequired = callback; + } + private async fetch(path: string, options: RequestInit = {}): Promise { const headers: HeadersInit = { 'Content-Type': 'application/json', @@ -78,6 +84,9 @@ class ApiClient { if (response.status === 403) { const body = await response.json().catch(() => ({ error: 'Forbidden' })); if ((body as { error: string }).error === 'scope_upgrade_required') { + if (this.onScopeUpgradeRequired) { + this.onScopeUpgradeRequired(); + } throw new ScopeUpgradeError((body as { message?: string }).message); } if ((body as { error: string }).error === 'url_save_limit_reached') { diff --git a/src/lib/stores/auth.svelte.ts b/src/lib/stores/auth.svelte.ts index 5279021..41e058e 100644 --- a/src/lib/stores/auth.svelte.ts +++ b/src/lib/stores/auth.svelte.ts @@ -8,6 +8,7 @@ interface AuthState { user: User | null; isLoading: boolean; error: string | null; + scopeUpgradeRequired: boolean; } function createAuthStore() { @@ -15,6 +16,7 @@ function createAuthStore() { user: null, isLoading: true, error: null, + scopeUpgradeRequired: false, }); // Handle 401 - session expired/invalid on the backend @@ -46,6 +48,11 @@ function createAuthStore() { // Set up 401 handler api.setOnUnauthorized(handleUnauthorized); + + // Set up scope upgrade handler + api.setOnScopeUpgradeRequired(() => { + state.scopeUpgradeRequired = true; + }); } // Set user after successful authentication @@ -114,6 +121,12 @@ function createAuthStore() { get error() { return state.error; }, + get scopeUpgradeRequired() { + return state.scopeUpgradeRequired; + }, + dismissScopeUpgrade() { + state.scopeUpgradeRequired = false; + }, setUser, verifySession, logout, diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 36ca718..22a602e 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -186,6 +186,16 @@
{#if !auth.isLoading} {#if auth.isAuthenticated} + {#if auth.scopeUpgradeRequired} +
+ Your session was created with outdated permissions. Please log in again to restore full functionality. + +
+ {/if}