Spaces:
Running
Running
| import { writable, get } from "svelte/store"; | |
| import { | |
| oauthLoginUrl, | |
| oauthHandleRedirectIfPresent, | |
| type UserInfo, | |
| } from "@huggingface/hub"; | |
| export interface AuthState { | |
| isAuthenticated: boolean; | |
| user: UserInfo | null; | |
| accessToken: string | null; | |
| expiresAt: number | null; | |
| loading: boolean; | |
| error: string | null; | |
| } | |
| function createAuthStore() { | |
| const { subscribe, set, update } = writable<AuthState>({ | |
| isAuthenticated: false, | |
| user: null, | |
| accessToken: null, | |
| expiresAt: null, | |
| loading: true, | |
| error: null, | |
| }); | |
| const getOAuthConfig = () => { | |
| const isProduction = window.location.hostname.includes("hf.space"); | |
| const clientId = "87f5f1d1-6e9e-4962-98f0-e5f3831ec988"; | |
| let redirectUrl: string; | |
| if (isProduction) { | |
| redirectUrl = `https://${window.location.hostname}/auth/callback`; | |
| } else { | |
| redirectUrl = `http://localhost:7860/auth/callback`; | |
| } | |
| return { | |
| clientId, | |
| redirectUrl, | |
| scopes: "openid profile inference-api", | |
| }; | |
| }; | |
| return { | |
| subscribe, | |
| async init() { | |
| update((state) => ({ ...state, loading: true })); | |
| try { | |
| const oauthResult = await oauthHandleRedirectIfPresent(); | |
| if (oauthResult) { | |
| const { accessToken, accessTokenExpiresAt, userInfo } = oauthResult; | |
| set({ | |
| isAuthenticated: true, | |
| user: userInfo, | |
| accessToken, | |
| expiresAt: accessTokenExpiresAt | |
| ? accessTokenExpiresAt.getTime() | |
| : null, | |
| loading: false, | |
| error: null, | |
| }); | |
| sessionStorage.setItem( | |
| "hf_auth", | |
| JSON.stringify({ | |
| accessToken, | |
| expiresAt: accessTokenExpiresAt | |
| ? accessTokenExpiresAt.getTime() | |
| : null, | |
| user: userInfo, | |
| }), | |
| ); | |
| return true; | |
| } | |
| const stored = sessionStorage.getItem("hf_auth"); | |
| if (stored) { | |
| const authData = JSON.parse(stored); | |
| if (!authData.expiresAt || authData.expiresAt > Date.now()) { | |
| set({ | |
| isAuthenticated: true, | |
| user: authData.user, | |
| accessToken: authData.accessToken, | |
| expiresAt: authData.expiresAt, | |
| loading: false, | |
| error: null, | |
| }); | |
| return true; | |
| } else { | |
| sessionStorage.removeItem("hf_auth"); | |
| } | |
| } | |
| set({ | |
| isAuthenticated: false, | |
| user: null, | |
| accessToken: null, | |
| expiresAt: null, | |
| loading: false, | |
| error: null, | |
| }); | |
| return false; | |
| } catch (error) { | |
| console.error("Auth initialization error:", error); | |
| set({ | |
| isAuthenticated: false, | |
| user: null, | |
| accessToken: null, | |
| expiresAt: null, | |
| loading: false, | |
| error: | |
| error instanceof Error ? error.message : "Authentication failed", | |
| }); | |
| return false; | |
| } | |
| }, | |
| async login() { | |
| const config = getOAuthConfig(); | |
| try { | |
| const url = await oauthLoginUrl({ | |
| clientId: config.clientId, | |
| redirectUrl: config.redirectUrl, | |
| scopes: config.scopes, | |
| }); | |
| window.location.href = url; | |
| } catch (error) { | |
| console.error("Login error:", error); | |
| update((state) => ({ | |
| ...state, | |
| error: error instanceof Error ? error.message : "Login failed", | |
| })); | |
| } | |
| }, | |
| logout() { | |
| sessionStorage.removeItem("hf_auth"); | |
| set({ | |
| isAuthenticated: false, | |
| user: null, | |
| accessToken: null, | |
| expiresAt: null, | |
| loading: false, | |
| error: null, | |
| }); | |
| }, | |
| getToken(): string | null { | |
| const state = get({ subscribe }); | |
| return state.accessToken; | |
| }, | |
| isTokenValid(): boolean { | |
| const state = get({ subscribe }); | |
| if (!state.accessToken) return false; | |
| if (!state.expiresAt) return true; | |
| return state.expiresAt > Date.now(); | |
| }, | |
| }; | |
| } | |
| export const authStore = createAuthStore(); | |