'use client' import { useEffect } from 'react' import { useRouter } from './contexts/RouterContext' import { useAllauthConfig } from './contexts/ConfigContext' import { useAuth, useUser, useConfig } from './contexts/AuthContext' /** * Route guard that only renders children if the user is authenticated. * Redirects to login page if not authenticated. */ export function UserRoute({ children }: { children: React.ReactNode }) { const router = useRouter() const config = useAllauthConfig() const { isAuthenticated } = useAuth() useEffect(() => { if (!isAuthenticated) { const next = encodeURIComponent(router.pathname + router.searchParams.toString()) router.replace(`${config.routes.login}?next=${next}`) } }, [isAuthenticated, router, config.routes.login]) if (!isAuthenticated) return null return children } /** * Route guard that only renders children if the user is authenticated AND is staff. * Redirects to login if not authenticated, or to authenticated route if not staff. */ export function StaffRoute({ children }: { children: React.ReactNode }) { const router = useRouter() const config = useAllauthConfig() const { isAuthenticated } = useAuth() const user = useUser() useEffect(() => { if (!isAuthenticated) { const next = encodeURIComponent(router.pathname + router.searchParams.toString()) router.replace(`${config.routes.login}?next=${next}`) } else if (!user.is_staff) { router.replace(config.routes.authenticated) } }, [isAuthenticated, user.is_staff, router, config.routes]) if (!isAuthenticated || !user.is_staff) return null return children } /** * Route guard that only renders children if the user is NOT authenticated. * Redirects to authenticated route if already logged in. */ export function AnonymousRoute({ children }: { children: React.ReactNode }) { const router = useRouter() const config = useAllauthConfig() const { isAuthenticated } = useAuth() useEffect(() => { if (isAuthenticated) { router.replace(config.routes.authenticated) } }, [isAuthenticated, config.routes.authenticated, router]) if (isAuthenticated) return null return children } /** * Route guard that checks if a feature is enabled in the allauth config. * Redirects to fallback if feature is disabled. */ type FeatureKey = 'signup' | 'login_by_code' | 'mfa' | 'socialaccount' function isFeatureEnabled(config: any, feature: FeatureKey): boolean | undefined { if (!config?.data) return undefined switch (feature) { case 'signup': return config.data.account?.is_open_for_signup case 'login_by_code': return config.data.account?.login_by_code_enabled case 'mfa': return config.data.mfa !== undefined case 'socialaccount': return (config.data.socialaccount?.providers?.length ?? 0) > 0 } } export function FeatureRoute({ children, feature, redirectTo, }: { children: React.ReactNode feature: FeatureKey redirectTo?: string }) { const router = useRouter() const allauthConfig = useConfig() const config = useAllauthConfig() const enabled = isFeatureEnabled(allauthConfig, feature) const fallback = redirectTo ?? config.routes.login useEffect(() => { if (allauthConfig && enabled === false) { router.replace(fallback) } }, [allauthConfig, enabled, fallback, router]) if (!allauthConfig || enabled === false) return null return children }