frigate/web/src/components/auth/ProtectedRoute.tsx
Nicolas Mowen c136e5e8bd
Some checks failed
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
Miscellaneous fixes (#21141)
* Remove source_type from API

* Don't require state classification models to select all classes

* Specifically validate provided end_time for manual events

* Remove yolov9 specification for warning

* Remove warning for coral

* clarify zone name tip

* clarify replace rules in lpr docs

* remove periods

* Add explanation for review report

* adjust HLS gap controller params

defaults to false, should help to recover from hangs and stalling in tracking details videos on chrome

* only redirect to login page once on 401

attempt to fix ios pwa safari redirect storm

* Use contextual information from other cameras to inform report summary

* Formatting and prompt improvements for review summary report

* More improvements to prompt

* Remove examples

* Don't show admin action buttons on export card

* fix redirect race condition

Coordinate 401 redirect logic between ApiProvider and ProtectedRoute using a shared flag to prevent multiple simultaneous redirects that caused UI flashing. Ensure both auth error paths check and set the redirect flag before navigating to login, eliminating race conditions where both mechanisms could trigger at once

---------

Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
2025-12-04 12:19:07 -06:00

61 lines
1.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useContext, useEffect } from "react";
import { Navigate, Outlet } from "react-router-dom";
import { AuthContext } from "@/context/auth-context";
import ActivityIndicator from "../indicators/activity-indicator";
import {
isRedirectingToLogin,
setRedirectingToLogin,
} from "@/api/auth-redirect";
export default function ProtectedRoute({
requiredRoles,
}: {
requiredRoles: string[];
}) {
const { auth } = useContext(AuthContext);
// Redirect to login page when not authenticated
// don't use <Navigate> because we need a full page load to reset state
useEffect(() => {
if (
!auth.isLoading &&
auth.isAuthenticated &&
!auth.user &&
!isRedirectingToLogin()
) {
setRedirectingToLogin(true);
window.location.href = "/login";
}
}, [auth.isLoading, auth.isAuthenticated, auth.user]);
if (auth.isLoading) {
return (
<ActivityIndicator className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" />
);
}
// Unauthenticated mode
if (!auth.isAuthenticated) {
return <Outlet />;
}
// Authenticated mode (8971): require login
if (!auth.user) {
return (
<ActivityIndicator className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" />
);
}
// If role is null (shouldnt happen if isAuthenticated, but type safety), fallback
// though isAuthenticated should catch this
if (auth.user.role === null) {
return <Outlet />;
}
if (!requiredRoles.includes(auth.user.role)) {
return <Navigate to="/unauthorized" replace />;
}
return <Outlet />;
}