at main 2.0 kB view raw
1// auth state management using Svelte 5 runes 2import { browser } from '$app/environment'; 3import { API_URL } from '$lib/config'; 4import { toast } from '$lib/toast.svelte'; 5import type { User } from '$lib/types'; 6 7export interface AuthState { 8 user: User | null; 9 isAuthenticated: boolean; 10 loading: boolean; 11 scopeUpgradeRequired: boolean; 12} 13 14class AuthManager { 15 user = $state<User | null>(null); 16 isAuthenticated = $state(false); 17 loading = $state(true); 18 scopeUpgradeRequired = $state(false); 19 20 async initialize(): Promise<void> { 21 if (!browser) { 22 this.loading = false; 23 return; 24 } 25 26 try { 27 const response = await fetch(`${API_URL}/auth/me`, { 28 credentials: 'include' 29 }); 30 31 if (response.ok) { 32 this.user = await response.json(); 33 this.isAuthenticated = true; 34 this.scopeUpgradeRequired = false; 35 } else if (response.status === 403) { 36 // check if this is a scope upgrade requirement 37 const data = await response.json().catch(() => ({})); 38 if (data.detail === 'scope_upgrade_required') { 39 this.scopeUpgradeRequired = true; 40 this.clearSession(); 41 toast.info( 42 "plyr.fm's permissions have changed since you logged in. please log in again", 43 5000, 44 { label: 'see changes', href: 'https://github.com/zzstoatzz/plyr.fm/releases/latest' } 45 ); 46 } else { 47 this.clearSession(); 48 } 49 } else { 50 this.clearSession(); 51 } 52 } catch (e) { 53 console.error('auth check failed:', e); 54 this.clearSession(); 55 } finally { 56 this.loading = false; 57 } 58 } 59 60 clearSession(): void { 61 if (!browser) return; 62 this.user = null; 63 this.isAuthenticated = false; 64 } 65 66 async logout(): Promise<void> { 67 try { 68 await fetch(`${API_URL}/auth/logout`, { 69 method: 'POST', 70 credentials: 'include' 71 }); 72 } catch (e) { 73 console.error('logout failed:', e); 74 } 75 this.clearSession(); 76 } 77 78 getAuthHeaders(): Record<string, string> { 79 return {}; 80 } 81} 82 83export const auth = new AuthManager();