ERP-node/frontend/components/auth/AuthGuard.tsx

187 lines
5.7 KiB
TypeScript
Raw Normal View History

2025-08-21 09:41:46 +09:00
"use client";
import { useEffect, ReactNode, useState } from "react";
2025-08-21 09:41:46 +09:00
import { useRouter } from "next/navigation";
import { useAuth } from "@/hooks/useAuth";
interface AuthGuardProps {
children: ReactNode;
requireAuth?: boolean;
requireAdmin?: boolean;
redirectTo?: string;
fallback?: ReactNode;
}
/**
*
*
*/
export function AuthGuard({
children,
requireAuth = true,
requireAdmin = false,
redirectTo = "/login",
fallback,
}: AuthGuardProps) {
const { isLoggedIn, isAdmin, loading, error } = useAuth();
const router = useRouter();
const [redirectCountdown, setRedirectCountdown] = useState<number | null>(null);
const [authDebugInfo, setAuthDebugInfo] = useState<any>({});
2025-08-21 09:41:46 +09:00
useEffect(() => {
console.log("=== AuthGuard 디버깅 ===");
console.log("requireAuth:", requireAuth);
console.log("requireAdmin:", requireAdmin);
console.log("loading:", loading);
console.log("isLoggedIn:", isLoggedIn);
console.log("isAdmin:", isAdmin);
console.log("error:", error);
// 토큰 확인을 더 정확하게
const token = localStorage.getItem("authToken");
console.log("AuthGuard localStorage 토큰:", token ? "존재" : "없음");
console.log("현재 경로:", window.location.pathname);
// 디버깅 정보 수집
setAuthDebugInfo({
requireAuth,
requireAdmin,
loading,
isLoggedIn,
isAdmin,
error,
hasToken: !!token,
currentPath: window.location.pathname,
timestamp: new Date().toISOString(),
tokenLength: token ? token.length : 0,
});
if (loading) {
console.log("AuthGuard: 로딩 중 - 대기");
return;
}
// 토큰이 있는데도 인증이 안 된 경우, 잠시 대기
if (token && !isLoggedIn && !loading) {
console.log("AuthGuard: 토큰은 있지만 인증이 안됨 - 잠시 대기");
return;
}
2025-08-21 09:41:46 +09:00
// 인증이 필요한데 로그인되지 않은 경우
if (requireAuth && !isLoggedIn) {
console.log("AuthGuard: 인증 필요하지만 로그인되지 않음 - 5초 후 리다이렉트");
console.log("리다이렉트 대상:", redirectTo);
setRedirectCountdown(5);
const countdownInterval = setInterval(() => {
setRedirectCountdown((prev) => {
if (prev === null || prev <= 1) {
clearInterval(countdownInterval);
router.push(redirectTo);
return null;
}
return prev - 1;
});
}, 1000);
2025-08-21 09:41:46 +09:00
return;
}
// 관리자 권한이 필요한데 관리자가 아닌 경우
if (requireAdmin && !isAdmin) {
console.log("AuthGuard: 관리자 권한 필요하지만 관리자가 아님 - 5초 후 리다이렉트");
console.log("리다이렉트 대상:", redirectTo);
setRedirectCountdown(5);
const countdownInterval = setInterval(() => {
setRedirectCountdown((prev) => {
if (prev === null || prev <= 1) {
clearInterval(countdownInterval);
router.push(redirectTo);
return null;
}
return prev - 1;
});
}, 1000);
2025-08-21 09:41:46 +09:00
return;
}
console.log("AuthGuard: 모든 인증 조건 통과 - 컴포넌트 렌더링");
}, [requireAuth, requireAdmin, loading, isLoggedIn, isAdmin, error, redirectTo, router]);
// 로딩 중일 때 fallback 또는 기본 로딩 표시
2025-08-21 09:41:46 +09:00
if (loading) {
console.log("AuthGuard: 로딩 중 - fallback 표시");
2025-08-21 09:41:46 +09:00
return (
<div>
<div className="mb-4 rounded bg-primary/20 p-4">
<h3 className="font-bold">AuthGuard ...</h3>
<pre className="text-xs">{JSON.stringify(authDebugInfo, null, 2)}</pre>
2025-08-21 09:41:46 +09:00
</div>
{fallback || <div> ...</div>}
</div>
2025-08-21 09:41:46 +09:00
);
}
// 인증 실패 시 fallback 또는 기본 메시지 표시
if (requireAuth && !isLoggedIn) {
console.log("AuthGuard: 인증 실패 - fallback 표시");
2025-08-21 09:41:46 +09:00
return (
<div>
<div className="mb-4 rounded bg-destructive/20 p-4">
<h3 className="font-bold"> </h3>
{redirectCountdown !== null && (
<div className="mb-2 text-destructive">
<strong> :</strong> {redirectCountdown} {redirectTo}
</div>
)}
<pre className="text-xs">{JSON.stringify(authDebugInfo, null, 2)}</pre>
2025-08-21 09:41:46 +09:00
</div>
{fallback || <div> .</div>}
2025-08-21 09:41:46 +09:00
</div>
);
}
if (requireAdmin && !isAdmin) {
console.log("AuthGuard: 관리자 권한 없음 - fallback 표시");
2025-08-21 09:41:46 +09:00
return (
<div>
<div className="mb-4 rounded bg-orange-100 p-4">
<h3 className="font-bold"> </h3>
{redirectCountdown !== null && (
<div className="mb-2 text-destructive">
<strong> :</strong> {redirectCountdown} {redirectTo}
</div>
)}
<pre className="text-xs">{JSON.stringify(authDebugInfo, null, 2)}</pre>
2025-08-21 09:41:46 +09:00
</div>
{fallback || <div> .</div>}
2025-08-21 09:41:46 +09:00
</div>
);
}
console.log("AuthGuard: 인증 성공 - 자식 컴포넌트 렌더링");
2025-08-21 09:41:46 +09:00
return <>{children}</>;
}
/**
*
*/
export function RequireAuth({ children }: { children: ReactNode }) {
return <AuthGuard requireAuth={true}>{children}</AuthGuard>;
}
/**
*
*/
export function RequireAdmin({ children }: { children: ReactNode }) {
return (
<AuthGuard requireAuth={true} requireAdmin={true}>
{children}
</AuthGuard>
);
}
export default AuthGuard;