From fd8105d30a9b77d4cd3e8333af18b78eea62cb52 Mon Sep 17 00:00:00 2001 From: IluaAir Date: Sun, 19 Oct 2025 00:14:34 +0300 Subject: [PATCH] Refactor Dashboard component to handle authentication errors and improve token validation logic --- taskncoffee-app/src/api/auth.service.js | 6 ++-- taskncoffee-app/src/lib/utils.js | 32 +++++++++++++++----- taskncoffee-app/src/main.jsx | 8 ++--- taskncoffee-app/src/pages/Dashboard.jsx | 40 +++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 15 deletions(-) diff --git a/taskncoffee-app/src/api/auth.service.js b/taskncoffee-app/src/api/auth.service.js index 2243ae2..a8f2e8f 100644 --- a/taskncoffee-app/src/api/auth.service.js +++ b/taskncoffee-app/src/api/auth.service.js @@ -84,7 +84,10 @@ export const login = async (username, password) => { export const refreshToken = async () => { try { - const response = await client.post(API_ENDPOINTS.AUTH.REFRESH); + const fingerprint = localStorage.getItem('fingerprint'); + const response = await client.post(API_ENDPOINTS.AUTH.REFRESH, { + fingerprint: fingerprint, + }); if (response.data.access_token && response.data.token_type === 'bearer') { localStorage.setItem('access_token', response.data.access_token); } @@ -92,7 +95,6 @@ export const refreshToken = async () => { } catch (error) { localStorage.removeItem('access_token'); localStorage.removeItem('fingerprint'); - cookies.remove('refresh_token'); throw error.response?.data || error.message; } }; \ No newline at end of file diff --git a/taskncoffee-app/src/lib/utils.js b/taskncoffee-app/src/lib/utils.js index 7df6a47..25211b5 100644 --- a/taskncoffee-app/src/lib/utils.js +++ b/taskncoffee-app/src/lib/utils.js @@ -7,22 +7,38 @@ export function cn(...inputs) { return twMerge(clsx(inputs)); } +let refreshPromise = null; + export async function jwtexp(token) { + console.log("jwtexp called from:", new Error().stack); const decoded = decode(token); const currentTime = Date.now() / 1000; const tokenExp = decoded.exp; + console.log("Token exp:", tokenExp, "Current time:", currentTime); + if (tokenExp < currentTime || tokenExp - currentTime < 120) { console.log("Token needs refresh"); - try { - await refreshToken(); - console.log("Token refreshed successfully"); - return true; - - } catch (error) { - console.error("Failed to refresh token:", error); - return false; + if (refreshPromise) { + console.log("Refresh already in progress, waiting..."); + return await refreshPromise; } + + refreshPromise = (async () => { + try { + console.log("Starting token refresh..."); + await refreshToken(); + console.log("Token refreshed successfully"); + return true; + } catch (error) { + console.error("Failed to refresh token:", error); + return false; + } finally { + refreshPromise = null; + } + })(); + + return await refreshPromise; } console.log("Token is valid"); diff --git a/taskncoffee-app/src/main.jsx b/taskncoffee-app/src/main.jsx index 560babb..c7b3634 100644 --- a/taskncoffee-app/src/main.jsx +++ b/taskncoffee-app/src/main.jsx @@ -5,9 +5,7 @@ import App from './App.jsx' import { BrowserRouter } from 'react-router' createRoot(document.getElementById('root')).render( - - - - - , + + + ) diff --git a/taskncoffee-app/src/pages/Dashboard.jsx b/taskncoffee-app/src/pages/Dashboard.jsx index 1b2ddd3..80ceecb 100644 --- a/taskncoffee-app/src/pages/Dashboard.jsx +++ b/taskncoffee-app/src/pages/Dashboard.jsx @@ -18,11 +18,32 @@ const menuItems = [ export default function Dashboard() { const [tasksFromBackend, setTasksFromBackend] = useState([]); const [loading, setLoading] = useState(true); + const [authError, setAuthError] = useState(false); // Fetch tasks useEffect(() => { + console.log('Dashboard useEffect triggered'); const fetchTasks = async () => { try { + console.log('Starting fetchTasks...'); + const token = localStorage.getItem('access_token'); + if (token) { + console.log('Token found, validating...'); + const isTokenValid = await jwtexp(token); + if (!isTokenValid) { + console.error('Token validation failed'); + setAuthError(true); + setLoading(false); + return; + } + } else { + console.error('No access token found'); + setAuthError(true); + setLoading(false); + return; + } + + console.log('Fetching user tasks...'); const response = await getUserTasks(1); console.log('Tasks from backend:', response); setTasksFromBackend(response); @@ -98,6 +119,25 @@ export default function Dashboard() { ); } + if (authError) { + return ( +
+
+
+

Authentication Error

+

Please log in again

+ +
+
+
+ ); + } + return (
{/* Navigation Rail - Material Design 3 */}