mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 17:31:13 -05:00
74 lines
2.1 KiB
TypeScript
74 lines
2.1 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import type { User } from '@supabase/supabase-js';
|
|
import { useAuth } from './useAuth';
|
|
import { useUserRole } from './useUserRole';
|
|
import { useRequireMFA } from './useRequireMFA';
|
|
|
|
export interface AdminGuardState {
|
|
/** Whether auth/role/MFA checks are still loading */
|
|
isLoading: boolean;
|
|
|
|
/** Whether user is authenticated and authorized */
|
|
isAuthorized: boolean;
|
|
|
|
/** Whether user needs to enroll in MFA */
|
|
needsMFA: boolean;
|
|
|
|
/** Current authenticated user */
|
|
user: User | null;
|
|
}
|
|
|
|
/**
|
|
* Consolidated admin guard hook for all admin pages
|
|
*
|
|
* Handles:
|
|
* - Authentication check (redirects to /auth)
|
|
* - Role authorization check (redirects to /)
|
|
* - MFA enrollment check
|
|
* - Loading states
|
|
*
|
|
* @param requireMFA - Whether to enforce MFA requirement (default: true)
|
|
* @returns AdminGuardState with loading, authorization, and MFA status
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* const { isLoading, isAuthorized, needsMFA } = useAdminGuard();
|
|
*
|
|
* if (isLoading) return <LoadingSkeleton />;
|
|
* if (!isAuthorized) return null;
|
|
* if (needsMFA) return <MFARequiredAlert />;
|
|
*
|
|
* return <AdminContent />;
|
|
* ```
|
|
*/
|
|
export function useAdminGuard(requireMFA: boolean = true): AdminGuardState {
|
|
const { user, loading: authLoading } = useAuth();
|
|
const { isModerator, loading: roleLoading } = useUserRole();
|
|
const { needsEnrollment, needsVerification, loading: mfaLoading } = useRequireMFA();
|
|
const navigate = useNavigate();
|
|
|
|
// Auto-redirect based on auth state
|
|
useEffect(() => {
|
|
if (!authLoading && !roleLoading) {
|
|
if (!user) {
|
|
navigate('/auth');
|
|
} else if (!isModerator()) {
|
|
navigate('/');
|
|
}
|
|
}
|
|
}, [user, authLoading, roleLoading, navigate, isModerator]);
|
|
|
|
const isLoading = authLoading || roleLoading || mfaLoading;
|
|
const isAuthorized = !!user && isModerator();
|
|
// Block access if EITHER not enrolled OR session is at AAL1 (needs verification)
|
|
const needsMFA = requireMFA && (needsEnrollment || needsVerification);
|
|
|
|
return {
|
|
isLoading,
|
|
isAuthorized,
|
|
needsMFA,
|
|
user,
|
|
};
|
|
}
|