Files
Stirling-PDF/frontend/shared/auth/guards/RequireAdmin.tsx
T
James BruntonandGitHub 1816bad1ba Unified auth for portal and editor (#6725)
# Description of Changes
Refactor frontend auth to the shared folder and hook it up to both the
portal and editor so they share the same system. Also adds various tasks
to help run the portal, including `task dev:portal` to spawn the portal
with the backend, and `task dev:portal:proxy` to spawn the editor,
portal and backend, and a reverse proxy (at localhost:3000) to allow you
to use both at once to simulate how this will actually be deployed,
allowing you to check whether the seamless transition between the two
actually works.
2026-06-22 16:22:36 +00:00

43 lines
1.3 KiB
TypeScript

/**
* Gate that renders its children only for an authenticated admin.
*
* - Still loading -> `loading`
* - Signed out -> `fallback` (login screen)
* - Signed in but not admin -> calls `onForbidden` (e.g. redirect to the
* editor) and renders `forbidden` in the meantime
*/
import { useEffect, type ReactNode } from "react";
import { useAuth } from "@shared/auth/context";
export interface RequireAdminProps {
children: ReactNode;
/** Rendered when there is no session (e.g. the login panel). */
fallback: ReactNode;
/** Invoked once when an authenticated non-admin is detected. */
onForbidden: () => void;
/** Rendered while the session is still resolving. */
loading?: ReactNode;
/** Rendered for an authenticated non-admin (while `onForbidden` runs). */
forbidden?: ReactNode;
}
export function RequireAdmin({
children,
fallback,
onForbidden,
loading = null,
forbidden = null,
}: RequireAdminProps) {
const { session, loading: isLoading, isAdmin } = useAuth();
const shouldRedirect = !isLoading && !!session && !isAdmin;
useEffect(() => {
if (shouldRedirect) onForbidden();
}, [shouldRedirect, onForbidden]);
if (isLoading) return <>{loading}</>;
if (!session) return <>{fallback}</>;
if (!isAdmin) return <>{forbidden}</>;
return <>{children}</>;
}