feat(auth): single-admin password login (signed cookie) — gate tuning + Sources catalog, keep chat and document viewer public
This commit is contained in:
@@ -9,10 +9,24 @@
|
||||
const tbody = document.querySelector("#docs-tbody");
|
||||
const emptyEl = document.querySelector("#sources-empty");
|
||||
const tableWrap = document.querySelector(".table-wrap");
|
||||
const statCards = document.querySelector("#stat-cards");
|
||||
const gateEl = document.querySelector("#sources-gate");
|
||||
const statDocs = document.querySelector("#stat-docs");
|
||||
const statChunks = document.querySelector("#stat-chunks");
|
||||
const statLast = document.querySelector("#stat-last");
|
||||
|
||||
/* Phase 16: whoami BEFORE the docs fetch. Anonymous visitors get the
|
||||
* sign-in gate (stat cards + table hidden) and NO /api/docs call — the
|
||||
* catalog is admin-only. The document viewer itself stays public (the
|
||||
* soft rule), so the gate copy points at what keeps working. */
|
||||
async function isAdmin() {
|
||||
try {
|
||||
const r = await fetch("/api/whoami");
|
||||
if (r.ok) return (await r.json()).authenticated === true;
|
||||
} catch { /* API unreachable: anonymous-safe gate */ }
|
||||
return false;
|
||||
}
|
||||
|
||||
function fmtDate(iso) {
|
||||
try {
|
||||
return new Date(iso).toLocaleString();
|
||||
@@ -97,4 +111,15 @@ function showEmpty() {
|
||||
if (tableWrap) tableWrap.hidden = true;
|
||||
}
|
||||
|
||||
loadDocs();
|
||||
(async () => {
|
||||
if (!(await isAdmin())) {
|
||||
// Anonymous: gate in, catalog out, and no /api/docs request at all.
|
||||
if (statCards) statCards.hidden = true;
|
||||
if (tableWrap) tableWrap.hidden = true;
|
||||
if (emptyEl) emptyEl.hidden = true;
|
||||
if (gateEl) gateEl.hidden = false;
|
||||
return;
|
||||
}
|
||||
if (gateEl) gateEl.hidden = true;
|
||||
loadDocs();
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user