From 54fe425b3cb3c825a5bea39ad45b8b14c08983c9 Mon Sep 17 00:00:00 2001 From: Godopu Date: Tue, 25 Aug 2026 14:42:26 +0900 Subject: [PATCH] fix(console): fix stuck authentication check and add reliable redirect to /console/login - Add immediate redirection to /console/login when unauthenticated in AdminLayout - Add timeout (4000ms) with AbortController in adminApi.ts to prevent infinite pending fetch - Provide explicit sign-in link in layout fallback view --- refer_landing_page/app/console/layout.tsx | 42 +++++++++++++++++------ refer_landing_page/lib/adminApi.ts | 39 +++++++++++++-------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/refer_landing_page/app/console/layout.tsx b/refer_landing_page/app/console/layout.tsx index c950248..b68a9f9 100644 --- a/refer_landing_page/app/console/layout.tsx +++ b/refer_landing_page/app/console/layout.tsx @@ -13,14 +13,17 @@ export default function AdminLayout({ children }: { children: React.ReactNode }) useEffect(() => { let isMounted = true; + async function checkAuth() { + if (pathname === "/console/login") { + if (isMounted) setIsAuthenticated(false); + return; + } + const token = getClientToken(); if (!token) { - if (pathname !== "/console/login") { - router.push("/console/login"); - } else { - setIsAuthenticated(false); - } + if (isMounted) setIsAuthenticated(false); + router.replace("/console/login"); return; } @@ -29,11 +32,8 @@ export default function AdminLayout({ children }: { children: React.ReactNode }) if (!isValid) { removeClientToken(); - if (pathname !== "/console/login") { - router.push("/console/login"); - } else { - setIsAuthenticated(false); - } + setIsAuthenticated(false); + router.replace("/console/login"); } else { setIsAuthenticated(true); } @@ -51,8 +51,28 @@ export default function AdminLayout({ children }: { children: React.ReactNode }) if (isAuthenticated === null) { return ( -
+
Checking authentication...
+ + Click here to sign in + +
+ ); + } + + if (isAuthenticated === false) { + return ( +
+
Redirecting to login...
+ + Go to Sign In Page +
); } diff --git a/refer_landing_page/lib/adminApi.ts b/refer_landing_page/lib/adminApi.ts index 4cd51ec..f911eaf 100644 --- a/refer_landing_page/lib/adminApi.ts +++ b/refer_landing_page/lib/adminApi.ts @@ -153,23 +153,32 @@ async function request( const baseUrl = getAdminApiBaseUrl(); const url = `${baseUrl}${endpoint}`; - const response = await fetch(url, { - ...options, - headers, - cache: "no-store", - }); + + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 4000); - if (response.status === 204) { - return {} as T; + try { + const response = await fetch(url, { + ...options, + headers, + signal: controller.signal, + cache: "no-store", + }); + + if (response.status === 204) { + return {} as T; + } + + const json = await response.json().catch(() => ({})); + if (!response.ok) { + const errorMsg = json?.error?.message || `Request failed with status ${response.status}`; + throw new Error(errorMsg); + } + + return json.data; + } finally { + clearTimeout(timeoutId); } - - const json = await response.json().catch(() => ({})); - if (!response.ok) { - const errorMsg = json?.error?.message || `Request failed with status ${response.status}`; - throw new Error(errorMsg); - } - - return json.data; } // 0. Auth Verification