Spaces:
Running
Running
| import React, { createContext, useContext, useState, useEffect } from 'react'; | |
| import axios from 'axios'; | |
| const AuthContext = createContext(); | |
| export const useAuth = () => useContext(AuthContext); | |
| export const AuthProvider = ({ children }) => { | |
| const [user, setUser] = useState(null); | |
| const [loading, setLoading] = useState(true); | |
| const API_URL = import.meta.env.VITE_API_URL; | |
| // Keep HF Space alive — ping every 25 minutes to prevent sleeping | |
| useEffect(() => { | |
| const ping = () => axios.get(`${API_URL}/users`).catch(() => {}); | |
| ping(); // initial ping on load | |
| const interval = setInterval(ping, 25 * 60 * 1000); | |
| return () => clearInterval(interval); | |
| }, []); | |
| useEffect(() => { | |
| const initializeAuth = async () => { | |
| console.log('[Auth] Initializing authentication...'); | |
| const token = localStorage.getItem('token'); | |
| if (token) { | |
| console.log('[Auth] Found token in localStorage, setting Authorization header.'); | |
| axios.defaults.headers.common['Authorization'] = `Bearer ${token}`; | |
| try { | |
| console.log('[Auth] Fetching user profile from:', `${API_URL}/users/me`); | |
| const response = await axios.get(`${API_URL}/users/me`); | |
| console.log('[Auth] Profile fetched successfully:', response.data); | |
| setUser(response.data); | |
| } catch (error) { | |
| console.error('[Auth] Failed to fetch profile:', error); | |
| // Only logout on explicit authorization failures (e.g. 401, 403). Keep session on server network errors. | |
| if (error.response && (error.response.status === 401 || error.response.status === 403 || error.response.status === 404)) { | |
| console.warn('[Auth] Token is expired, invalid, or user was not found on server. Logging out.'); | |
| logout(); | |
| } else { | |
| console.warn('[Auth] Server is unreachable or returned network error. Retaining session.'); | |
| const cachedUser = localStorage.getItem('user'); | |
| if (cachedUser) { | |
| try { | |
| const parsed = JSON.parse(cachedUser); | |
| console.log('[Auth] Loaded cached user from localStorage:', parsed); | |
| setUser(parsed); | |
| } catch (parseErr) { | |
| console.error('[Auth] Failed to parse cached user:', parseErr); | |
| logout(); | |
| } | |
| } | |
| } | |
| } | |
| } else { | |
| console.log('[Auth] No token found in localStorage.'); | |
| } | |
| setLoading(false); | |
| }; | |
| initializeAuth(); | |
| }, []); | |
| const login = async (email, password) => { | |
| try { | |
| const response = await axios.post(`${API_URL}/users/login`, { email, password }); | |
| handleAuthResponse(response.data); | |
| return { success: true }; | |
| } catch (error) { | |
| return { success: false, message: error.response?.data?.message || 'Login failed' }; | |
| } | |
| }; | |
| const register = async (email, password, displayName) => { | |
| try { | |
| const response = await axios.post(`${API_URL}/users/register`, { email, password, displayName }); | |
| handleAuthResponse(response.data); | |
| return { success: true }; | |
| } catch (error) { | |
| return { success: false, message: error.response?.data?.message || 'Registration failed' }; | |
| } | |
| }; | |
| const googleLogin = async (idToken) => { | |
| try { | |
| const response = await axios.post(`${API_URL}/users/google-login`, { idToken }); | |
| handleAuthResponse(response.data); | |
| return { success: true }; | |
| } catch (error) { | |
| return { success: false, message: error.response?.data?.message || 'Google Login failed' }; | |
| } | |
| }; | |
| const logout = () => { | |
| setUser(null); | |
| localStorage.removeItem('user'); | |
| localStorage.removeItem('token'); | |
| delete axios.defaults.headers.common['Authorization']; | |
| }; | |
| const updateUser = (updatedUser) => { | |
| setUser(updatedUser); | |
| localStorage.setItem('user', JSON.stringify(updatedUser)); | |
| }; | |
| const handleAuthResponse = (data) => { | |
| const { user, token } = data; | |
| setUser(user); | |
| localStorage.setItem('user', JSON.stringify(user)); | |
| localStorage.setItem('token', token); | |
| axios.defaults.headers.common['Authorization'] = `Bearer ${token}`; | |
| }; | |
| return ( | |
| <AuthContext.Provider value={{ user, loading, login, register, googleLogin, logout, updateUser }}> | |
| {!loading && children} | |
| </AuthContext.Provider> | |
| ); | |
| }; | |