frigate/web/src/context/auth-context.tsx

111 lines
2.5 KiB
TypeScript
Raw Normal View History

import axios from "axios";
import { createContext, useEffect, useState } from "react";
import useSWR from "swr";
interface AuthState {
2025-09-10 14:55:19 +03:00
user: { username: string; role: string | null } | null;
allowedCameras: string[];
isLoading: boolean;
isAuthenticated: boolean; // true if auth is required
}
interface AuthContextType {
auth: AuthState;
login: (user: AuthState["user"]) => void;
logout: () => void;
}
export const AuthContext = createContext<AuthContextType>({
2025-09-10 14:55:19 +03:00
auth: {
user: null,
allowedCameras: [],
isLoading: true,
isAuthenticated: false,
},
login: () => {},
logout: () => {},
});
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [auth, setAuth] = useState<AuthState>({
user: null,
2025-09-10 14:55:19 +03:00
allowedCameras: [],
isLoading: true,
isAuthenticated: false,
});
const { data: profile, error } = useSWR("/profile", {
revalidateOnFocus: false,
revalidateOnReconnect: true,
fetcher: (url) =>
axios.get(url, { withCredentials: true }).then((res) => res.data),
});
useEffect(() => {
if (error) {
if (axios.isAxiosError(error) && error.response?.status === 401) {
// auth required but not logged in
2025-09-10 14:55:19 +03:00
setAuth({
user: null,
allowedCameras: [],
isLoading: false,
isAuthenticated: true,
});
}
return;
}
if (profile) {
if (profile.username && profile.username !== "anonymous") {
const newUser = {
username: profile.username,
role: profile.role || "viewer",
};
2025-09-10 14:55:19 +03:00
const allowedCameras = Array.isArray(profile.allowed_cameras)
? profile.allowed_cameras
: [];
setAuth({
user: newUser,
allowedCameras,
isLoading: false,
isAuthenticated: true,
});
} else {
// Unauthenticated mode (anonymous)
2025-09-10 14:55:19 +03:00
setAuth({
user: null,
allowedCameras: [],
isLoading: false,
isAuthenticated: false,
});
}
}
}, [profile, error]);
const login = (user: AuthState["user"]) => {
2025-09-10 14:55:19 +03:00
setAuth((current) => ({
...current,
user,
isLoading: false,
isAuthenticated: true,
}));
};
const logout = () => {
2025-09-10 14:55:19 +03:00
setAuth({
user: null,
allowedCameras: [],
isLoading: false,
isAuthenticated: true,
});
axios.get("/logout", { withCredentials: true });
};
return (
<AuthContext.Provider value={{ auth, login, logout }}>
{children}
</AuthContext.Provider>
);
}