الملفات
back_end_oudelaa/oudelaa_dashboard/components/auth/auth-guard.tsx
boutmoun123 8863f61d00
فشلت بعض الفحوصات
Deploy To Ghaymah / deploy (push) Has been cancelled
Add Oudelaa dashboard API integration
2026-05-25 20:36:52 +03:00

176 أسطر
4.9 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { usePathname, useRouter } from "next/navigation";
import { SuperAdminSessionProvider } from "@/components/auth/session-context";
import { getSuperAdminSession } from "@/lib/api/superadmin";
import { refreshSuperAdmin } from "@/lib/auth/client";
import type { SuperAdminSessionResponse } from "@/types/api";
const RETRY_DELAY_MS = 5000;
function isRecoverableSessionError(error: unknown) {
const message = String(error).toLowerCase();
return [
"502",
"503",
"504",
"fetch failed",
"failed to fetch",
"econnrefused",
"timeout",
"network",
"upstream",
].some((token) => message.includes(token));
}
export function AuthGuard({ children }: { children: React.ReactNode }) {
const [ready, setReady] = useState(false);
const [sessionError, setSessionError] = useState<string | null>(null);
const [session, setSession] = useState<SuperAdminSessionResponse | null>(null);
const [retryNonce, setRetryNonce] = useState(0);
const [retryCountdown, setRetryCountdown] = useState<number | null>(null);
const router = useRouter();
const pathname = usePathname();
useEffect(() => {
let active = true;
let retryTimeout: number | null = null;
let countdownInterval: number | null = null;
const clearRetryTimers = () => {
if (retryTimeout) {
window.clearTimeout(retryTimeout);
retryTimeout = null;
}
if (countdownInterval) {
window.clearInterval(countdownInterval);
countdownInterval = null;
}
};
const scheduleRetry = () => {
clearRetryTimers();
setRetryCountdown(RETRY_DELAY_MS / 1000);
countdownInterval = window.setInterval(() => {
setRetryCountdown((value) => (value && value > 1 ? value - 1 : 1));
}, 1000);
retryTimeout = window.setTimeout(() => {
clearRetryTimers();
setRetryCountdown(null);
if (active) {
setRetryNonce((value) => value + 1);
}
}, RETRY_DELAY_MS);
};
const ensureSession = async () => {
try {
const nextSession = await getSuperAdminSession();
if (!active) {
return;
}
clearRetryTimers();
setSession(nextSession);
setSessionError(null);
setRetryCountdown(null);
setReady(true);
} catch (initialError) {
try {
const refreshed = await refreshSuperAdmin();
if (!refreshed) {
router.replace("/login");
return;
}
const nextSession = await getSuperAdminSession();
if (!active) {
return;
}
clearRetryTimers();
setSession(nextSession);
setSessionError(null);
setRetryCountdown(null);
setReady(true);
} catch (error) {
if (String(initialError).includes("401") || String(error).includes("401")) {
router.replace("/login");
return;
}
if (!active) {
return;
}
setSession(null);
setSessionError(String(error));
setReady(true);
if (isRecoverableSessionError(initialError) || isRecoverableSessionError(error)) {
scheduleRetry();
} else {
clearRetryTimers();
setRetryCountdown(null);
}
}
}
};
void ensureSession();
return () => {
active = false;
clearRetryTimers();
};
}, [router, pathname, retryNonce]);
if (!ready) {
return (
<div className="frame-panel mx-auto mt-10 w-full max-w-2xl p-6 text-sm text-muted-foreground">
Checking the current SuperAdmin session...
</div>
);
}
if (sessionError && !session) {
return (
<SuperAdminSessionProvider value={{ session: null, permissions: [] }}>
<div className="frame-panel mx-auto mt-10 w-full max-w-2xl space-y-4 p-6 text-sm text-muted-foreground">
<div>
The dashboard could not verify the current session, so permissions were not loaded.
Reload the page after the backend connection is available again.
</div>
<div className="break-words text-xs text-red-300">{sessionError}</div>
{retryCountdown !== null ? (
<div className="text-xs text-muted-foreground">
Retrying automatically in {retryCountdown}s...
</div>
) : null}
<button
type="button"
className="rounded-full border border-border px-4 py-2 text-foreground transition hover:bg-secondary"
onClick={() => {
setRetryCountdown(null);
setRetryNonce((value) => value + 1);
}}
>
Retry now
</button>
</div>
</SuperAdminSessionProvider>
);
}
return (
<SuperAdminSessionProvider value={{ session, permissions: session?.permissions ?? [] }}>
{children}
</SuperAdminSessionProvider>
);
}