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
This commit is contained in:
@@ -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 (
|
||||
<div className="min-h-screen bg-ivory text-ink flex items-center justify-center">
|
||||
<div className="min-h-screen bg-ivory text-ink flex flex-col items-center justify-center space-y-4">
|
||||
<div className="text-sm text-ink/70">Checking authentication...</div>
|
||||
<Link
|
||||
href="/console/login"
|
||||
className="text-xs text-cobalt underline hover:text-cobalt/80 font-mono"
|
||||
>
|
||||
Click here to sign in
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isAuthenticated === false) {
|
||||
return (
|
||||
<div className="min-h-screen bg-ivory text-ink flex flex-col items-center justify-center space-y-4">
|
||||
<div className="text-sm text-ink/70">Redirecting to login...</div>
|
||||
<Link
|
||||
href="/console/login"
|
||||
className="px-4 py-2 bg-cobalt text-white rounded text-sm font-medium hover:bg-cobalt/90"
|
||||
>
|
||||
Go to Sign In Page
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -153,23 +153,32 @@ async function request<T>(
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user