Spaces:
Running
Running
Download frontend/src/hooks/useAuth.jsx from Agmmm/valhalla: direct link, hf CLI and curl.
- Browser
- Download file 2.52 kB
-
https://huggingface.co/spaces/Agmmm/valhalla/resolve/main/frontend/src/hooks/useAuth.jsx
- Command line
-
hf download hf://spaces/Agmmm/valhalla/frontend/src/hooks/useAuth.jsx
-
curl -L -o useAuth.jsx https://huggingface.co/spaces/Agmmm/valhalla/resolve/main/frontend/src/hooks/useAuth.jsx
2.52 kB
| /** | |
| * useAuth — authentication context provider. | |
| * | |
| * Validates a stored token against /api/auth/me on load and exposes | |
| * login/logout backed by the backend auth routes; persists the token in | |
| * localStorage. | |
| * | |
| * Architecture: wraps the whole app in App.jsx; consumed by InfoBar, | |
| * LoginButton, LoginModal, and RosterManager. | |
| * | |
| * Design: one shared context so every auth-gated component reads the same | |
| * session state. | |
| */ | |
| import { createContext, useContext, useState, useEffect, useCallback } from "react"; | |
| import { apiUrl } from "../utils/api"; | |
| const AuthContext = createContext(null); | |
| export function AuthProvider({ children }) { | |
| const [token, setToken] = useState(() => localStorage.getItem("valhalla_token")); | |
| const [user, setUser] = useState(null); | |
| const [loading, setLoading] = useState(true); | |
| useEffect(() => { | |
| if (!token) { | |
| setLoading(false); | |
| return; | |
| } | |
| fetch(apiUrl("/api/auth/me"), { | |
| headers: { Authorization: `Bearer ${token}` }, | |
| }) | |
| .then((r) => (r.ok ? r.json() : Promise.reject())) | |
| .then((u) => setUser(u)) | |
| .catch(() => { | |
| localStorage.removeItem("valhalla_token"); | |
| setToken(null); | |
| }) | |
| .finally(() => setLoading(false)); | |
| }, [token]); | |
| const login = useCallback(async (email, password) => { | |
| const res = await fetch(apiUrl("/api/auth/login"), { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ email, password }), | |
| }); | |
| if (!res.ok) { | |
| const err = await res.json().catch(() => ({ detail: "Login failed" })); | |
| throw new Error(err.detail || "Login failed"); | |
| } | |
| const data = await res.json(); | |
| localStorage.setItem("valhalla_token", data.token); | |
| setToken(data.token); | |
| setUser(data.user); | |
| return data; | |
| }, []); | |
| const logout = useCallback(async () => { | |
| if (token) { | |
| await fetch(apiUrl("/api/auth/logout"), { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ token }), | |
| }).catch(() => {}); | |
| } | |
| localStorage.removeItem("valhalla_token"); | |
| setToken(null); | |
| setUser(null); | |
| }, [token]); | |
| return ( | |
| <AuthContext.Provider | |
| value={{ token, user, isAuthenticated: !!user, loading, login, logout }} | |
| > | |
| {children} | |
| </AuthContext.Provider> | |
| ); | |
| } | |
| export function useAuth() { | |
| const ctx = useContext(AuthContext); | |
| if (!ctx) throw new Error("useAuth must be used within AuthProvider"); | |
| return ctx; | |
| } | |