2025-03-08 10:01:08 -06:00
|
|
|
import axios from "axios";
|
2026-09-15 16:33:09 -05:00
|
|
|
import { useEffect, useState } from "react";
|
2025-03-08 10:01:08 -06:00
|
|
|
import useSWR from "swr";
|
2026-09-15 16:33:09 -05:00
|
|
|
import { AuthContext, AuthState } from "./auth-context";
|
2025-03-08 10:01:08 -06:00
|
|
|
|
|
|
|
|
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|
|
|
|
const [auth, setAuth] = useState<AuthState>({
|
|
|
|
|
user: null,
|
2025-09-12 06:19:29 -05:00
|
|
|
allowedCameras: [],
|
2025-03-08 10:01:08 -06:00
|
|
|
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-12 06:19:29 -05:00
|
|
|
setAuth({
|
|
|
|
|
user: null,
|
|
|
|
|
allowedCameras: [],
|
|
|
|
|
isLoading: false,
|
|
|
|
|
isAuthenticated: true,
|
|
|
|
|
});
|
2025-03-08 10:01:08 -06:00
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (profile) {
|
|
|
|
|
if (profile.username && profile.username !== "anonymous") {
|
|
|
|
|
const newUser = {
|
|
|
|
|
username: profile.username,
|
|
|
|
|
role: profile.role || "viewer",
|
|
|
|
|
};
|
2025-09-12 06:19:29 -05:00
|
|
|
|
|
|
|
|
const allowedCameras = Array.isArray(profile.allowed_cameras)
|
|
|
|
|
? profile.allowed_cameras
|
|
|
|
|
: [];
|
|
|
|
|
setAuth({
|
|
|
|
|
user: newUser,
|
|
|
|
|
allowedCameras,
|
|
|
|
|
isLoading: false,
|
|
|
|
|
isAuthenticated: true,
|
|
|
|
|
});
|
2025-03-08 10:01:08 -06:00
|
|
|
} else {
|
|
|
|
|
// Unauthenticated mode (anonymous)
|
2025-09-12 06:19:29 -05:00
|
|
|
setAuth({
|
|
|
|
|
user: null,
|
|
|
|
|
allowedCameras: [],
|
|
|
|
|
isLoading: false,
|
|
|
|
|
isAuthenticated: false,
|
|
|
|
|
});
|
2025-03-08 10:01:08 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, [profile, error]);
|
|
|
|
|
|
|
|
|
|
const login = (user: AuthState["user"]) => {
|
2025-09-12 06:19:29 -05:00
|
|
|
setAuth((current) => ({
|
|
|
|
|
...current,
|
|
|
|
|
user,
|
|
|
|
|
isLoading: false,
|
|
|
|
|
isAuthenticated: true,
|
|
|
|
|
}));
|
2025-03-08 10:01:08 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const logout = () => {
|
2025-09-12 06:19:29 -05:00
|
|
|
setAuth({
|
|
|
|
|
user: null,
|
|
|
|
|
allowedCameras: [],
|
|
|
|
|
isLoading: false,
|
|
|
|
|
isAuthenticated: true,
|
|
|
|
|
});
|
2025-03-08 10:01:08 -06:00
|
|
|
axios.get("/logout", { withCredentials: true });
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-05 08:42:38 -06:00
|
|
|
return <AuthContext value={{ auth, login, logout }}>{children}</AuthContext>;
|
2025-03-08 10:01:08 -06:00
|
|
|
}
|