// auth.jsx — login-форма + хелперы для API-вызовов. // // Сессия — signed cookie 'zxckotik_admin' (ставит бэк). Фронт не хранит // пароль; для определения статуса делает /api/auth/me. const { useState: useStateAuth, useEffect: useEffectAuth } = React; /** GET /api/auth/me — true если есть валидная сессия. */ async function checkAuth() { try { const res = await fetch("/api/auth/me"); if (!res.ok) return false; const data = await res.json(); return Boolean(data.authenticated); } catch { return false; } } /** POST /api/auth/login — отправить пароль, на успех cookie ставится автоматом. */ async function loginWithPassword(password) { try { const res = await fetch("/api/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ password }), }); return res.ok; } catch { return false; } } async function logoutSession() { try { await fetch("/api/auth/logout", { method: "POST" }); } catch {} } /** Универсальный wrapper для mutating запросов. На 401 → window-event для login. */ async function apiMutate(method, url, body) { const opts = { method, headers: body ? { "Content-Type": "application/json" } : {}, body: body ? JSON.stringify(body) : undefined, }; const res = await fetch(url, opts); if (res.status === 401) { window.dispatchEvent(new CustomEvent("auth-required")); throw new Error("auth_required"); } if (!res.ok) { const detail = await res.text().catch(() => ""); throw new Error(`${method} ${url} → ${res.status} ${detail.slice(0, 200)}`); } const ct = res.headers.get("content-type") || ""; return ct.includes("application/json") ? res.json() : null; } function LoginScreen({ onSuccess }) { const [password, setPassword] = useStateAuth(""); const [loading, setLoading] = useStateAuth(false); const [error, setError] = useStateAuth(""); const submit = async (e) => { e.preventDefault(); if (!password) return; setLoading(true); setError(""); const ok = await loginWithPassword(password); setLoading(false); if (ok) { setPassword(""); onSuccess(); } else { setError("Неверный пароль"); } }; return (