testspace / frontend /src /lib /admin.ts
Mayug Maniparambil
Add admin leaderboard, LLM comparison, random puzzles, clearer rules
c52f47a
Raw
History Blame Contribute Delete
1.89 kB
import { useEffect, useState } from "react";
const ADMIN_TOKEN_KEY = "topobench:admin-token";
const ADMIN_CHANGE_EVENT = "topobench:admin-change";
export function getAdminToken(): string | null {
if (typeof window === "undefined") {
return null;
}
return window.sessionStorage.getItem(ADMIN_TOKEN_KEY);
}
function emitChange(): void {
if (typeof window !== "undefined") {
window.dispatchEvent(new Event(ADMIN_CHANGE_EVENT));
}
}
export async function validateAdminToken(token: string): Promise<boolean> {
try {
const response = await fetch("/api/admin/check", {
headers: { Authorization: `Bearer ${token}` },
});
return response.ok;
} catch {
return false;
}
}
export async function unlockAdmin(token: string): Promise<boolean> {
const trimmed = token.trim();
if (!trimmed) {
return false;
}
const ok = await validateAdminToken(trimmed);
if (!ok) {
return false;
}
window.sessionStorage.setItem(ADMIN_TOKEN_KEY, trimmed);
emitChange();
return true;
}
export function lockAdmin(): void {
if (typeof window !== "undefined") {
window.sessionStorage.removeItem(ADMIN_TOKEN_KEY);
emitChange();
}
}
export function useAdmin(): { enabled: boolean; token: string | null } {
const [token, setToken] = useState<string | null>(getAdminToken);
useEffect(() => {
const handler = () => setToken(getAdminToken());
window.addEventListener(ADMIN_CHANGE_EVENT, handler);
return () => window.removeEventListener(ADMIN_CHANGE_EVENT, handler);
}, []);
return { enabled: Boolean(token), token };
}
export async function adminFetch(
input: string,
init: RequestInit = {},
): Promise<Response> {
const token = getAdminToken();
const headers = new Headers(init.headers);
if (token) {
headers.set("Authorization", `Bearer ${token}`);
}
return fetch(input, { ...init, headers });
}