89 lines
2.8 KiB
JavaScript
89 lines
2.8 KiB
JavaScript
import { useState, useEffect, useRef } from 'react';
|
|
import { auth, setAuthErrorHandler } from '../utils/api';
|
|
|
|
export function useAuth() {
|
|
const [user, setUser] = useState(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const userRef = useRef(user);
|
|
|
|
// Keep userRef in sync with user state
|
|
useEffect(() => {
|
|
userRef.current = user;
|
|
}, [user]);
|
|
|
|
const checkAuth = async () => {
|
|
try {
|
|
const userData = await auth.getMe();
|
|
setUser(userData);
|
|
setLoading(false);
|
|
return userData; // Return user data for verification
|
|
} catch (error) {
|
|
// If 401/403, user is not authenticated
|
|
// Check if it's an auth error
|
|
if (error.message && (error.message.includes('Unauthorized') || error.message.includes('401') || error.message.includes('403'))) {
|
|
setUser(null);
|
|
setLoading(false);
|
|
throw error; // Re-throw to allow caller to handle
|
|
} else {
|
|
// Other errors (network, etc.) - don't log out, just re-throw
|
|
// This prevents network issues from logging users out
|
|
setLoading(false);
|
|
throw error; // Re-throw to allow caller to handle
|
|
}
|
|
}
|
|
};
|
|
|
|
const logout = async () => {
|
|
try {
|
|
await auth.logout();
|
|
} catch (error) {
|
|
console.error('Logout error:', error);
|
|
} finally {
|
|
// Refresh the page to show login
|
|
window.location.reload();
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
// Set up global auth error handler
|
|
setAuthErrorHandler(() => {
|
|
setUser(null);
|
|
setLoading(false);
|
|
});
|
|
|
|
// Listen for auth errors from API calls
|
|
const handleAuthErrorEvent = () => {
|
|
setUser(null);
|
|
setLoading(false);
|
|
};
|
|
window.addEventListener('auth-error', handleAuthErrorEvent);
|
|
|
|
// Initial auth check
|
|
checkAuth();
|
|
|
|
// Periodic auth check every 10 seconds
|
|
const authInterval = setInterval(() => {
|
|
// Use ref to check current user state without dependency
|
|
if (userRef.current) {
|
|
// Only check if we have a user (don't spam when logged out)
|
|
checkAuth().catch((error) => {
|
|
// Only log out if it's actually an auth error, not a network error
|
|
// Network errors shouldn't log the user out
|
|
if (error.message && (error.message.includes('Unauthorized') || error.message.includes('401') || error.message.includes('403'))) {
|
|
// This is a real auth error - user will be set to null by checkAuth
|
|
}
|
|
// For other errors (network, etc.), don't log out - just silently fail
|
|
});
|
|
}
|
|
}, 10000); // 10 seconds
|
|
|
|
return () => {
|
|
window.removeEventListener('auth-error', handleAuthErrorEvent);
|
|
clearInterval(authInterval);
|
|
};
|
|
}, []); // Empty deps - only run on mount/unmount
|
|
|
|
return { user, loading, logout, refresh: checkAuth };
|
|
}
|
|
|