This repository has no description
1import React, { useEffect, useRef, useState } from 'react';
2import { Navigate, useLocation } from 'react-router-dom';
3import { useAuth } from '../contexts/AuthContext';
4import { isAccountAllowed } from '../config/allowlist';
5import Loading from './Loading/Loading';
6
7// Component to protect routes that require authentication
8const ProtectedRoute = ({ children }) => {
9 const { isAuthenticated, loading, session, checkAuthStatus } = useAuth();
10 const location = useLocation();
11 const [redirecting, setRedirecting] = useState(false);
12 const [checkingStatus, setCheckingStatus] = useState(false);
13 const checkCount = useRef(0);
14 const maxChecks = 3; // Maximum number of checks to prevent infinite loops
15
16 // Perform an immediate auth check when the component mounts
17 useEffect(() => {
18 const checkAuth = async () => {
19 if (checkCount.current >= maxChecks) {
20 console.error("Maximum auth check attempts reached. Stopping to prevent infinite loop.");
21 return;
22 }
23
24 // Only proceed if not already checking, not already redirecting, and not loading
25 if (!isAuthenticated && !checkingStatus && !redirecting && !loading) {
26 try {
27 console.log("ProtectedRoute: Checking authentication status");
28 setCheckingStatus(true);
29 checkCount.current += 1;
30 await checkAuthStatus();
31 } catch (error) {
32 console.error("ProtectedRoute: Auth check failed:", error);
33 } finally {
34 setCheckingStatus(false);
35 }
36 }
37 };
38
39 // Call immediately on mount or when dependency values change
40 checkAuth();
41
42 // Set up interval for periodic checks only if authenticated
43 let interval;
44 if (isAuthenticated && session) {
45 console.log("ProtectedRoute: Setting up periodic auth checks");
46 interval = setInterval(() => {
47 checkAuthStatus().catch(err => {
48 console.error("Error in periodic auth check:", err);
49 });
50 }, 30000); // Check every 30 seconds
51 }
52
53 return () => {
54 if (interval) {
55 console.log("ProtectedRoute: Clearing periodic auth checks");
56 clearInterval(interval);
57 }
58 };
59 }, [isAuthenticated, checkAuthStatus, redirecting, loading, checkingStatus, session]);
60
61 // Show loading state while authentication is being checked
62 if (loading || checkingStatus) {
63 return <Loading message="Checking authentication..." />;
64 }
65
66 // If not authenticated, redirect to login with return URL
67 if (!isAuthenticated && !redirecting) {
68 console.log("ProtectedRoute: Not authenticated, redirecting to login");
69 setRedirecting(true); // Prevent multiple redirects
70 const returnUrl = encodeURIComponent(location.pathname);
71 return <Navigate to={`/login?returnUrl=${returnUrl}`} replace />;
72 }
73
74 // Check if user is allowed
75 if (session && session.handle && !isAccountAllowed(session)) {
76 console.log("ProtectedRoute: User not in allowlist, redirecting to supporter page");
77 return <Navigate to="/supporter" replace />;
78 }
79
80 // Reset counter when rendering the protected content
81 checkCount.current = 0;
82
83 // Render children if authenticated and allowed
84 console.log("ProtectedRoute: Authentication successful, rendering protected content");
85 return children;
86};
87
88export default ProtectedRoute;