Spaces:
Sleeping
Sleeping
File size: 2,805 Bytes
1e6a9db | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | import { useEffect, useState } from 'react';
import { BrowserRouter, Routes, Route, Navigate, useNavigate, useLocation } from 'react-router-dom';
import { MainApp } from './pages/MainApp';
import { Login } from './pages/Login';
import { Settings } from './pages/Settings';
import { isAuthenticated, getCurrentUser, setAuthTokenFromHash } from './services/auth';
import './App.css';
// Protected route wrapper with auth check
function ProtectedRoute({ children }: { children: React.ReactNode }) {
const navigate = useNavigate();
const location = useLocation();
const [isChecking, setIsChecking] = useState(true);
const [hasToken, setHasToken] = useState<boolean>(isAuthenticated());
// T110: Check if user is authenticated on mount
useEffect(() => {
const checkAuth = async () => {
// Check for OAuth callback token in URL hash
const tokenExtracted = setAuthTokenFromHash();
if (tokenExtracted) {
console.log('OAuth token extracted from URL hash');
setHasToken(true);
setIsChecking(false);
return;
}
if (!isAuthenticated()) {
setHasToken(false);
setIsChecking(false);
return;
}
setHasToken(true);
const token = localStorage.getItem('auth_token');
// Skip validation for local dev token
if (token === 'local-dev-token') {
setIsChecking(false);
return;
}
try {
// Verify the token is valid by calling getCurrentUser
await getCurrentUser();
setIsChecking(false);
} catch (err) {
// Token is invalid (401), redirect to login
console.warn('Authentication failed, redirecting to login');
localStorage.removeItem('auth_token');
setHasToken(false);
setIsChecking(false);
if (location.pathname !== '/login') {
navigate('/login', { replace: true, state: { from: location } });
}
}
};
checkAuth();
}, [navigate, location]);
if (isChecking) {
return (
<div className="h-screen flex items-center justify-center bg-background">
<div className="text-muted-foreground">Loading...</div>
</div>
);
}
if (!hasToken) {
return <Navigate to="/login" replace />;
}
return <>{children}</>;
}
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/login" element={<Login />} />
<Route
path="/"
element={
<ProtectedRoute>
<MainApp />
</ProtectedRoute>
}
/>
<Route
path="/settings"
element={
<ProtectedRoute>
<Settings />
</ProtectedRoute>
}
/>
</Routes>
</BrowserRouter>
);
}
export default App;
|