| |
|
|
| const STORAGE_KEY = 'hf_oauth_token'; |
| const SESSION_KEY = 'hf_session_token'; |
| const USER_INFO_KEY = 'hf_user_info'; |
| const DEV_MODE_KEY = 'hf_dev_mode'; |
| const API_BASE = '/api'; |
|
|
| |
| const isDevelopment = typeof window !== 'undefined' && |
| (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'); |
|
|
| export interface OAuthUserInfo { |
| id?: string; |
| sub?: string; |
| name: string; |
| preferred_username?: string; |
| preferredUsername?: string; |
| picture?: string; |
| avatarUrl?: string; |
| } |
|
|
| export interface OAuthResult { |
| accessToken: string; |
| accessTokenExpiresAt: Date; |
| userInfo: OAuthUserInfo; |
| } |
|
|
| |
| |
| |
| |
| export async function initializeOAuth(): Promise<OAuthResult | null> { |
| try { |
| |
| if (isDevelopment && isDevModeEnabled()) { |
| const storedToken = getStoredToken(); |
| const storedUserInfo = getStoredUserInfo(); |
| |
| if (storedToken && storedUserInfo) { |
| return { |
| accessToken: storedToken, |
| accessTokenExpiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), |
| userInfo: storedUserInfo, |
| }; |
| } |
| return null; |
| } |
| |
| |
| const urlParams = new URLSearchParams(window.location.search); |
| const sessionToken = urlParams.get('session'); |
| |
| if (sessionToken) { |
| |
| try { |
| const response = await fetch(`${API_BASE}/auth/session?session=${sessionToken}`); |
| if (response.ok) { |
| const data = await response.json(); |
| |
| |
| const userInfo: OAuthUserInfo = { |
| id: data.user_info.sub || data.user_info.id, |
| name: data.user_info.name, |
| preferredUsername: data.user_info.preferred_username || data.user_info.preferredUsername, |
| avatarUrl: data.user_info.picture || data.user_info.avatarUrl, |
| }; |
| |
| const oauthResult: OAuthResult = { |
| accessToken: data.access_token, |
| accessTokenExpiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), |
| userInfo, |
| }; |
| |
| |
| storeOAuthData(oauthResult); |
| storeSessionToken(sessionToken); |
| |
| |
| window.history.replaceState({}, document.title, window.location.pathname); |
| |
| return oauthResult; |
| } |
| } catch (error) { |
| console.error('Failed to fetch session:', error); |
| } |
| } |
| |
| |
| const storedToken = getStoredToken(); |
| const storedUserInfo = getStoredUserInfo(); |
| |
| if (storedToken && storedUserInfo) { |
| return { |
| accessToken: storedToken, |
| accessTokenExpiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), |
| userInfo: storedUserInfo, |
| }; |
| } |
| |
| return null; |
| } catch (error) { |
| console.error('OAuth initialization error:', error); |
| return null; |
| } |
| } |
|
|
| |
| |
| |
| export async function loginWithHuggingFace(): Promise<void> { |
| try { |
| |
| const response = await fetch(`${API_BASE}/auth/login`); |
| if (!response.ok) { |
| throw new Error('Failed to get login URL'); |
| } |
| |
| const data = await response.json(); |
| |
| window.location.href = data.login_url; |
| } catch (error) { |
| console.error('Failed to initiate OAuth login:', error); |
| throw new Error('Failed to start login process'); |
| } |
| } |
|
|
| |
| |
| |
| export function logout(): void { |
| if (typeof window !== 'undefined') { |
| localStorage.removeItem(STORAGE_KEY); |
| localStorage.removeItem(SESSION_KEY); |
| localStorage.removeItem(USER_INFO_KEY); |
| localStorage.removeItem(DEV_MODE_KEY); |
| } |
| } |
|
|
| |
| |
| |
| function storeOAuthData(result: OAuthResult): void { |
| if (typeof window !== 'undefined') { |
| localStorage.setItem(STORAGE_KEY, result.accessToken); |
| localStorage.setItem(USER_INFO_KEY, JSON.stringify(result.userInfo)); |
| } |
| } |
|
|
| |
| |
| |
| function storeSessionToken(sessionToken: string): void { |
| if (typeof window !== 'undefined') { |
| localStorage.setItem(SESSION_KEY, sessionToken); |
| } |
| } |
|
|
| |
| |
| |
| export function getStoredSessionToken(): string | null { |
| if (typeof window !== 'undefined') { |
| return localStorage.getItem(SESSION_KEY); |
| } |
| return null; |
| } |
|
|
| |
| |
| |
| export function getStoredToken(): string | null { |
| if (typeof window !== 'undefined') { |
| return localStorage.getItem(STORAGE_KEY); |
| } |
| return null; |
| } |
|
|
| |
| |
| |
| export function getStoredUserInfo(): OAuthUserInfo | null { |
| if (typeof window !== 'undefined') { |
| const userInfoStr = localStorage.getItem(USER_INFO_KEY); |
| if (userInfoStr) { |
| try { |
| return JSON.parse(userInfoStr); |
| } catch { |
| return null; |
| } |
| } |
| } |
| return null; |
| } |
|
|
| |
| |
| |
| export function isAuthenticated(): boolean { |
| return getStoredToken() !== null; |
| } |
|
|
| |
| |
| |
| |
| export async function validateAuthentication(): Promise<boolean> { |
| const token = getStoredToken(); |
| if (!token) { |
| return false; |
| } |
|
|
| |
| if (isDevelopment && token.startsWith('dev_token_')) { |
| return true; |
| } |
|
|
| try { |
| const response = await fetch(`${API_BASE}/auth/status`, { |
| headers: { |
| 'Authorization': `Bearer ${token}`, |
| }, |
| }); |
|
|
| if (response.status === 401) { |
| |
| logout(); |
| return false; |
| } |
|
|
| if (!response.ok) { |
| return false; |
| } |
|
|
| const data = await response.json(); |
| return data.authenticated === true; |
| } catch (error) { |
| console.error('Failed to validate authentication:', error); |
| return false; |
| } |
| } |
|
|
| |
| |
| |
| export function loginDevMode(username: string): OAuthResult { |
| const mockToken = `dev_token_${username}_${Date.now()}`; |
| const mockUserInfo: OAuthUserInfo = { |
| id: `dev_${Date.now()}`, |
| name: username, |
| preferredUsername: username.toLowerCase().replace(/\s+/g, '_'), |
| avatarUrl: `https://ui-avatars.com/api/?name=${encodeURIComponent(username)}&background=random&size=128`, |
| }; |
| |
| const result: OAuthResult = { |
| accessToken: mockToken, |
| accessTokenExpiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), |
| userInfo: mockUserInfo, |
| }; |
| |
| |
| storeOAuthData(result); |
| |
| if (typeof window !== 'undefined') { |
| localStorage.setItem(DEV_MODE_KEY, 'true'); |
| } |
| |
| return result; |
| } |
|
|
| |
| |
| |
| export function isDevModeEnabled(): boolean { |
| if (typeof window !== 'undefined') { |
| return localStorage.getItem(DEV_MODE_KEY) === 'true'; |
| } |
| return false; |
| } |
|
|
| |
| |
| |
| export function isDevelopmentMode(): boolean { |
| return isDevelopment; |
| } |
|
|
|
|