72 lines
1.9 KiB
TypeScript
72 lines
1.9 KiB
TypeScript
"use client";
|
|
|
|
import { useRouter, usePathname } from "next/navigation";
|
|
import { Loader2 } from "lucide-react";
|
|
import { useEffect } from "react";
|
|
import { useAuthSession } from "@/shared/hooks/use-session";
|
|
import { adminRoutePermissions } from "@/shared/config/route-permission-map";
|
|
import { hasPermission } from "@/shared/config/role";
|
|
import { roles } from "@/shared/config/role";
|
|
|
|
export default function AdminRouteGuard({
|
|
children,
|
|
}: Readonly<{
|
|
children: React.ReactNode;
|
|
}>) {
|
|
const router = useRouter();
|
|
const pathname = usePathname();
|
|
const isAdminRoute = pathname.startsWith("/admin");
|
|
|
|
const { session, status } = useAuthSession(true);
|
|
const role = session?.user?.role;
|
|
|
|
const redirectPath = role
|
|
? roles[role.name]?.redirectTo
|
|
: "/auth/admin/login";
|
|
|
|
const matched = Object.entries(adminRoutePermissions).find(([route]) =>
|
|
pathname.startsWith(route)
|
|
);
|
|
|
|
const menu = matched?.[1]?.menu;
|
|
const permission = matched?.[1]?.permission;
|
|
|
|
const isAllowed =
|
|
pathname === "/admin" ||
|
|
(role && menu && permission
|
|
? hasPermission(role, menu, permission)
|
|
: false);
|
|
|
|
useEffect(() => {
|
|
if (isAdminRoute && status === "unauthenticated") {
|
|
router.push(
|
|
`/auth/admin/login?callbackUrl=${encodeURIComponent(pathname)}`
|
|
);
|
|
}
|
|
}, [isAdminRoute, pathname, router, status]);
|
|
|
|
useEffect(() => {
|
|
if (
|
|
status === "authenticated" &&
|
|
!isAllowed &&
|
|
isAdminRoute &&
|
|
pathname !== redirectPath
|
|
) {
|
|
router.push(redirectPath);
|
|
}
|
|
}, [status, isAllowed, isAdminRoute, router, redirectPath, pathname]);
|
|
|
|
if (
|
|
isAdminRoute &&
|
|
(status === "loading" || (status === "unauthenticated" && !isAllowed))
|
|
) {
|
|
return (
|
|
<div className="flex items-center justify-center h-screen">
|
|
<Loader2 className="w-6 h-6 animate-spin" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return <>{children}</>;
|
|
}
|