Files
site-gateway/src/public/features.js
T

616 lines
264 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ============================================================================
// features.js -- rendering and event handling for the "extended" views that
// live alongside app.js: Streaming Hosts, Redirect Hosts, Access Lists, and the
// entire Administration area (Users, Groups, Gateway defaults, Backup & restore,
// Security & updates, Logs & Retention). app.js owns Hosted Sites/Proxy Hosts and
// the core dialogs; this file owns everything else, wired up as a set of module-
// level event listeners plus render functions called from window.renderExtendedViews.
// ============================================================================
// --- Small shared helpers -------------------------------------------------
function extendedEscape(value) { return escapeHtml(value); }
function featureIcon(item, fallback) { return item.icon ? `<img src="${extendedEscape(item.icon)}" alt="">` : fallback; }
const backupDialogTextFix = new MutationObserver(() => { const dialog = document.querySelector("#create-backup-dialog"); if (dialog) dialog.querySelectorAll("p,small").forEach(node => { if (node.textContent.includes("Hosted Site files")) node.textContent = node.textContent.replaceAll("Hosted Site files", "uploaded hosted-site files"); }); });
backupDialogTextFix.observe(document.body, { childList:true, subtree:true });
// --- Streaming Hosts view ---------------------------------------------------
// Renders the Streaming Hosts grid and its shared empty state.
function renderStreams() {
const list = document.querySelector("#stream-list"), empty = document.querySelector("#stream-empty");
if (!state.loaded) return;
empty.classList.toggle("hidden", !state.loaded || state.streams.length > 0);
list.innerHTML = state.streams.map(item => {
const status = item.status === "running" ? "running" : item.status === "error" ? "error" : "disabled";
const upstream = item.enabled === false || item.upstream?.status === "unmonitored" ? "Monitoring paused" : !item.upstream || item.upstream.status === "pending" ? "Target check pending" : item.upstream.status === "healthy" ? `Target reachable · ${item.upstream.responseMs} ms` : `Target unreachable · ${extendedEscape(item.upstream.error || "check failed")}`;
const protocols = [item.tcp !== false ? "TCP" : null, item.udp ? "UDP" : null].filter(Boolean).map(value => `<span class="chip">${value}</span>`).join("");
const toggle = `<button class="toggle ${item.enabled === false ? "" : "on"}" data-stream-action="toggle" aria-label="${item.enabled === false ? "Enable" : "Disable"} ${extendedEscape(item.name)}"><span></span></button>`;
return `<article class="site-card stream-card" data-stream-id="${item.id}" data-kind="stream"><div class="card-top"><div class="site-icon">${featureIcon(item,"SH")}</div><div class="menu-wrap"><button class="icon-button menu-button" aria-label="Streaming host options" aria-expanded="false">•••</button><div class="menu"><button data-stream-action="edit">Edit streaming host</button><button data-stream-action="icon">Change icon</button><button data-stream-action="delete" class="danger-text">Delete streaming host</button></div></div></div><h2>${extendedEscape(item.name)}</h2><p class="address">Port ${item.port}</p><p class="gateway-address">→ ${extendedEscape(item.target)}</p><p class="upstream-copy ${item.upstream?.status === "unhealthy" ? "bad" : ""}">${upstream}</p><div class="card-footer"><span class="status-pill"><span class="status-dot ${status}"></span>${status === "error" ? "Needs attention" : status[0].toUpperCase() + status.slice(1)}</span><div class="card-actions">${toggle}${protocols}</div></div></article>`;
}).join("");
}
// --- Redirect Hosts view -----------------------------------------------------
// Renders the Redirect Hosts grid. Redirect cards render their own empty state
// inline (no separate #redirect-empty toggle needed here).
function renderRedirects() {
const list = document.querySelector("#redirect-list"), empty = document.querySelector("#redirect-empty");
// Keep the existing cards or empty state mounted while the shared refresh is pending.
// The completed response is the only point at which this view should be replaced.
if (!state.loaded) return;
empty.classList.toggle("hidden", !state.loaded || state.redirects.length > 0);
list.innerHTML = state.redirects.map(item => `<article class="site-card redirect-card" data-redirect-id="${item.id}" data-kind="redirect"><div class="card-top"><div class="site-icon">${featureIcon(item,"RD")}</div><div class="menu-wrap"><button class="icon-button menu-button" aria-label="Redirect options" aria-expanded="false">•••</button><div class="menu"><button data-redirect-action="edit">Edit redirect host</button><button data-redirect-action="icon">Change icon</button><button data-redirect-action="caddy-config">View Caddy config</button><button data-redirect-action="toggle">${item.enabled ? "Disable" : "Enable"}</button><button data-redirect-action="delete" class="danger-text">Delete redirect host</button></div></div></div><h2>${extendedEscape(item.name)}</h2><p class="address">${extendedEscape(item.domain)}</p><p class="gateway-address">→ ${extendedEscape(item.target)}${item.preservePath ? " · preserves path" : ""}</p><div class="card-footer"><span class="status-pill"><span class="status-dot ${item.enabled ? "running" : "disabled"}"></span>${item.enabled ? "Running" : "Disabled"}</span><div class="card-actions"><span class="chip">HTTP ${item.code}</span></div></div></article>`).join("");
}
// --- Access Lists view --------------------------------------------------------
// Renders the Access Lists grid (including its own empty state) and refreshes
// every "Access List" <select> used elsewhere (create/edit dialogs) with the
// current set of Access Lists as options.
function renderAccessLists() {
const list = document.querySelector("#access-list");
list.classList.toggle("loading", !state.loaded);
list.innerHTML = state.accessLists.length ? `<div class="access-grid">${state.accessLists.map(item => { const assigned = [...state.proxies, ...state.sites, ...state.redirects].filter(host => host.accessListId === item.id); const loginCount = item.credentials?.length || 0; return `<article class="site-card access-card" data-access-id="${item.id}"><div class="card-top"><div class="site-icon">${featureIcon(item, "AL")}</div><div class="menu-wrap"><button class="icon-button menu-button" aria-label="Access List options" aria-expanded="false">•••</button><div class="menu"><button data-access-action="edit">Edit Access List</button><button data-access-action="icon">Change icon</button><button data-access-action="assignments">View assigned hosts</button><button data-access-action="toggle">${item.enabled === false ? "Enable" : "Disable"}</button><button data-access-action="delete" class="danger-text">Delete Access List</button></div></div></div><h2>${extendedEscape(item.name)}</h2><p class="address">${item.enabled === false ? "Protection disabled" : "Protection available"}</p><div class="access-card-stats"><span><strong>${item.networks?.length || 0}</strong><small>Allowed network${item.networks?.length === 1 ? "" : "s"}</small></span><span><strong>${loginCount}</strong><small>Login${loginCount === 1 ? "" : "s"}</small></span><span><strong>${assigned.length}</strong><small>Assigned host${assigned.length === 1 ? "" : "s"}</small></span></div><div class="card-footer"><span class="status-pill"><span class="status-dot ${item.enabled === false ? "disabled" : "running"}"></span>${item.enabled === false ? "Disabled" : "Enabled"}</span></div></article>`; }).join("")}</div>` : '<section class="empty"><div class="empty-icon">◎</div><h2>Create your first Access List</h2><p>Protect your hosts with reusable network and login rules.</p><button class="button primary create-trigger">Create an Access List</button></section>';
const options = '<option value="">Public — no Access List</option>' + state.accessLists.filter(item => item.enabled !== false).map(item => `<option value="${item.id}">${extendedEscape(item.name)}</option>`).join("");
document.querySelectorAll('select[name="accessListId"], #settings-access-list').forEach(select => { const value = select.value; select.innerHTML = options; select.value = value; });
}
// --- Backup & restore panel ----------------------------------------------------
function backupTypeLabel(type) {
return type === "complete" ? "Complete" : type === "configuration" ? "Configuration only" : type === "encrypted" ? "Encrypted" : "Unknown";
}
function updateBackupConfigOnlyWarning() {
const form = document.querySelector("#backup-settings-form"), warning = document.querySelector("#backup-config-only-warning");
if (!form || !warning) return;
warning.classList.toggle("hidden", !(form.elements.enabled.checked && form.elements.type.value === "configuration"));
}
// Populates the scheduled-backup settings form from saved settings and renders
// the list of existing backups.
function renderBackups() {
if (!state.settings) return;
const form = document.querySelector("#backup-settings-form"), defaults = state.settings.backups || {};
for (const key of ["type","frequency","hour","retention"]) if (form.elements[key] && defaults[key] !== undefined) form.elements[key].value = defaults[key];
form.elements.enabled.checked = Boolean(defaults.enabled); form.elements.includeLogs.checked = Boolean(defaults.includeLogs); form.elements.encrypt.checked = Boolean(defaults.encrypt);
updateBackupConfigOnlyWarning();
document.querySelector("#backup-path").textContent = `Backups are stored in ${state.settings.backupDirectory}. Separate storage can be mounted directly at /data/backups for disk-failure protection.`;
const completeBackups = state.backups.filter(item => item.type === "complete"), configBackups = state.backups.filter(item => item.type === "configuration");
const summaryEl = document.querySelector("#backup-summary");
if (summaryEl) summaryEl.textContent = state.backups.length ? `${completeBackups.length} Complete (${formatBytes(completeBackups.reduce((sum, item) => sum + item.size, 0))}), ${configBackups.length} Configuration only (${formatBytes(configBackups.reduce((sum, item) => sum + item.size, 0))}).` : "";
document.querySelector("#backup-list").innerHTML = state.backups.length ? state.backups.map(item => `<article class="data-row backup-row" data-backup="${extendedEscape(item.filename)}"><span class="status-dot ${item.valid ? "running" : "error"}"></span><div><strong title="${extendedEscape(item.filename)}">${backupTypeLabel(item.type)} backup — ${formatTime(item.createdAt)}</strong><small>${formatBytes(item.size)}</small></div><div><span class="chip type-${extendedEscape(item.type)}">${backupTypeLabel(item.type)}</span><small>Site Gateway ${extendedEscape(item.appVersion)}</small></div><div><strong>${item.valid ? "Verified" : "Unreadable"}</strong><small>${item.valid ? "Manifest checks out" : "Manifest could not be read"}</small></div><div class="row-actions"><a class="button secondary" href="/api/backups/${encodeURIComponent(item.filename)}/download">Download</a><button class="button secondary" data-backup-action="restore">Restore</button><button class="button secondary danger-text" data-backup-action="delete">Delete</button></div></article>`).join("") : '<p class="quiet-state padded">No stored backups yet.</p>';
}
// Toggle the "configuration only" warning banner whenever scheduling or the
// backup type changes.
document.querySelector("#backup-settings-form [name=\"enabled\"]")?.addEventListener("change", updateBackupConfigOnlyWarning);
document.querySelector("#backup-settings-form [name=\"type\"]")?.addEventListener("change", updateBackupConfigOnlyWarning);
// --- Gateway defaults (custom 404 / no-response / redirect page) --------------
// Populates the Gateway Defaults form from saved settings and refreshes the
// live preview panel.
function renderDefaultSettings() {
if (!state.settings) return; const form = document.querySelector("#default-site-form"), value = state.settings.defaultSite || {};
if (!document.querySelector("#default-site-help")) { const help = document.createElement("p"); help.id = "default-site-help"; help.className = "muted"; help.textContent = "The Default Site handles unknown HTTP hostnames. HTTPS requests still require a matching host and certificate."; form.prepend(help); }
for (const key of ["mode","title","message","redirectUrl","redirectCode","customHtml"]) if (form.elements[key] && value[key] !== undefined) form.elements[key].value = value[key];
form.elements.preservePath.checked = value.preservePath !== false;
renderDefaultSitePreview();
}
// Keep this HTML template in sync with the themed-page literal inside renderDefaultSiteHtml()
// in src/server.js -- duplicated here so the live preview below renders instantly, without a
// round trip to the server, on every keystroke. If the server template ever changes, this must
// be updated to match or the preview will silently drift from what visitors actually see.
function defaultSiteThemedHtml(title, message) {
const safeTitle = extendedEscape(title);
const safeMessage = extendedEscape(message);
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="color-scheme" content="dark"><title>${safeTitle}</title><style>:root{color-scheme:dark;--bg:#08101d;--card:#101a2b;--line:#25344c;--text:#eef4ff;--muted:#95a4ba;--green:#62e6a7}*{box-sizing:border-box}body{margin:0;min-height:100vh;display:grid;place-items:center;padding:24px;background:radial-gradient(circle 260px at 50% 0,#163829 0,transparent 100%),var(--bg);color:var(--text);font-family:Inter,system-ui,sans-serif}.card{width:min(620px,100%);padding:44px;border:1px solid var(--line);border-radius:22px;background:color-mix(in srgb,var(--card) 94%,transparent);box-shadow:0 28px 80px #0006;text-align:center}.mark-stack{display:flex;flex-direction:column;align-items:center;gap:16px;margin-bottom:40px}.mark-icon{width:88px;height:88px;object-fit:contain;display:block;margin:0 auto}.mark-wordmark{width:290px;max-width:100%;height:auto;object-fit:contain;display:block;margin-top:0}h1{margin:0;font-size:clamp(34px,7vw,56px);letter-spacing:-.05em;line-height:1.02}p{color:var(--muted);font-size:17px;line-height:1.65;margin:20px 0 0}.foot{padding-top:28px;margin-top:30px;border-top:1px solid var(--line);font-size:13px;color:var(--muted)}</style></head><body><main class="card"><div class="mark-stack"><img class="mark-icon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAB+RUlEQVR42u29d5xlV3EtvKr2Pjd198xolBMiimAyxhgbm/RwwjY2Bj9scOB9BhOMCcbY5ByMsQ0GY4KNMTmaDBIgJESSCBLKAUlII81oRpNnOtxwzq7vj51qn27Zz36gEdOn5nd/03379u3ue0/Vrlq1ahXQWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWedddZZZ5111llnnXXWWWfrx6h7CdbJG01U3ABARIqvRxOR4tZZFwA6+0l0eGYwEZqm+R87MhHBGAPnXBcQugDQ2a3d2BgQgKZpivsXNm2kU2572+Htbn+7zbe57W1POvqYY47euGHDpqpfDeHQ1NPp5MDi4uK2bVu3brl2y9ZtN9yw/9prr13Zt3uP089jjIGIwDnXvdhdAOjs1nLaM3Ph9IPREPe+z302PvThD7/fzz7o53791Dvf5SHHHX/cvYbVgOObLup/CjcJt6mbYfuN2y+95IILPnP2WV/95FfPPOviCy+4YLGZzW72Z3bWBYDObmEzxhRO+MAH/fymxzzudx/5v37pl590yh3v8OABWawAWMYYK5PJtHFN3Yg4B0mODxBAAoi/xxKzZWOHvX5vjgboA1huJrjqiitO+/JpX/zXj3/0o18875xvH7i536GzLgB0dguk+i44XX8wwKMe/du3+z9PftJzf/bBv/A0C4sDmOLAZHk6dfXUQdiRWEeChsBOBI4ELtXzlDIAAGAhGCJYkGOHmoVc3/YGG3rzdgEG42aKs790xuv/+S1v/ocvfe4L2xPmQNSVBl0A6OzHne4nRyPg957whDs+83l/+ca73f2ejxxDsHu6bzqpZ1PHZGcstoZDLQ0aCBo4+JNf4CBwcAAoZAIhCAjAIBhiGPhbBYIFwwrX3GA6NFVv82DToAJwzje//q43vv5vX3zapz69LWYDETDsrAsAnf0o031r0dQ1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kxrkJAE6Eok5HNQ6TdjVbnzKH0/9eJITkz/xw/8mnupB5NNYC8sMy4wq7P9LXyMDywRLBj0iVCBUqQXMsGAYGFTooQLDYYrxjj03Xv+N899z1YdPe9eW0755FQ6MPaBpupT/x3PdsFqgSaA7PfxY/oUn/C7f92FPlhNOvrsMgu/MANTwh2kT7nP+Y2n81+L94tTX63ALj0XjB8rFARS+T1rPlx6f7vO+L0588HdhxkXqfBiIbxELesDy3jEued6Dsf3d3y7/vsM5ALTAU/rpO53AD7v3b8vtT3gwLwxPRlya6btpAFkHYqaKTdAGEPhMwZEBszFgMl6y3ZiQqZOHCXwAIGMMLFPDxLVltszs2AmMYbbETBBXgZxly1VQ7+mx/yXIAc1kuljv2b/l4HU7Ljx4xXUX7r3oB5fv/e4V2+od++r0J1njHb9r8/2Yy0jjOQPR7Camk+6zGbe7753opLveA8eecneZ33xbsgtHC9kKjpiaSPMlIiELR4AjK0KMuvGlhLBFHa9LZjQANU0tDg4NmJw4cSLhMR60qgVoBJCm8Uw+YoIxEAdx4uBc4wMADJwTSDNBMzmI5Zuuxv7vn4mt7/ksVq5YPhTOf2gDwBodFABAFZUebiZziN9TUDZp7b9IWuCMi5kYrfGcktsCsW2ThskFmNWCmVvjV/JZibjO8Q8FNpDahmt9nQae/E+6J89a7DGgv0688+l6Pjx34ZTSurB010KwSrQCotJ5yimHzKTg/R4i5z/0AUADg+TTp1t/FhrHi8WneZ3T3zqCgdKK8E52K39folBoqkGwjgPAf+s3WittWOsb5Uf850m3z/snLSjcupHN7i3qrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzzjrrrLPOOuuss84666yzH6X9/2yKxnNuqYSWAAAAAElFTkSuQmCC" alt=""><img class="mark-wordmark" src="data:image/png;base64,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" alt="Site Gateway"></div><h1>${safeTitle}</h1><p>${safeMessage}</p><div class="foot">Host. Proxy. Secure.</div></main></body></html>`;
}
// Refreshes the live preview iframe/caption on the Gateway Defaults page to
// match the currently selected response mode (themed 404 / welcome / abort /
// redirect / custom HTML).
function renderDefaultSitePreview() {
const form = document.querySelector("#default-site-form"), frame = document.querySelector("#default-site-preview-frame"), note = document.querySelector("#default-site-preview-note"), caption = document.querySelector("#default-site-preview-caption");
if (!form || !frame || !note) return;
const mode = form.elements.mode.value;
if (mode === "abort") { frame.closest(".default-site-preview-frame-wrap").classList.add("hidden"); note.classList.remove("hidden"); note.textContent = "No page is shown for this mode \u2014 the connection is closed immediately."; caption?.classList.add("hidden"); return; }
if (mode === "redirect") { frame.closest(".default-site-preview-frame-wrap").classList.add("hidden"); note.classList.remove("hidden"); const destination = form.elements.redirectUrl.value.trim(); note.textContent = destination ? `No page is shown for this mode \u2014 visitors are redirected to ${destination}.` : "No page is shown for this mode \u2014 enter a redirect destination above."; caption?.classList.add("hidden"); return; }
frame.closest(".default-site-preview-frame-wrap").classList.remove("hidden"); note.classList.add("hidden"); caption?.classList.remove("hidden");
if (mode === "custom") { frame.srcdoc = form.elements.customHtml.value || "<p style=\"font:14px sans-serif;color:#95a4ba;padding:20px\">Enter Custom HTML above to preview it here.</p>"; return; }
const title = form.elements.title.value || (mode === "welcome" ? "Gateway ready" : "Route not found");
const message = form.elements.message.value || "The gateway is responding, but this address has not been configured.";
frame.srcdoc = defaultSiteThemedHtml(title, message);
}
document.querySelector("#default-site-form")?.addEventListener("input", renderDefaultSitePreview);
document.querySelector("#default-site-form")?.addEventListener("change", renderDefaultSitePreview);
// --- Certificate health thresholds (Security & updates admin panel) -----------
// Populates the health-settings form (renewing-soon / critical / stale-data
// thresholds) from saved settings.
function renderHealthSettings() {
if (!state.settings) return; const form = document.querySelector("#health-settings-form"), value = state.settings.certificateHealth || {};
for (const key of ["warningDays","criticalDays","staleMinutes"]) if (value[key] !== undefined) form.elements[key].value = value[key];
}
// --- Misc admin panel decorators, called after every refresh -------------------
function decorateAccessAssignments() { document.querySelectorAll("#access-list [data-access-id]").forEach(card => { const item = state.accessLists.find(value => value.id === card.dataset.accessId); if (!item || card.querySelector(".access-assignment-preview")) return; const assigned = [...state.proxies, ...state.sites, ...state.redirects].filter(host => host.accessListId === item.id); const preview = document.createElement("p"); preview.className = "access-assignment-preview"; preview.textContent = assigned.length ? `Protects: ${assigned.map(host => host.name || host.domain).join(" · ")}` : "Not assigned to a host"; card.querySelector(".card-footer")?.before(preview); }); }
function renderAuditPanel() { if (state.user?.role !== "administrator") return; const tabs = document.querySelector(".admin-tabs"), users = document.querySelector('[data-admin-panel="users"]'); if (!tabs || !users) return; let tab = tabs.querySelector('[data-admin-tab="audit"]'); if (!tab) { tab = document.createElement("button"); tab.dataset.adminTab = "audit"; tab.textContent = "Audit log"; tabs.insertBefore(tab, tabs.children[1]); } let panel = document.querySelector('[data-admin-panel="audit"]'); if (!panel) { panel = document.createElement("section"); panel.dataset.adminPanel = "audit"; panel.className = "settings-panel hidden"; users.parentElement.insertBefore(panel, users.nextElementSibling); } if (panel.dataset.ready) return; panel.dataset.ready = "1"; panel.innerHTML = '<div class="panel-heading"><div><h2>Configuration audit log</h2><p class="muted">A history of Site Gateway configuration changes. Audit records cannot be edited or deleted.</p></div></div><div class="event-filters"><label>Search audit events<input id="audit-action" placeholder="Search by user, action, or target"></label><label>Result<select id="audit-status"><option value="">All results</option><option value="ok">Success</option><option value="error">Failed</option></select></label></div><div id="audit-list" class="dashboard-list event-list"><p class="quiet-state">Open this tab to load audit records.</p></div>'; const load = async () => { const records = await api(`/api/audit?action=${encodeURIComponent(document.querySelector("#audit-action").value)}&status=${encodeURIComponent(document.querySelector("#audit-status").value)}`); document.querySelector("#audit-list").innerHTML = records.length ? records.map(item => `<div class="event-row"><span class="activity-mark ${item.status === "error" ? "bad" : ""}">${item.status === "error" ? "!" : "✓"}</span><span><strong>${extendedEscape(item.action)}</strong><small>${extendedEscape(item.actor || "System")} · ${extendedEscape(item.status === "error" ? "Failed" : "Success")} · ${extendedEscape(formatTime(item.created_at))}</small></span></div>`).join("") : '<p class="quiet-state">No matching audit records.</p>'; }; let timer; tab.addEventListener("click", async () => { document.querySelectorAll("[data-admin-tab]").forEach(item => item.classList.toggle("tab-active", item === tab)); document.querySelectorAll("[data-admin-panel]").forEach(item => item.classList.toggle("hidden", item !== panel)); await load(); }); panel.querySelector("#audit-action").addEventListener("input", () => { clearTimeout(timer); timer = setTimeout(load, 300); }); panel.querySelector("#audit-status").addEventListener("change", load); }
function hideRestrictedControls() { if (state.user?.role !== "viewer") return; document.querySelectorAll("#access-list .menu-wrap, #redirect-list .menu-wrap, #stream-list .menu-wrap, #access-list [data-access-action=toggle], #redirect-list [data-redirect-action=toggle], #stream-list [data-stream-action=toggle], .create-trigger, #open-create, #create-backup, #import-backup").forEach(element => { element.classList.add("hidden"); element.setAttribute("aria-hidden", "true"); }); }
function renderRetentionPanel() { if (state.user?.role !== "administrator") return; const tabs = document.querySelector(".admin-tabs"), users = document.querySelector('[data-admin-panel="users"]'); if (!tabs || !users) return; let tab = tabs.querySelector('[data-admin-tab="retention"]'); if (!tab) { tab = document.createElement("button"); tab.dataset.adminTab = "retention"; tab.textContent = "Logs & retention"; tabs.append(tab); } let panel = document.querySelector('[data-admin-panel="retention"]'); if (!panel) { panel = document.createElement("section"); panel.dataset.adminPanel = "retention"; panel.className = "settings-panel hidden"; users.parentElement.append(panel); } const policy = state.settings?.logsRetention || { accessDays:30, activityDays:90, auditDays:365, certificateDays:365, securityDays:365, pruningEnabled:false }; panel.innerHTML = `<div class="panel-heading"><div><h2>Logs & retention</h2><p class="muted">Choose how long Site Gateway keeps operational and administrative records. Pruning is disabled until you enable it.</p></div></div><form class="settings-form retention-form"><label class="check-control"><input name="pruningEnabled" type="checkbox" ${policy.pruningEnabled ? "checked" : ""}><span>Enable automatic pruning</span></label><label>Access logs<input name="accessDays" type="number" min="7" max="3650" value="${policy.accessDays}"><small>High-volume request records.</small></label><label>Gateway activity<input name="activityDays" type="number" min="7" max="3650" value="${policy.activityDays}"><small>Operational and configuration events.</small></label><label>Audit logs<input name="auditDays" type="number" min="7" max="3650" value="${policy.auditDays}"><small>Administrative accountability records.</small></label><label>Certificate events<input name="certificateDays" type="number" min="7" max="3650" value="${policy.certificateDays}"></label><label>Security events<input name="securityDays" type="number" min="7" max="3650" value="${policy.securityDays}"></label><div class="dialog-actions"><button class="button primary">Save retention policy</button></div></form>`; panel.querySelector("form").addEventListener("submit", async event => { event.preventDefault(); const form = new FormData(event.target); try { const updated = await api("/api/settings", { method:"PATCH", headers:{"Content-Type":"application/json"}, body:JSON.stringify({ logsRetention:{ accessDays:Number(form.get("accessDays")), activityDays:Number(form.get("activityDays")), auditDays:Number(form.get("auditDays")), certificateDays:Number(form.get("certificateDays")), securityDays:Number(form.get("securityDays")), pruningEnabled:form.has("pruningEnabled") } }) }); state.settings = updated; toast("Log retention policy saved."); } catch (error) { toast(error.message); } }); }
// The single entry point app.js calls after every refresh() to re-render every
// view and admin panel owned by this file.
window.renderExtendedViews = function () { renderStreams(); renderRedirects(); renderAccessLists(); decorateAccessAssignments(); decorateAccessGroups(); decorateAccessToggles(); renderBackups(); renderDefaultSettings(); renderHealthSettings(); renderGroups(); decorateGroupCards(); renderAuditPanel(); renderRetentionPanel(); const retentionPanel = document.querySelector('[data-admin-panel="retention"]'); const retentionHeading = retentionPanel?.querySelector('.panel-heading > div'); if (retentionHeading && !retentionHeading.querySelector('.retention-eyebrow')) retentionHeading.insertAdjacentHTML("afterbegin", '<p class="eyebrow retention-eyebrow">AUTOMATIC LOG PRUNING</p>'); const retentionActions = retentionPanel?.querySelector('.retention-actions'); if (retentionPanel && !retentionActions) { retentionPanel.querySelector('.panel-heading')?.insertAdjacentHTML('beforeend', '<div class="row-actions retention-actions"><button class="button secondary" type="button" data-retention-action="prune">Prune Now</button><button class="button secondary" type="button" data-retention-action="download">Download Logs</button></div>'); retentionPanel.querySelector('[data-retention-action="prune"]')?.addEventListener('click', () => toast('Pruning will run when automatic pruning is enabled and the policy is saved.')); retentionPanel.querySelector('[data-retention-action="download"]')?.addEventListener('click', () => toast('Log download is not available yet.')); } normalizeAdminTabOrder(); hideRestrictedControls(); };
// Populate the scheduled-backup "Hour" <select> with 0-23.
for (let hour = 0; hour < 24; hour++) document.querySelector('#backup-settings-form [name="hour"]').insertAdjacentHTML("beforeend", `<option value="${hour}">${String(hour).padStart(2,"0")}:00</option>`);
// --- Streaming host: create/edit dialog and card actions -----------------------
document.querySelector("#stream-form").addEventListener("submit", async event => {
event.preventDefault(); const form = new FormData(event.target), body = { name: form.get("name"), port: Number(form.get("port")), target: form.get("target"), tcp: form.has("tcp"), udp: form.has("udp"), healthEnabled: form.has("healthEnabled") }; document.querySelector("#stream-error").textContent = "";
try { const id = event.target.dataset.editing; await api(id ? `/api/streams/${id}` : "/api/streams", { method: id ? "PATCH" : "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) }); delete event.target.dataset.editing; document.querySelector("#stream-dialog").close(); await refresh(); toast(`Streaming host ${id ? "updated" : "created"} and applied.`); } catch (error) { document.querySelector("#stream-error").textContent = error.message; }
});
document.querySelector("#stream-list").addEventListener("click", async event => {
const button = event.target.closest("[data-stream-action]"), card = button?.closest("[data-stream-id]"); if (!button || !card) return; const item = state.streams.find(value => value.id === card.dataset.streamId); if (!item) return;
try {
if (button.dataset.streamAction === "edit") { const form = document.querySelector("#stream-form"); form.reset(); form.dataset.editing = item.id; form.elements.name.value = item.name || ""; form.elements.port.value = item.port; form.elements.target.value = item.target || ""; form.elements.tcp.checked = item.tcp !== false; form.elements.udp.checked = Boolean(item.udp); form.elements.healthEnabled.checked = item.healthEnabled !== false; document.querySelector("#stream-title").textContent = "Edit streaming host"; document.querySelector("#stream-form .button.primary").textContent = "Save & apply"; document.querySelector("#stream-error").textContent = ""; document.querySelector("#stream-dialog").showModal(); return; }
if (button.dataset.streamAction === "icon") { card.classList.remove("menu-open"); return openIconPicker("streams", item.id); }
if (button.dataset.streamAction === "delete") { if (!confirm(`Delete streaming host “${item.name}”?`)) return; await api(`/api/streams/${item.id}`, { method: "DELETE" }); await refresh(); toast("Streaming host deleted."); return; }
await api(`/api/streams/${item.id}/toggle`, { method: "POST" }); await refresh(); toast("Streaming host updated.");
} catch (error) { toast(error.message); }
});
// Card options menu open/close toggle.
document.querySelector("#stream-list").addEventListener("click", event => { if (event.target.closest(".menu-button")) { const card = event.target.closest("[data-stream-id]"); const opening = !card.classList.contains("menu-open"); document.querySelectorAll("#stream-list .menu-open").forEach(item => item.classList.remove("menu-open")); card.classList.toggle("menu-open", opening); card.querySelector(".menu-button")?.setAttribute("aria-expanded", String(opening)); } });
// --- Redirect host: create/edit dialog and related field wiring ----------------
document.querySelector("#redirect-form").addEventListener("submit", async event => {
event.preventDefault(); const form = new FormData(event.target), body = Object.fromEntries(form); body.domains = String(form.get("domainsText") || "").split(/[\n,]+/).map(value => value.trim()).filter(Boolean); body.preservePath = form.has("preservePath"); document.querySelector("#redirect-error").textContent = "";
try { const id = event.target.dataset.editing; await api(id ? `/api/redirects/${id}` : "/api/redirects", { method:id ? "PATCH" : "POST", headers:{"Content-Type":"application/json"}, body:JSON.stringify(body) }); delete event.target.dataset.editing; document.querySelector("#redirect-dialog").close(); await refresh(); toast(`Redirect Host ${id ? "updated" : "created"} and applied.`); } catch (error) { document.querySelector("#redirect-error").textContent = error.message; }
});
document.querySelector("#redirect-list")?.addEventListener("click", event => { if (!event.target.closest("[data-redirect-action=edit]")) return; const row = event.target.closest("[data-redirect-id]"); const item = state.redirects.find(value => value.id === row?.dataset.redirectId); if (!item) return; setTimeout(() => { const form = document.querySelector("#redirect-form"); if (form.elements.domainsText) form.elements.domainsText.value = (item.domains || []).filter(domain => domain !== item.domain).join("\n"); if (form.elements.accessListId) form.elements.accessListId.value = item.accessListId || ""; }, 0); }, true);
if (!document.querySelector("#redirect-form [name=domainsText]")) { const source = document.querySelector("#redirect-form [name=domain]"); const label = document.createElement("label"); label.innerHTML = 'Additional source domains <span class="optional">Optional</span><textarea name="domainsText" placeholder="www.old.example.com\nold.example.net"></textarea><small>One alias per line. All source domains use this redirect destination.</small>'; source.closest("label").after(label); }
if (!document.querySelector("#redirect-form [name=accessListId]")) { const tls = document.querySelector("#redirect-form [name=tls]")?.closest("label"); if (tls) { const label = document.createElement("label"); label.innerHTML = '<span>Access List <span class="optional">Optional</span></span><select name="accessListId"><option value="">Public — no Access List</option></select><small>Protect this redirect and all of its source domains.</small>'; tls.before(label); } }
// --- Access List: create/edit dialog --------------------------------------------
document.querySelector("#access-form").addEventListener("submit", async event => {
event.preventDefault(); const form = new FormData(event.target), body = { name:form.get("name"), networks:form.get("networks"), deniedNetworks:form.get("deniedNetworks") }; const editorRows = [...document.querySelectorAll("#access-credential-editor .credential-row")]; body.credentials = editorRows.map(row => ({ username: row.querySelector("[name=credentialUsername]").value.trim(), password: row.querySelector("[name=credentialPassword]").value })).filter(entry => entry.username); if (!event.target.dataset.editing) body.groups = [...document.querySelectorAll("#access-create-groups [data-create-group]:checked")].map(input => input.dataset.createGroup); document.querySelector("#access-error").textContent = "";
try { const id = event.target.dataset.editing; await api(id ? `/api/access-lists/${id}` : "/api/access-lists", { method:id ? "PATCH" : "POST", headers:{"Content-Type":"application/json"}, body:JSON.stringify(body) }); delete event.target.dataset.editing; document.querySelector("#access-dialog").close(); await refresh(); toast(`Access List ${id ? "updated" : "created"}.`); } catch (error) { document.querySelector("#access-error").textContent = error.message; }
});
// Renders the login-credential rows inside the Access List dialog.
function renderCredentialEditor(credentials = []) { const editor = document.querySelector("#access-credential-editor"); editor.classList.remove("hidden"); editor.innerHTML = `<div class="credential-editor-heading"><strong>Login accounts</strong><button type="button" class="button secondary" id="add-access-credential">Add login</button></div><p class="muted">Add a username and password. When editing an existing user, leave the password blank to keep it unchanged.</p>${credentials.map(credential => `<div class="credential-row"><input name="credentialUsername" value="${extendedEscape(credential.username)}" placeholder="Username"><input name="credentialPassword" type="password" minlength="8" placeholder="New password"><button type="button" class="button secondary danger-text remove-credential">Remove</button></div>`).join("")}`; document.querySelector("#add-access-credential").addEventListener("click", () => { const row = document.createElement("div"); row.className = "credential-row"; row.innerHTML = '<input name="credentialUsername" placeholder="Username"><input name="credentialPassword" type="password" minlength="8" placeholder="Password"><button type="button" class="button secondary danger-text remove-credential">Remove</button>'; editor.append(row); row.querySelector(".remove-credential").addEventListener("click", () => row.remove()); }); editor.querySelectorAll(".remove-credential").forEach(button => button.addEventListener("click", () => button.closest(".credential-row").remove())); }
window.renderCredentialEditor = renderCredentialEditor;
// Redirect card options menu actions: edit / change icon / delete.
document.querySelector("#redirect-list").addEventListener("click", async event => {
const button = event.target.closest("[data-redirect-action]"), card = button?.closest("[data-redirect-id]"); if (!button || !card) return; const item = state.redirects.find(value => value.id === card.dataset.redirectId); if (!item) return;
try { if (button.dataset.redirectAction === "edit") { const form = document.querySelector("#redirect-form"); form.reset(); form.dataset.editing = item.id; for (const key of ["name","domain","target","code","tls"]) form.elements[key].value = item[key] || ""; form.elements.preservePath.checked = item.preservePath !== false; document.querySelector("#redirect-dialog").showModal(); return; } if (button.dataset.redirectAction === "delete") { if (!confirm(`Delete redirect “${item.name}”?`)) return; await api(`/api/redirects/${item.id}`, { method:"DELETE" }); } else if (button.dataset.redirectAction === "toggle") await api(`/api/redirects/${item.id}`, { method:"PATCH", headers:{"Content-Type":"application/json"}, body:JSON.stringify({ enabled:!item.enabled }) }); else return; await refresh(); toast("Redirect Host updated."); } catch (error) { toast(error.message); }
});
// Themed replacement for a native confirm() dialog, used for destructive
// Access List actions.
function themedAccessDialog(title, copy, confirmLabel = "Delete", danger = false, eyebrow = "Access Lists") { let dialog = document.querySelector("#access-action-dialog"); if (!dialog) { dialog = document.createElement("dialog"); dialog.id = "access-action-dialog"; document.body.append(dialog); } dialog.innerHTML = `<form method="dialog" class="dialog-card compact"><div class="dialog-heading"><div><p class="eyebrow">${extendedEscape(eyebrow)}</p><h2>${extendedEscape(title)}</h2></div></div><p class="muted">${copy}</p><div class="dialog-actions"><button value="cancel" class="button secondary">Cancel</button>${confirmLabel ? `<button value="confirm" class="button ${danger ? "danger" : "primary"}">${extendedEscape(confirmLabel)}</button>` : ""}</div></form>`; dialog.showModal(); return new Promise(resolve => dialog.addEventListener("close", () => resolve(dialog.returnValue === "confirm"), { once:true })); }
// Access List card actions: edit / change icon / view assignments / toggle /
// delete.
document.querySelector("#access-list").addEventListener("click", async event => {
if (event.target.closest(".menu-button")) { const card = event.target.closest("[data-access-id]"); const opening = !card.classList.contains("menu-open"); document.querySelectorAll("#access-list .menu-open").forEach(item => item.classList.remove("menu-open")); card.classList.toggle("menu-open", opening); card.querySelector(".menu-button")?.setAttribute("aria-expanded", String(opening)); return; }
const button = event.target.closest("[data-access-action]"), row = button?.closest("[data-access-id]"); if (!button || !row) return; const item = state.accessLists.find(value => value.id === row.dataset.accessId); if (!item) return;
try { const assigned = [...state.proxies, ...state.sites, ...state.redirects].filter(host => host.accessListId === item.id); if (button.dataset.accessAction === "edit") { const latest = (await api("/api/access-lists")).find(value => value.id === item.id) || item; state.accessLists = state.accessLists.map(value => value.id === item.id ? latest : value); const form = document.querySelector("#access-form"); form.reset(); form.querySelector(".access-create-guidance")?.remove(); form.querySelector("#access-create-groups")?.remove(); form.dataset.editing = latest.id; form.elements.name.value = latest.name; form.elements.networks.value = (latest.networks || []).join("\n"); form.elements.deniedNetworks.value = (latest.deniedNetworks || []).join("\n"); const summary = document.querySelector("#access-assignment-summary"); summary.classList.remove("hidden"); summary.innerHTML = ""; renderCredentialEditor(latest.credentials || []); renderAssignmentEditor(latest.id); ensureAssignmentSearch(); renderAccessGroupSelector(latest.id); document.querySelector("#access-dialog").showModal(); return; } if (button.dataset.accessAction === "icon") { row.classList.remove("menu-open"); openIconPicker("access", item.id); return; } if (button.dataset.accessAction === "assignments") { row.classList.remove("menu-open"); await themedAccessDialog(`Assigned hosts · ${item.name}`, assigned.length ? `<strong>${assigned.length} protected host${assigned.length === 1 ? "" : "s"}</strong><div class="assignment-host-list">${assigned.map(host => `<span class="assignment-host-chip"><b>${extendedEscape(host.name || host.domain)}</b><small>${extendedEscape(host.domain || "No domain")}</small></span>`).join("")}</div>` : "This Access List is not assigned to any hosts.", ""); return; } if (button.dataset.accessAction === "delete") { const copy = assigned.length ? `This Access List protects ${assigned.length} active host${assigned.length === 1 ? "" : "s"}. Delete it anyway?` : `Delete Access List “${extendedEscape(item.name)}”?`; if (!(await themedAccessDialog("Delete Access List?", copy, "Delete", true))) return; await api(`/api/access-lists/${item.id}`, { method:"DELETE" }); } else { if (item.enabled !== false && assigned.length && !(await themedAccessDialog("Disable Access List?", `Disabling this Access List will remove protection from ${assigned.length} active host${assigned.length === 1 ? "" : "s"}. Continue?`, "Disable", true))) return; await api(`/api/access-lists/${item.id}`, { method:"PATCH", headers:{"Content-Type":"application/json"}, body:JSON.stringify({ enabled:item.enabled === false }) }); } await refresh(); toast("Access List updated."); } catch (error) { toast(error.message); }
});
document.querySelector("#access-list").addEventListener("click", event => { if (!event.target.closest("[data-access-action=edit]")) return; const row = event.target.closest("[data-access-id]"); const item = state.accessLists.find(value => value.id === row?.dataset.accessId); if (!item) return; setTimeout(() => { const assigned = [...state.proxies, ...state.sites, ...state.redirects].filter(host => host.accessListId === item.id); const summary = document.querySelector("#access-assignment-summary"); if (!summary) return; summary.innerHTML = assigned.length ? `<strong>Assigned hosts (${assigned.length})</strong><div class="assignment-host-list">${assigned.map(host => `<span class="assignment-host-chip"><b>${extendedEscape(host.name || host.domain)}</b><small>${extendedEscape(host.domain || "No domain")}</small></span>`).join("")}</div>` : `<strong>Assigned hosts</strong><span>This Access List is not assigned to a host yet.</span>`; }, 0); });
// --- Administration: tab switching between admin panel sections ----------------
document.querySelector(".admin-tabs").addEventListener("click", event => { const button = event.target.closest("[data-admin-tab]"); if (!button) return; document.querySelectorAll("[data-admin-tab]").forEach(item => item.classList.toggle("tab-active", item === button)); document.querySelectorAll("[data-admin-panel]").forEach(panel => panel.classList.toggle("hidden", panel.dataset.adminPanel !== button.dataset.adminTab)); document.querySelector("#open-create").classList.toggle("hidden", button.dataset.adminTab !== "users"); });
document.querySelector(".admin-tabs").addEventListener("click", event => { const button = event.target.closest("[data-admin-tab]"); if (!button) return; state.adminTab = button.dataset.adminTab; history.replaceState(null, "", `${location.pathname}${location.search}#administration/${state.adminTab}`); });
if (state.adminTab && state.view === "administration") document.querySelector(`[data-admin-tab="${state.adminTab}"]`)?.click();
// --- Gateway defaults form submit ------------------------------------------------
document.querySelector("#default-site-form").addEventListener("submit", async event => { event.preventDefault(); const form = new FormData(event.target), value = Object.fromEntries(form); value.preservePath = form.has("preservePath"); try { state.settings = await api("/api/settings", { method:"PATCH", headers:{"Content-Type":"application/json"}, body:JSON.stringify({defaultSite:value}) }); toast("Default Site validated and applied."); } catch (error) { document.querySelector("#default-error").textContent = error.message; } });
// --- Backup & restore: schedule type change, health settings save, restore
// defaults, and factory reset --------------------------------------------------
document.querySelector("#backup-settings-form [name=type]")?.addEventListener("change", event => { document.querySelector("#backup-type-help").textContent = event.target.value === "complete" ? "Complete backups include configuration, uploaded Hosted Site files, icons, default-site assets, and certificate storage. Verify the file count after creation." : "Configuration-only backups include settings and metadata, but not uploaded Hosted Site files."; }); document.querySelector("#backup-settings-form")?.insertAdjacentHTML("beforeend", '<p id="backup-schedule-status" class="inline-status" aria-live="polite"></p>'); document.querySelector("#backup-settings-form").addEventListener("submit", async event => { event.preventDefault(); const form = new FormData(event.target), backups = Object.fromEntries(form); delete backups.backupPassword; backups.enabled = form.has("enabled"); backups.includeLogs = form.has("includeLogs"); backups.encrypt = form.has("encrypt"); try { state.settings = await api("/api/settings", { method:"PATCH", headers:{"Content-Type":"application/json"}, body:JSON.stringify({backups}) }); const scheduleStatus = document.querySelector("#backup-schedule-status"); scheduleStatus.className = `inline-status ${backups.enabled ? "status-success" : "status-warning"}`; scheduleStatus.textContent = backups.enabled ? `Scheduled backups enabled · ${backups.frequency} · ${backups.type === "complete" ? "complete backups" : "configuration backups"}.` : "Scheduled backups disabled. Your saved schedule remains available if you enable it later."; } catch (error) { toast(error.message); } });
document.querySelector("#health-settings-form").addEventListener("submit", async event => { event.preventDefault(); const certificateHealth = Object.fromEntries(new FormData(event.target)); try { state.settings = await api("/api/settings", { method:"PATCH", headers:{"Content-Type":"application/json"}, body:JSON.stringify({certificateHealth}) }); renderHealthSettings(); toast("Certificate health thresholds saved."); } catch (error) { toast(error.message); } });
const restoreDefaultsButton = document.querySelector("#restore-defaults"); restoreDefaultsButton.insertAdjacentHTML("beforebegin", '<div class="danger-credentials"><label>Administrator username<input id="restore-admin-username" autocomplete="username" required></label><label>Administrator password<input id="restore-admin-password" type="password" autocomplete="current-password" required></label><label>Type <strong>RESTORE DEFAULT</strong> to confirm<input id="restore-confirmation" autocomplete="off" required></label><p id="restore-defaults-error" class="error"></p></div>'); const restoreUsername = document.querySelector("#restore-admin-username"), restorePassword = document.querySelector("#restore-admin-password"), restoreConfirmation = document.querySelector("#restore-confirmation"), restoreInlineError = document.querySelector("#restore-defaults-error"); restoreUsername.addEventListener("blur", async () => { if (!restoreUsername.value.trim()) { restoreInlineError.textContent = "Enter the administrator username."; return; } try { const identity = await api("/api/settings/verify-username", {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:restoreUsername.value.trim()})}); restoreInlineError.textContent = identity.valid ? "" : "That administrator username was not found."; } catch (error) { restoreInlineError.textContent = error.message; } }); restorePassword.addEventListener("blur", async () => { if (!restorePassword.value) { restoreInlineError.textContent = "Enter the administrator password."; return; } if (!restoreUsername.value.trim()) { restoreInlineError.textContent = "Enter the administrator username first."; return; } try { await api("/api/settings/verify-admin", {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:restoreUsername.value.trim(),password:restorePassword.value})}); restoreInlineError.textContent = ""; } catch (error) { restoreInlineError.textContent = "The password is incorrect for the entered administrator."; } }); restoreConfirmation.addEventListener("blur", () => { if (restoreConfirmation.value && restoreConfirmation.value.trim() !== "RESTORE DEFAULT") restoreInlineError.textContent = "Type RESTORE DEFAULT exactly to continue."; }); restoreDefaultsButton.addEventListener("click", async event => { event.preventDefault(); const username = document.querySelector("#restore-admin-username").value.trim(), password = document.querySelector("#restore-admin-password").value, confirmation = document.querySelector("#restore-confirmation").value.trim(); const inlineError = document.querySelector("#restore-defaults-error"); inlineError.textContent = ""; if (!username) { inlineError.textContent = "Enter the administrator username."; return; } try { const identity = await api("/api/settings/verify-username", {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username})}); if (!identity.valid) { inlineError.textContent = "That administrator username was not found."; return; } } catch (error) { inlineError.textContent = error.message; return; } if (!password) { inlineError.textContent = "Enter the administrator password."; return; } try { await api("/api/settings/verify-admin", {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username,password})}); } catch (error) { inlineError.textContent = "The password is incorrect for the entered administrator."; return; } if (confirmation !== "RESTORE DEFAULT") { inlineError.textContent = "Type RESTORE DEFAULT exactly to continue."; return; } let dialog = document.querySelector("#restore-defaults-confirm-dialog"); if (!dialog) { dialog = document.createElement("dialog"); dialog.id = "restore-defaults-confirm-dialog"; dialog.innerHTML = '<form method="dialog" class="dialog-card"><div class="dialog-heading"><div><p class="eyebrow">Gateway preferences</p><h2>Confirm restore defaults</h2></div></div><p class="muted">This restores the default site behavior, backup scheduling, certificate thresholds, and interface preferences. Users, routes, hosted files, certificates, logs, backups, and Access Lists will remain unchanged.</p><label>Type <strong>YES</strong> to continue<input name="yes" autocomplete="off" required></label><p class="error" data-restore-error></p><div class="dialog-actions"><button value="cancel" formnovalidate class="button secondary">Cancel</button><button value="confirm" class="button primary">Restore defaults</button></div></form>'; document.body.append(dialog); } dialog.querySelector('[name="yes"]').value = ""; dialog.showModal(); const result = await new Promise(resolve => dialog.addEventListener("close", () => resolve(dialog.returnValue), { once:true })); if (result !== "confirm" || dialog.querySelector('[name="yes"]').value.trim().toUpperCase() !== "YES") { dialog.querySelector('[name="yes"]').value = ""; document.querySelector("#restore-admin-username").value = ""; document.querySelector("#restore-admin-password").value = ""; document.querySelector("#restore-confirmation").value = ""; document.querySelector("#restore-defaults-error").textContent = ""; return; } try { state.settings = await api("/api/settings/reset-defaults", {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username,password,confirmation})}); dialog.querySelector(".dialog-card").innerHTML = '<div class="dialog-heading"><div><p class="eyebrow">Gateway preferences</p><h2>Defaults restored</h2></div></div><p class="muted">The gateway preferences were restored successfully. Your data and routes were preserved.</p>'; state.settings = await api("/api/settings"); renderDefaultSettings(); renderBackups(); document.querySelector("#restore-admin-username").value = ""; document.querySelector("#restore-admin-password").value = ""; document.querySelector("#restore-confirmation").value = ""; dialog.showModal(); setTimeout(() => dialog.close(), 900); } catch (error) { dialog.querySelector("[data-restore-error]").textContent = error.message; if (!dialog.open) dialog.showModal(); } });
const factoryResetForm = document.querySelector("#factory-reset-form"), factoryUsername = factoryResetForm.elements.username, factoryPassword = factoryResetForm.elements.password, factoryConfirmation = factoryResetForm.elements.confirmation, factoryInlineError = document.querySelector("#factory-reset-error"); factoryUsername.addEventListener("blur", async () => { if (!factoryUsername.value.trim()) { factoryInlineError.textContent = "Enter the administrator username."; return; } try { const identity = await api("/api/settings/verify-username", {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:factoryUsername.value.trim()})}); factoryInlineError.textContent = identity.valid ? "" : "That administrator username was not found."; } catch (error) { factoryInlineError.textContent = error.message; } }); factoryPassword.addEventListener("blur", async () => { if (!factoryPassword.value) { factoryInlineError.textContent = "Enter the administrator password."; return; } if (!factoryUsername.value.trim()) { factoryInlineError.textContent = "Enter the administrator username first."; return; } try { await api("/api/settings/verify-admin", {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:factoryUsername.value.trim(),password:factoryPassword.value})}); factoryInlineError.textContent = ""; } catch (error) { factoryInlineError.textContent = "The password is incorrect for the entered administrator."; } }); factoryConfirmation.addEventListener("blur", () => { if (factoryConfirmation.value && factoryConfirmation.value.trim() !== "FACTORY RESET") factoryInlineError.textContent = "Type FACTORY RESET exactly to continue."; }); document.querySelector("#factory-reset-form").addEventListener("submit", async event => { event.preventDefault(); const form = new FormData(event.target), confirmation = String(form.get("confirmation") || ""), resetError = document.querySelector("#factory-reset-error"), username = String(form.get("username") || "").trim(), password = String(form.get("password") || ""); resetError.textContent = ""; if (!username) { resetError.textContent = "Enter the administrator username."; return; } try { const identity = await api("/api/settings/verify-username", {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username})}); if (!identity.valid) { resetError.textContent = "That administrator username was not found."; return; } } catch (error) { resetError.textContent = error.message; return; } if (!password) { resetError.textContent = "Enter the administrator password."; return; } try { await api("/api/settings/verify-admin", {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username,password})}); } catch (error) { resetError.textContent = "The password is incorrect for the entered administrator."; return; } if (confirmation !== "FACTORY RESET") { resetError.textContent = "Type FACTORY RESET exactly to continue."; return; } let dialog = document.querySelector("#factory-reset-confirm-dialog"); if (!dialog) { dialog = document.createElement("dialog"); dialog.id = "factory-reset-confirm-dialog"; dialog.innerHTML = '<form method="dialog" class="dialog-card"><div class="dialog-heading"><div><p class="eyebrow">Permanent action</p><h2>Confirm factory reset</h2></div></div><p class="muted">This will permanently delete all Site Gateway data under <code>/data</code>, including hosted files, routes, users, groups, Access Lists, certificates, logs, backups, and settings. The container will restart and return to the first-install setup screen.</p><p class="muted">After restart, open the management URL again and use the original installation credentials to begin setup.</p><label>Type <strong>YES</strong> to continue<input name="yes" autocomplete="off" required></label><p class="error" data-reset-error></p><div class="dialog-actions"><button value="cancel" formnovalidate class="button secondary">Cancel</button><button value="confirm" class="button danger">Yes, reset Site Gateway</button></div></form>'; document.body.append(dialog); } dialog.querySelector('[name="yes"]').value = ""; dialog.showModal(); const result = await new Promise(resolve => dialog.addEventListener("close", () => resolve(dialog.returnValue), { once:true })); if (result !== "confirm" || dialog.querySelector('[name="yes"]').value.trim().toUpperCase() !== "YES") { dialog.querySelector('[name="yes"]').value = ""; factoryResetForm.reset(); factoryInlineError.textContent = ""; return; } try { await api("/api/factory-reset", {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Object.fromEntries(form))}); dialog.querySelector(".dialog-card").innerHTML = '<div class="dialog-heading"><div><p class="eyebrow">Permanent action</p><h2>Factory reset in progress</h2></div></div><p class="muted">Site Gateway is deleting its data and restarting. Keep this window open. The first-install setup screen will open automatically when the container is ready.</p><p class="reset-countdown" aria-live="polite">Restarting in <strong data-reset-countdown>10</strong> seconds…</p>'; dialog.showModal(); let seconds = 10; const timer = setInterval(() => { seconds--; const counter = dialog.querySelector("[data-reset-countdown]"); if (counter) counter.textContent = String(seconds); if (seconds <= 0) { clearInterval(timer); if (counter) counter.textContent = "Opening setup…"; dialog.close(); const openSetup = () => { window.location.href = "/"; }; (async () => { for (let attempt = 0; attempt < 30; attempt++) { try { const response = await fetch("/api/session", { cache: "no-store" }); if (response.ok) { openSetup(); return; } } catch {} await new Promise(resolve => setTimeout(resolve, 1000)); } openSetup(); })(); window.setTimeout(openSetup, 5000); } }, 1000); } catch (error) { document.querySelector("#factory-reset-error").textContent = error.message; } });
// --- Backup import / manual create / restore flows -------------------------------
document.querySelector("#import-backup").addEventListener("click", () => document.querySelector("#backup-upload").click());
async function themedConfirm(title, message, actionLabel = "Continue") { let dialog = document.querySelector("#backup-action-dialog"); if (!dialog) { dialog = document.createElement("dialog"); dialog.id = "backup-action-dialog"; document.body.append(dialog); } dialog.innerHTML = `<form method="dialog" class="dialog-card"><div class="dialog-heading"><div><p class="eyebrow">Backup & restore</p><h2>${title}</h2></div></div><p class="muted">${message}</p><div class="dialog-actions"><button value="cancel" formnovalidate class="button secondary">Cancel</button><button value="confirm" class="button primary">${actionLabel}</button></div></form>`; dialog.showModal(); return new Promise(resolve => dialog.addEventListener("close", () => resolve(dialog.returnValue === "confirm"), { once:true })); }
document.querySelector("#backup-upload").addEventListener("change", async event => { const file = event.target.files[0]; if (!file) return; const data = new FormData(), password = document.querySelector('#backup-settings-form [name="backupPassword"]').value; data.append("backup", file); data.append("password", password); try { await api("/api/backups/import", { method:"POST", body:data }); state.backups = await api("/api/backups"); renderBackups(); toast("Backup imported. Review it before restoring."); } catch (error) { toast(error.message); } finally { event.target.value = ""; } });
document.querySelector("#backup-list").addEventListener("click", async event => { const button = event.target.closest("[data-backup-action]"), row = button?.closest("[data-backup]"); if (!button || !row) return; const filename = row.dataset.backup; try { if (button.dataset.backupAction === "delete") { if (!await themedConfirm("Delete backup?", `This permanently removes ${filename}. It cannot be restored unless you have another copy.`, "Delete backup")) return; await api(`/api/backups/${encodeURIComponent(filename)}`, {method:"DELETE"}); } else { if (!await themedConfirm("Restore this backup?", "Current data will be replaced after a safety backup is created. Site Gateway validates the archive and can roll back if restoration fails.", "Restore backup")) return; const password = document.querySelector('#backup-settings-form [name="backupPassword"]').value; await api(`/api/backups/${encodeURIComponent(filename)}/restore`, {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password})}); await refresh(); } state.backups = await api("/api/backups"); renderBackups(); toast(button.dataset.backupAction === "delete" ? "Backup deleted." : "Backup restored."); } catch (error) { toast(error.message); } });
const restoreButton = document.querySelector("#restore-defaults"), restoreCredentialsBlock = document.querySelector(".danger-credentials"); if (restoreButton && restoreCredentialsBlock && !restoreButton.closest(".restore-form")) { const restoreForm = document.createElement("form"); restoreForm.className = "danger-form restore-form"; restoreCredentialsBlock.replaceWith(restoreForm); restoreForm.append(restoreCredentialsBlock, restoreButton); } const restoreCancel = document.createElement("button"); restoreCancel.type = "button"; restoreCancel.className = "button secondary"; restoreCancel.textContent = "Cancel"; restoreCancel.id = "restore-defaults-cancel"; const restoreActions = document.createElement("div"); restoreActions.className = "danger-actions"; restoreButton.parentNode.insertBefore(restoreActions, restoreButton); restoreActions.append(restoreCancel, restoreButton); restoreCancel.addEventListener("click", () => { document.querySelector("#restore-admin-username").value = ""; document.querySelector("#restore-admin-password").value = ""; document.querySelector("#restore-confirmation").value = ""; document.querySelector("#restore-defaults-error").textContent = ""; }); document.querySelector("#factory-reset-cancel")?.addEventListener("click", () => { document.querySelector("#factory-reset-form").reset(); document.querySelector("#factory-reset-error").textContent = ""; });
// --- Documentation accordion (Administration > Documentation) --------------------
document.querySelectorAll("#docs-content article").forEach((article, index) => { article.id = `doc-${index}`; }); document.querySelectorAll("[data-doc-jump]").forEach(button => button.addEventListener("click", () => { const key = button.dataset.docJump; const article = [...document.querySelectorAll("#docs-content article")].find(item => item.dataset.doc.includes(key)); article?.scrollIntoView({ behavior:"instant", block:"start" }); })); document.querySelector("#doc-search").addEventListener("input", event => { const query = event.target.value.trim().toLowerCase(), articles = [...document.querySelectorAll("#docs-content article")]; let topResult = null, topOrder = Infinity; articles.forEach((article, index) => { const eyebrow = (article.querySelector(".eyebrow")?.textContent || "").toLowerCase(), heading = (article.querySelector("h2")?.textContent || "").toLowerCase(), keywords = (article.dataset.doc || "").toLowerCase(), topicMatch = !query || eyebrow.includes(query) || heading.includes(query), keywordMatch = !topicMatch && keywords.includes(query), match = topicMatch || keywordMatch || article.textContent.toLowerCase().includes(query), order = topicMatch ? index : keywordMatch ? index + articles.length : index + articles.length * 2; article.style.order = ""; if (match && order < topOrder) { topOrder = order; topResult = article; } }); articles.forEach(article => article.classList.toggle("hidden", Boolean(query) && article !== topResult)); document.querySelector("#doc-empty").classList.toggle("hidden", Boolean(!query || topResult)); });
// --- Proxy dialog: show/hide the custom-certificate fields based on TLS mode -----
document.querySelector("#proxy-dialog").addEventListener("close", () => document.querySelector("#proxy-dialog details")?.removeAttribute("open"));
document.querySelectorAll("#proxy-form, #settings-form").forEach(form => form.elements.tls.addEventListener("change", () => { const fields = form.querySelector("#custom-certificate-fields, .custom-certificate-fields"); fields?.classList.toggle("custom-certificate-visible", form.elements.tls.value === "custom"); }));
// --- Access List assignment editor: which hosts use this Access List -------------
function renderAssignmentEditor(accessListId) { const summary = document.querySelector("#access-assignment-summary"); if (!summary) return; const hosts = [...state.sites.map(host => ({ ...host, kind: "sites", label: "Hosted Site" })), ...state.proxies.map(host => ({ ...host, kind: "proxies", label: "Proxy Host" })), ...state.redirects.map(host => ({ ...host, kind: "redirects", label: "Redirect Host" }))]; summary.classList.remove("hidden"); summary.innerHTML = "<strong>Protected hosts</strong><p class=\"muted\">Select the routes this Access List should protect. Changes apply immediately.</p><div class=\"assignment-editor\">" + (hosts.length ? hosts.map(host => "<label class=\"assignment-option\"><input type=\"checkbox\" data-assignment-kind=\"" + host.kind + "\" data-assignment-id=\"" + host.id + "\"" + (host.accessListId === accessListId ? " checked" : "") + "><span><b>" + extendedEscape(host.name || host.domain || "Unnamed host") + "</b><small>" + host.label + " · " + extendedEscape(host.domain || "No domain") + "</small></span></label>").join("") : "<span class=\"muted\">Create a Hosted Site, Proxy Host, or Redirect Host first.</span>") + "</div>"; }
document.querySelector("#access-list")?.addEventListener("change", async event => { const checkbox = event.target.closest("[data-assignment-kind]"); if (!checkbox) return; const kind = checkbox.dataset.assignmentKind; try { await api("/api/" + kind + "/" + checkbox.dataset.assignmentId, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ accessListId: checkbox.checked ? document.querySelector("#access-form")?.dataset.editing || "" : "" }) }); await refresh(); const current = document.querySelector("#access-form")?.dataset.editing; if (current) renderAssignmentEditor(current); toast(checkbox.checked ? "Host added to Access List." : "Host removed from Access List."); } catch (error) { checkbox.checked = !checkbox.checked; toast(error.message); } });
document.querySelector("#access-list")?.addEventListener("click", event => { if (!event.target.closest("[data-access-action=edit]")) return; const row = event.target.closest("[data-access-id]"); if (row) setTimeout(() => renderAssignmentEditor(row.dataset.accessId), 0); });
// Search/filter within the assignment editor.
function ensureAssignmentSearch() { const editor = document.querySelector("#access-assignment-summary .assignment-editor"); if (!editor || editor.querySelector(".assignment-search")) return; const label = document.createElement("label"); label.className = "assignment-search-label"; label.textContent = "Filter hosts"; const input = document.createElement("input"); input.className = "assignment-search"; input.type = "search"; input.placeholder = "Name, type, or domain"; input.setAttribute("aria-label", "Filter hosts"); label.append(input); editor.before(label); input.addEventListener("input", () => { const query = input.value.trim().toLowerCase(); editor.querySelectorAll(".assignment-option").forEach(option => { option.hidden = query && !option.textContent.toLowerCase().includes(query); }); }); }
document.querySelector("#access-list")?.addEventListener("click", () => setTimeout(ensureAssignmentSearch, 0));
document.addEventListener("input", event => { const input = event.target.closest("#access-assignment-summary .assignment-search"); if (!input) return; const query = input.value.trim().toLowerCase(); document.querySelectorAll("#access-assignment-summary .assignment-option").forEach(option => { option.hidden = Boolean(query) && !option.textContent.toLowerCase().includes(query); }); });
document.addEventListener("change", async event => { const checkbox = event.target.closest("#access-assignment-summary [data-assignment-kind]"); if (!checkbox) return; event.stopImmediatePropagation(); const accessListId = document.querySelector("#access-form")?.dataset.editing; if (!accessListId) return; try { await api("/api/access-lists/" + accessListId + "/assignments", { method:"POST", headers:{"Content-Type":"application/json"}, body:JSON.stringify({ kind:checkbox.dataset.assignmentKind, hostId:checkbox.dataset.assignmentId, assigned:checkbox.checked }) }); await refresh(); renderAssignmentEditor(accessListId); ensureAssignmentSearch(); toast(checkbox.checked ? "Host added to Access List." : "Host removed from Access List."); } catch (error) { checkbox.checked = !checkbox.checked; toast(error.message); } }, true);
document.querySelector("#access-list")?.addEventListener("change", async event => { const checkbox = event.target.closest("[data-assignment-kind]"); if (!checkbox) return; event.stopImmediatePropagation(); const accessListId = document.querySelector("#access-form")?.dataset.editing; const kind = checkbox.dataset.assignmentKind; if (!accessListId) { checkbox.checked = !checkbox.checked; toast("Open an Access List before assigning hosts."); return; } try { await api("/api/access-lists/" + accessListId + "/assignments", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ kind, hostId: checkbox.dataset.assignmentId, assigned: checkbox.checked }) }); await refresh(); renderAssignmentEditor(accessListId); ensureAssignmentSearch(); toast(checkbox.checked ? "Host added to Access List." : "Host removed from Access List."); } catch (error) { checkbox.checked = !checkbox.checked; toast(error.message); } }, true);
// --- Groups admin panel (dynamically inserted "Groups" tab) ----------------------
function renderGroups() { const tabs = document.querySelector(".admin-tabs"); const usersPanel = document.querySelector('[data-admin-panel="users"]'); if (!tabs || !usersPanel) return; let tab = tabs.querySelector('[data-admin-tab="groups"]'); if (!tab) { tab = document.createElement("button"); tab.dataset.adminTab = "groups"; tab.textContent = "Groups"; tabs.insertBefore(tab, tabs.children[1]); } let panel = document.querySelector('[data-admin-panel="groups"]'); if (!panel) { panel = document.createElement("section"); panel.dataset.adminPanel = "groups"; panel.className = "settings-panel hidden"; usersPanel.parentElement.insertBefore(panel, usersPanel.nextElementSibling); } panel.innerHTML = '<div class="panel-heading"><div><h2>Groups</h2><p class="muted">Organize users for Access List permissions.</p></div><button id="create-group" class="button primary">Create group</button></div>' + (state.groups.length ? '<div class="user-grid">' + state.groups.map(group => '<article class="site-card group-card"><div class="card-top"><div class="site-icon">GR</div><div class="menu-wrap"><button class="icon-button menu-button" aria-label="Group options" aria-expanded="false">•••</button><div class="menu"><button data-group-action="edit" data-group-id="' + group.id + '">Edit group</button><button data-group-action="icon" data-group-id="' + group.id + '">Change icon</button><button data-group-action="delete" data-group-id="' + group.id + '" class="danger-text">Delete group</button></div></div></div><h2>' + extendedEscape(group.name) + '</h2><p class="address">' + (group.members?.length || 0) + ' members</p><div class="card-footer"><span class="status-pill"><span class="status-dot ' + (group.enabled === false ? "disabled" : "running") + '"></span>' + (group.enabled === false ? "Disabled" : "Enabled") + '</span><div class="card-actions"><button class="toggle ' + (group.enabled !== false ? "on" : "") + '" data-group-action="toggle" data-group-id="' + group.id + '" aria-label="' + (group.enabled !== false ? "Disable" : "Enable") + ' group"><span></span></button></div></div></article>').join("") + '</div>' : '<p class="quiet-state padded">No groups yet. Create one to organize users.</p>'); }
function openGroupEditor(group) { let dialog = document.querySelector("#group-dialog"); if (!dialog) { dialog = document.createElement("dialog"); dialog.id = "group-dialog"; document.body.append(dialog); } dialog.innerHTML = '<form class="dialog-card group-editor"><div class="dialog-heading"><div><p class="eyebrow">Administration</p><h2>Edit group</h2></div></div><label>Group name<input name="name" required maxlength="80"></label><label>Members <span class="optional">Optional</span></label><p class="muted">Select Site Gateway users who should belong to this group.</p><div class="group-member-options">' + (state.users || []).filter(user => user.status !== "disabled").map(user => '<label class="check-control"><input type="checkbox" name="members" value="' + user.id + '"><span>' + extendedEscape(user.username) + ' <small>' + extendedEscape(user.role || "Standard User") + '</small></span></label>').join("") + '</div><p class="error" data-group-error></p><div class="dialog-actions"><button type="button" class="button secondary close-group-dialog">Cancel</button><button class="button primary">Save group</button></div></form>'; dialog.querySelector('[name="name"]').value = group.name; dialog.querySelectorAll('[name="members"]').forEach(input => { input.checked = (group.memberIds || group.members || []).includes(input.value) || (group.members || []).some(value => value === state.users?.find(user => user.id === input.value)?.username); }); dialog.querySelectorAll(".close-group-dialog").forEach(button => button.addEventListener("click", () => dialog.close())); dialog.querySelector("form").addEventListener("submit", async event => { event.preventDefault(); const form = new FormData(event.target); try { await api("/api/groups/" + group.id, { method:"PATCH", headers:{"Content-Type":"application/json"}, body:JSON.stringify({ name:form.get("name"), members:[...event.target.querySelectorAll('[name="members"]:checked')].map(input => input.value) }) }); dialog.close(); await refresh(); toast("Group updated."); } catch (error) { dialog.querySelector("[data-group-error]").textContent = error.message; } }); dialog.showModal(); }
document.addEventListener("click", event => { const button = event.target.closest('[data-admin-panel="groups"] .group-card .menu-button'); if (!button) return; const card = button.closest(".group-card"); const opening = !card.classList.contains("menu-open"); document.querySelectorAll('[data-admin-panel="groups"] .group-card.menu-open').forEach(item => { item.classList.remove("menu-open"); item.querySelector(".menu-button")?.setAttribute("aria-expanded", "false"); }); card.classList.toggle("menu-open", opening); button.setAttribute("aria-expanded", String(opening)); event.preventDefault(); event.stopImmediatePropagation(); }, true);
function openNewGroupEditor() { let dialog = document.querySelector("#group-dialog"); if (!dialog) { dialog = document.createElement("dialog"); dialog.id = "group-dialog"; document.body.append(dialog); } dialog.innerHTML = '<form class="dialog-card group-editor"><div class="dialog-heading"><div><p class="eyebrow">Administration</p><h2>Create group</h2></div></div><label>Group name<input name="name" required maxlength="80" placeholder="Home users"></label><label>Members <span class="optional">Optional</span></label><p class="muted">Select Site Gateway users who should belong to this group.</p><div class="group-member-options">' + (state.users || []).filter(user => user.status !== "disabled").map(user => '<label class="check-control"><input type="checkbox" name="members" value="' + user.id + '"><span>' + extendedEscape(user.username) + ' <small>' + extendedEscape(user.role || "Standard User") + '</small></span></label>').join("") + '</div><p class="error" data-group-error></p><div class="dialog-actions"><button type="button" class="button secondary close-group-dialog">Cancel</button><button class="button primary">Create group</button></div></form>'; dialog.querySelectorAll(".close-group-dialog").forEach(button => button.addEventListener("click", () => dialog.close())); dialog.querySelector("form").addEventListener("submit", async event => { event.preventDefault(); const form = new FormData(event.target); try { await api("/api/groups", { method:"POST", headers:{"Content-Type":"application/json"}, body:JSON.stringify({ name:String(form.get("name") || "").trim(), members:[...event.target.querySelectorAll('[name="members"]:checked')].map(input => input.value) }) }); dialog.close(); await refresh(); toast("Group created."); } catch (error) { dialog.querySelector("[data-group-error]").textContent = error.message; } }); dialog.showModal(); }
document.addEventListener("click", async event => { if (event.target.id === "create-group") { openNewGroupEditor(); return; } const button = event.target.closest("[data-group-action]"); if (!button) return; const id = button.dataset.groupId; const group = state.groups.find(value => value.id === id); if (button.dataset.groupAction === "edit") { if (group) openGroupEditor(group); return; } if (button.dataset.groupAction === "icon") return; if (button.dataset.groupAction === "delete" && !confirm("Delete this group?")) return; const isToggle = button.dataset.groupAction === "toggle", wasOn = button.classList.contains("on"); if (isToggle && wasOn) { const assignedLists = (state.accessLists || []).filter(list => (list.groups || []).includes(id) && list.enabled !== false); if (assignedLists.length) { const names = assignedLists.map(list => extendedEscape(list.name)).join(", "); if (!(await themedAccessDialog("Disable group?", `Disabling “${extendedEscape(group?.name || "this group")}” will immediately stop its members from signing in through: ${names}. Continue?`, "Disable", true, "Groups"))) return; } } if (isToggle) { button.classList.toggle("on", !wasOn); button.disabled = true; } try { if (button.dataset.groupAction === "delete") await api("/api/groups/" + id, { method:"DELETE" }); else await api("/api/groups/" + id, { method:"PATCH", headers:{"Content-Type":"application/json"}, body:JSON.stringify({ enabled: isToggle ? !wasOn : button.textContent.trim() === "Enable" }) }); await refresh(); toast("Group updated."); } catch (error) { if (isToggle) { button.classList.toggle("on", wasOn); button.disabled = false; } toast(error.message); } });
function renderAccessGroupSelector(accessListId) { const summary = document.querySelector("#access-assignment-summary"); if (!summary || !state.groups) return; let field = summary.querySelector(".access-group-selector"); if (!field) { field = document.createElement("section"); field.className = "access-group-selector"; summary.prepend(field); } const selected = state.accessLists.find(item => item.id === accessListId)?.groups || []; field.innerHTML = "<strong>Allowed groups <span class=\"optional\">Optional</span></strong><p class=\"access-group-help\">Members of enabled groups can sign in with their Site Gateway credentials.</p>" + (state.groups.length ? "<div class=\"access-group-options\">" + state.groups.map(group => "<label class=\"check-control access-group-option\"><input type=\"checkbox\" data-group-option=\"" + group.id + "\"" + (selected.includes(group.id) ? " checked" : "") + "><span>" + extendedEscape(group.name) + " <small>" + (group.members?.length || 0) + " members" + (group.enabled === false ? " · Disabled" : "") + "</small></span></label>").join("") + "</div>" : "<p class=\"access-group-empty\">No groups have been created yet.</p>"); }
document.addEventListener("change", async event => { const option = event.target.closest("[data-group-option]"); if (!option) return; const accessListId = document.querySelector("#access-form")?.dataset.editing; if (!accessListId) return; const groups = [...document.querySelectorAll("#access-assignment-summary [data-group-option]:checked")].map(input => input.dataset.groupOption); try { await api("/api/access-lists/" + accessListId + "/groups", { method:"POST", headers:{"Content-Type":"application/json"}, body:JSON.stringify({ groups }) }); const item = state.accessLists.find(value => value.id === accessListId); if (item) item.groups = groups; renderAccessLists(); decorateAccessGroups(); toast("Access List groups saved."); } catch (error) { option.checked = !option.checked; toast(error.message); } }, true);
document.addEventListener("click", event => { const button = event.target.closest("#access-list [data-access-action=toggle]"); if (button) event.stopImmediatePropagation(); });
document.querySelector("#access-list")?.addEventListener("click", event => { if (!event.target.closest("[data-access-action=edit]")) return; const row = event.target.closest("[data-access-id]"); if (row) setTimeout(() => renderAccessGroupSelector(row.dataset.accessId), 10); });
function decorateAccessGroups() { document.querySelectorAll("#access-list [data-access-id]").forEach(card => { const item = state.accessLists.find(value => value.id === card.dataset.accessId); if (!item) return; if (item.groups?.length && !card.querySelector(".access-group-preview")) { const names = item.groups.map(id => state.groups.find(group => group.id === id)?.name).filter(Boolean); if (names.length) { const preview = document.createElement("p"); preview.className = "access-group-preview"; preview.textContent = "Groups: " + names.join(" · "); card.querySelector(".card-footer")?.before(preview); } } if (!card.querySelector("[data-access-action=toggle]")) { const footer = card.querySelector(".card-footer"); const toggle = document.createElement("button"); toggle.className = "toggle " + (item.enabled !== false ? "on" : ""); toggle.dataset.accessAction = "toggle"; toggle.setAttribute("aria-label", item.enabled !== false ? "Disable Access List" : "Enable Access List"); toggle.innerHTML = "<span></span>"; footer?.querySelector(".card-actions")?.append(toggle); } }); }
function renderNewAccessGuidance() { const form = document.querySelector("#access-form"); if (!form || form.dataset.editing || form.querySelector(".access-create-guidance")) return; const assignmentSummary = document.querySelector("#access-assignment-summary"); if (assignmentSummary) { assignmentSummary.classList.add("hidden"); assignmentSummary.innerHTML = ""; } const guidance = document.createElement("p"); guidance.className = "access-create-guidance"; guidance.textContent = "After saving, edit this Access List to assign protected hosts. Allowed groups can be selected now or changed later."; document.querySelector("#access-credential-editor")?.after(guidance); const groupField = document.createElement("section"); groupField.id = "access-create-groups"; groupField.className = "access-create-groups"; groupField.innerHTML = `<strong>Allowed groups <span class="optional">Optional</span></strong><p class="access-group-help">Members of enabled groups can sign in with their Site Gateway credentials.</p>${state.groups?.length ? `<div class="access-group-options">${state.groups.filter(group => group.enabled !== false).map(group => `<label class="check-control access-group-option"><input type="checkbox" data-create-group="${extendedEscape(group.id)}"><span>${extendedEscape(group.name)} <small>${group.members?.length || 0} members</small></span></label>`).join("")}</div>` : '<p class="access-group-empty">No groups have been created yet. Create one under Administration → Groups.</p>'}`; guidance.after(groupField); }
document.querySelector("#access-list")?.addEventListener("click", () => setTimeout(renderNewAccessGuidance, 0));
document.addEventListener("click", event => { if (event.target.closest(".create-trigger") && state.view === "access") setTimeout(renderNewAccessGuidance, 0); });
function decorateAccessToggles() { document.querySelectorAll("#access-list [data-access-id]").forEach(card => { const item = state.accessLists.find(value => value.id === card.dataset.accessId); const footer = card.querySelector(".card-footer"); if (!footer || !item) return; card.querySelectorAll(".menu [data-access-action=toggle]").forEach(button => button.remove()); if (footer.querySelector("[data-access-action=toggle]")) return; let actions = footer.querySelector(".card-actions"); if (!actions) { actions = document.createElement("div"); actions.className = "card-actions"; footer.append(actions); } const toggle = document.createElement("button"); toggle.className = "toggle " + (item.enabled !== false ? "on" : ""); toggle.dataset.accessAction = "toggle"; toggle.setAttribute("aria-label", (item.enabled !== false ? "Disable" : "Enable") + " Access List"); toggle.innerHTML = "<span></span>"; actions.append(toggle); }); }
function decorateGroupCards() { document.querySelectorAll('[data-admin-panel="groups"] .group-card').forEach(card => { const group = state.groups.find(value => value.id === card.querySelector("[data-group-action]")?.dataset.groupId); if (!group) return; const icon = card.querySelector(".site-icon"); if (icon && icon.textContent.trim() === "GR") icon.innerHTML = featureIcon(group, "GR"); const menu = card.querySelector(".menu"); if (menu && !menu.querySelector("[data-group-action=icon]")) { const button = document.createElement("button"); button.dataset.groupAction = "icon"; button.dataset.groupId = group.id; button.textContent = "Change icon"; menu.prepend(button); } }); }
document.addEventListener("click", event => { const button = event.target.closest("[data-group-action=icon]"); if (!button) return; event.preventDefault(); event.stopImmediatePropagation(); openIconPicker("groups", button.dataset.groupId); }, true);
function normalizeAdminTabOrder() { const tabs = document.querySelector(".admin-tabs"); if (!tabs) return; const order = ["system","users","groups","defaults","audit","backups","retention","api","danger"]; order.forEach((name, index) => { const button = tabs.querySelector(`[data-admin-tab="${name}"]`); if (button) { if (name === "retention") button.textContent = "Logs & Retention"; tabs.append(button); } }); }
document.addEventListener("click", event => { if (event.target.closest(".admin-tabs")) setTimeout(normalizeAdminTabOrder, 0); });
// --- Backup encryption password field: placeholder/visibility polish -------------
const backupPasswordInput = document.querySelector('#backup-settings-form [name="backupPassword"]');
if (backupPasswordInput) {
backupPasswordInput.placeholder = "Optional — enter a password";
backupPasswordInput.closest(".backup-password-field")?.querySelector(".optional")?.remove();
}
function renderEncryptionToggle() {
const encryptionToggle = document.querySelector('#backup-settings-form .encryption-toggle');
if (!encryptionToggle) return;
const available = Boolean(state.config && state.config.backup && state.config.backup.encryptionAvailable);
const savedEncrypt = Boolean(state.settings && state.settings.backups && state.settings.backups.encrypt);
encryptionToggle.className = "encryption-toggle";
let message = "<code>BACKUP_PASSWORD</code> is configured \u2014 scheduled backups can be encrypted.";
if (!available && savedEncrypt) message = "This is enabled but <code>BACKUP_PASSWORD</code> is no longer configured \u2014 encrypted scheduled backups will fail until it\u2019s set again.";
else if (!available) message = "<code>BACKUP_PASSWORD</code> not configured \u2014 set it in the container\u2019s environment to enable encrypted scheduled backups.";
encryptionToggle.innerHTML = '<span class="field-label">Encrypt scheduled backups</span><span class="encryption-toggle-box"><input name="encrypt" type="checkbox"' + (available ? "" : " disabled") + (savedEncrypt ? " checked" : "") + '><span' + (!available ? ' class="warning-text"' : '') + '>' + message + '</span></span>';
}
renderEncryptionToggle();
setInterval(renderEncryptionToggle, 1000);
if (backupPasswordInput && !document.querySelector("#backup-password-toggle")) {
backupPasswordInput.insertAdjacentHTML("afterend", '<button type="button" id="backup-password-toggle" class="password-toggle" aria-label="Show backup encryption password" aria-pressed="false">Show</button>');
const toggle = document.querySelector("#backup-password-toggle");
toggle.addEventListener("click", () => { const visible = backupPasswordInput.type === "text"; backupPasswordInput.type = visible ? "password" : "text"; toggle.textContent = visible ? "Show" : "Hide"; toggle.setAttribute("aria-label", visible ? "Show backup encryption password" : "Hide backup encryption password"); toggle.setAttribute("aria-pressed", String(!visible)); });
}
// Manual "Create backup" button.
document.querySelector("#create-backup")?.addEventListener("click", async event => { event.preventDefault(); event.stopImmediatePropagation(); let dialog = document.querySelector("#create-backup-dialog"); if (!dialog) { dialog = document.createElement("dialog"); dialog.id = "create-backup-dialog"; document.body.append(dialog); } dialog.innerHTML = '<form method="dialog" class="dialog-card backup-create-dialog"><div class="dialog-heading"><div><p class="eyebrow">Backup & restore</p><h2>Create a backup</h2></div></div><p class="muted">Choose what to include. Site Gateway saves a copy in <code>/data/backups</code> and downloads a copy to your computer.</p><label>Backup type<select name="type"><option value="complete">Complete (Recommended) — configuration plus Hosted Site files</option><option value="configuration">Configuration only — settings and metadata</option></select></label><small class="backup-dialog-help">Complete backups include uploaded files, icons, certificates, and default-site assets. Configuration-only backups do not include uploaded Hosted Site files.</small><label>Encryption password <span class="optional">Optional</span><input name="password" type="password" placeholder="Optional — enter a password" autocomplete="new-password"></label><small class="backup-dialog-help">If provided, this password is required to restore the downloaded archive.</small><div class="dialog-actions"><button value="cancel" formnovalidate class="button secondary">Cancel</button><button value="confirm" class="button primary">Create backup</button></div></form>'; dialog.showModal(); const result = await new Promise(resolve => dialog.addEventListener("close", () => resolve(dialog.returnValue), {once:true})); if (result !== "confirm") return; const form = dialog.querySelector("form"), type = form.elements.type.value, password = form.elements.password.value; try { await api("/api/backups", {method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type,includeLogs:document.querySelector('#backup-settings-form [name="includeLogs"]')?.checked === true,password})}); state.backups = await api("/api/backups"); renderBackups(); toast("Backup created. Use Download in the list below to save it."); } catch (error) { toast(error.message); } }, true);
// --- Logs & Retention admin panel (Administration > Logs & Retention) ------------
function normalizeRetentionLayout() { const form = document.querySelector('[data-admin-panel="retention"] .retention-form'); if (!form || form.dataset.normalized === "true") return; const actions = form.querySelector(".dialog-actions"); const fields = [...form.children].filter(child => child !== actions); const section = document.createElement("div"); section.className = "form-section form-section-wide"; const eyebrow = document.createElement("p"); eyebrow.className = "eyebrow"; eyebrow.textContent = "Automatic Log Pruning"; section.append(eyebrow); const grid = document.createElement("div"); grid.className = "form-grid"; fields.forEach(field => grid.append(field)); section.append(grid); form.prepend(section); if (actions) form.append(actions); form.dataset.normalized = "true"; }
normalizeRetentionLayout();
function cleanRetentionLabels() { const form = document.querySelector('[data-admin-panel="retention"] .retention-form'); if (!form) return; const descriptions = { 'Access logs':'High-volume request records.', 'Gateway activity':'Operational and configuration events.', 'Audit logs':'Administrative accountability records.', 'Certificate events':'Certificate issuance and health changes.', 'Security events':'Authentication and security-related events.' }; [...form.querySelectorAll('label:not(.check-control)')].forEach(field => { const text = field.firstChild; const name = text?.textContent?.trim().replace(/ \(days\)$/, ''); if (!text || !descriptions[name]) return; if (!text.textContent.includes('(days)')) text.textContent = `${name} (days)`; let help = field.querySelector('small'); if (!help) { help = document.createElement('small'); field.append(help); } help.textContent = descriptions[name]; }); }
setTimeout(() => { cleanRetentionLabels(); normalizeRetentionLayout(); }, 0); setInterval(() => { cleanRetentionLabels(); normalizeRetentionLayout(); }, 300);
function renderRetentionRunStatus() { if (!state.user) return; const panel = document.querySelector('[data-admin-panel="retention"]'); const form = panel?.querySelector('.retention-form'); if (!panel || !form) return; const value = state.settings?.logsRetention?.lastRunAt ? state.settings.logsRetention : null; let status = panel.querySelector('.retention-run-status'); if (!status) { status = document.createElement('div'); status.className = 'retention-run-status muted'; const actions = form.querySelector('.dialog-actions'); if (actions) actions.before(status); else form.append(status); } status.textContent = value ? `Last run: ${value.lastRunMode || 'manual'} · ${new Date(value.lastRunAt).toLocaleString()} · Snapshot: ${value.lastRunSnapshot || 'available'}` : 'No pruning run yet.'; }
async function renderRetentionPreview() { if (!state.user) return; const panel = document.querySelector('[data-admin-panel="retention"]'); if (!panel) return; let preview = panel.querySelector('.retention-preview'); if (!preview) { preview = document.createElement('div'); preview.className = 'retention-preview muted'; const form = panel.querySelector('.retention-form'); const status = panel.querySelector('.retention-run-status'); (status || form)?.before(preview); } try { const data = await api('/api/logs/prune/preview'); const counts = data.counts || {}; const total = Object.values(counts).reduce((sum, value) => sum + Number(value || 0), 0); preview.textContent = data.enabled ? `Eligible to prune: ${total} records · Access ${counts.access || 0} · Activity ${counts.activity || 0} · Certificates ${counts.certificate || 0} · Security ${counts.security || 0} · Audit ${counts.audit || 0}` : 'Pruning is disabled. Enable automatic pruning to preview eligible records.'; } catch { preview.textContent = 'Prune preview unavailable.'; } }
async function renderRetentionHistory() { if (!state.user) return; const panel = document.querySelector('[data-admin-panel="retention"]'); if (!panel) return; let history = panel.querySelector('.retention-history'); if (!history) { history = document.createElement('div'); history.className = 'retention-history'; (panel.querySelector('.retention-run-status') || panel.querySelector('.retention-form'))?.after(history); } try { const rows = (await api('/api/audit?action=pruning')).filter(item => /pruning/i.test(item.action)).slice(0, 50); history.innerHTML = `<div class="retention-history-heading"><strong>Prune history</strong><span>${rows.length} runs</span></div>` + (rows.length ? `<div class="retention-history-list">${rows.map(item => `<div class="retention-history-row"><span class="status-dot ${item.status === 'error' ? 'disabled' : 'running'}"></span><span><strong>${extendedEscape(item.action)}</strong><small>${extendedEscape(item.actor || 'System')} · ${extendedEscape(item.status === 'error' ? 'Failed' : 'Success')} · ${extendedEscape(formatTime(item.created_at))}</small></span></div>`).join('')}</div>` : '<p class="muted">No pruning runs recorded yet.</p>'); } catch { history.innerHTML = '<p class="muted">Prune history unavailable.</p>'; } }
function ensureRetentionLoadMore() { const history = document.querySelector('.retention-history'); if (!history || history.querySelector('[data-retention-load-more]')) return; const button = document.createElement('button'); button.className = 'text-button retention-load-more'; button.dataset.retentionLoadMore = 'true'; button.textContent = 'Load more'; history.append(button); }
document.addEventListener('click', async event => { const button = event.target.closest('[data-retention-load-more]'); if (!button) return; try { const rows = (await api('/api/audit?action=pruning')).filter(item => /pruning/i.test(item.action)).slice(50); const list = button.parentElement.querySelector('.retention-history-list'); rows.forEach(item => { const row = document.createElement('div'); row.className = 'retention-history-row'; row.innerHTML = `<span class="status-dot ${item.status === 'error' ? 'disabled' : 'running'}"></span><span><strong>${extendedEscape(item.action)}</strong><small>${extendedEscape(item.actor || 'System')} · ${extendedEscape(item.status === 'error' ? 'Failed' : 'Success')} · ${extendedEscape(formatTime(item.created_at))}</small></span>`; list?.append(row); }); button.remove(); } catch { button.textContent = 'History unavailable'; } });
function normalizeRetentionActions() { const form = document.querySelector('[data-admin-panel="retention"] .retention-form'); const actions = form?.querySelector('.dialog-actions'); const section = form?.querySelector('.form-section'); if (form && actions && section && actions.previousElementSibling !== section) section.after(actions); }
async function expandRetentionHistory() { const history = document.querySelector('.retention-history'); const list = history?.querySelector('.retention-history-list'); if (!history || !list || history.dataset.expanded) return; history.dataset.expanded = 'true'; try { const rows = (await api('/api/audit?action=pruning')).filter(item => /pruning/i.test(item.action)).slice(50, 200); rows.forEach(item => { const row = document.createElement('div'); row.className = 'retention-history-row'; row.innerHTML = `<span class="status-dot ${item.status === 'error' ? 'disabled' : 'running'}"></span><span><strong>${extendedEscape(item.action)}</strong><small>${extendedEscape(item.actor || 'System')} · ${extendedEscape(item.status === 'error' ? 'Failed' : 'Success')} · ${extendedEscape(formatTime(item.created_at))}</small></span>`; list.append(row); }); } catch { /* Keep the initial 50 records if expansion is unavailable. */ } }
setInterval(ensureRetentionLoadMore, 500); setInterval(normalizeRetentionActions, 500); setInterval(expandRetentionHistory, 1000);
setInterval(renderRetentionRunStatus, 500); setInterval(renderRetentionPreview, 2000); setInterval(() => { if (document.querySelector('[data-admin-panel="retention"]:not(.hidden)') && !document.querySelector('.retention-history')) renderRetentionHistory(); }, 1000); setTimeout(renderRetentionPreview, 0); setTimeout(renderRetentionHistory, 0);
document.addEventListener("click", async event => { const button = event.target.closest('[data-retention-action="prune"]'); if (!button) return; try { const response = await api("/api/logs/prune", { method: "POST" }); const total = Object.values(response.counts || {}).reduce((sum, value) => sum + value, 0); toast(`Pruning completed. ${total} record${total === 1 ? "" : "s"} removed.`); } catch (error) { toast(error.message); } });
document.addEventListener("click", event => { const button = event.target.closest('[data-retention-action="download"]'); if (!button) return; window.location.href = "/api/logs/download"; });
document.addEventListener("click", async event => { const button = event.target.closest('[data-retention-action="prune"]'); if (!button) return; event.preventDefault(); event.stopImmediatePropagation(); try { const preview = await api("/api/logs/prune/preview"); const counts = preview.counts || {}; const total = Object.values(counts).reduce((sum, value) => sum + value, 0); let dialog = document.querySelector("#retention-prune-dialog"); if (!dialog) { dialog = document.createElement("dialog"); dialog.id = "retention-prune-dialog"; document.body.append(dialog); } dialog.innerHTML = `<form method="dialog" class="dialog-card compact"><div class="dialog-heading"><div><p class="eyebrow">Log Retention</p><h2>Confirm pruning</h2></div></div><p class="muted">This will remove records older than your saved retention periods.</p><p class="muted">Access: <strong>${counts.access || 0}</strong> · Activity: <strong>${counts.activity || 0}</strong> · Certificates: <strong>${counts.certificate || 0}</strong> · Security: <strong>${counts.security || 0}</strong> · Audit: <strong>${counts.audit || 0}</strong></p><div class="dialog-actions"><button value="cancel" class="button secondary">Cancel</button><button value="confirm" class="button primary">Confirm pruning</button></div></form>`; dialog.showModal(); const result = await new Promise(resolve => dialog.addEventListener("close", () => resolve(dialog.returnValue), { once: true })); if (result !== "confirm") return; const response = await api("/api/logs/prune", { method: "POST" }); toast(`Pruning completed. ${Object.values(response.counts || {}).reduce((sum, value) => sum + value, 0)} record${total === 1 ? "" : "s"} removed.`); } catch (error) { toast(error.message); } }, true);
// ============================================================================================
// v0.15.0 additions: API access tokens, backup history, and the Docker container picker.
// ============================================================================================
// Two overlapping rectangles, inline so it inherits currentColor from .icon-button.
const featureCopyIcon = '<svg class="copy-icon" viewBox="0 0 16 16" aria-hidden="true" focusable="false"><rect x="5.4" y="1.4" width="9.2" height="9.2" rx="1.8" fill="none" stroke="currentColor" stroke-width="1.4"></rect><rect x="1.4" y="5.4" width="9.2" height="9.2" rx="1.8" fill="none" stroke="currentColor" stroke-width="1.4"></rect></svg>';
function featureDialog(id) {
let dialog = document.querySelector(`#${id}`);
if (!dialog) { dialog = document.createElement("dialog"); dialog.id = id; document.body.append(dialog); }
return dialog;
}
// --- Administration > API Access ------------------------------------------------------------
// Follows the renderAuditPanel()/renderRetentionPanel() pattern: the tab and its panel are
// created once, then the table is re-rendered from /api/tokens on demand.
function apiTokenStatus(token) {
if (token.revoked) return { dot: "disabled", label: "Revoked" };
if (token.expiresAt && new Date(token.expiresAt).getTime() <= Date.now()) return { dot: "error", label: "Expired" };
return { dot: "running", label: "Active" };
}
async function loadApiTokens() {
const list = document.querySelector("#api-token-list"); if (!list) return;
try {
const tokens = await api("/api/tokens");
list.innerHTML = tokens.length ? tokens.map(token => {
const status = apiTokenStatus(token);
return `<article class="data-row api-token-row ${token.revoked ? "revoked" : ""}" data-token-id="${extendedEscape(token.id)}"><span class="status-dot ${status.dot}"></span><div><strong>${extendedEscape(token.name)}</strong><small>${extendedEscape(status.label)} · ${extendedEscape(token.ownerUsername || "unknown")}</small></div><div><span class="chip api-token-chip">${extendedEscape(token.prefix)}…</span><small>${token.scope === "read-only" ? "Read-only" : "Full access"}</small></div><div><strong>${extendedEscape(formatTime(token.createdAt))}</strong><small>${token.lastUsedAt ? `Last used ${extendedEscape(formatTime(token.lastUsedAt))}` : "Never used"}${token.expiresAt ? ` · expires ${extendedEscape(formatTime(token.expiresAt))}` : ""}</small></div><div class="row-actions">${token.revoked ? "" : '<button class="button secondary danger-text" data-token-action="revoke">Revoke</button>'}</div></article>`;
}).join("") : '<p class="quiet-state padded">No API tokens have been issued yet.</p>';
} catch (error) { list.innerHTML = `<p class="quiet-state padded">${extendedEscape(error.message)}</p>`; }
}
function renderApiTokensPanel() {
if (state.user?.role !== "administrator") return;
const tabs = document.querySelector(".admin-tabs"), users = document.querySelector('[data-admin-panel="users"]');
if (!tabs || !users) return;
let tab = tabs.querySelector('[data-admin-tab="api"]');
if (!tab) { tab = document.createElement("button"); tab.dataset.adminTab = "api"; tab.textContent = "API Access"; tabs.append(tab); }
let panel = document.querySelector('[data-admin-panel="api"]');
if (!panel) { panel = document.createElement("section"); panel.dataset.adminPanel = "api"; panel.className = "settings-panel hidden"; users.parentElement.append(panel); }
if (panel.dataset.ready) return;
panel.dataset.ready = "1";
panel.innerHTML = '<div class="panel-heading"><div><p class="eyebrow">Programmatic access</p><h2>API access tokens</h2><p class="muted">Issue bearer tokens for scripts and integrations. A token acts as the administrator who issued it, and is shown in full only once. Changing that administrators password, or disabling their account, revokes every token they issued.</p></div><div class="row-actions"><button id="create-api-token" class="button primary" type="button">Create token</button></div></div><div id="api-token-list" class="data-list"><p class="quiet-state padded">Open this tab to load API tokens.</p></div>';
tab.addEventListener("click", async () => {
document.querySelectorAll("[data-admin-tab]").forEach(item => item.classList.toggle("tab-active", item === tab));
document.querySelectorAll("[data-admin-panel]").forEach(item => item.classList.toggle("hidden", item !== panel));
await loadApiTokens();
});
}
// Shows a freshly issued token exactly once. No "x" close button -- Close only.
function showIssuedApiToken(result) {
const dialog = featureDialog("api-token-created-dialog");
dialog.innerHTML = `<form method="dialog" class="dialog-card"><div class="dialog-heading"><div><p class="eyebrow">API access</p><h2>Copy your token now</h2></div><button type="button" class="icon-button" id="copy-api-token" aria-label="Copy token" title="Copy token">${featureCopyIcon}</button></div><p class="muted">This is the only time Site Gateway will show this token. Store it somewhere safe — only its hash is kept.</p><code class="api-token-secret">${extendedEscape(result.token)}</code><div class="dialog-actions"><button value="cancel" class="button primary">Close</button></div></form>`;
dialog.querySelector("#copy-api-token").addEventListener("click", async () => {
try { await navigator.clipboard.writeText(result.token); toast("API token copied."); }
catch { toast("Your browser blocked clipboard access.", "error"); }
});
dialog.showModal();
}
document.addEventListener("click", async event => {
if (!event.target.closest("#create-api-token")) return;
const dialog = featureDialog("create-api-token-dialog");
dialog.innerHTML = '<form method="dialog" class="dialog-card"><div class="dialog-heading"><div><p class="eyebrow">API access</p><h2>Create an API token</h2></div></div><p class="muted">Re-enter your administrator credentials to confirm. The token inherits your role.</p><label>Token name<input name="name" maxlength="60" required placeholder="Home Assistant integration"></label><label>Scope<select name="scope"><option value="full">Full access — read and change configuration</option><option value="read-only">Read-only — GET requests only</option></select></label><label>Expires after <span class="optional">Optional</span><input name="expiresInDays" type="number" min="1" max="3650" placeholder="Leave empty for no expiry"><small>Number of days. Leave empty for a token that never expires.</small></label><label>Administrator username<input name="username" autocomplete="username" required></label><label>Administrator password<input name="password" type="password" autocomplete="current-password" required></label><p class="error" id="api-token-error"></p><div class="dialog-actions"><button value="cancel" formnovalidate class="button secondary">Cancel</button><button value="confirm" class="button primary">Create token</button></div></form>';
dialog.showModal();
const outcome = await new Promise(resolve => dialog.addEventListener("close", () => resolve(dialog.returnValue), { once: true }));
if (outcome !== "confirm") return;
const form = new FormData(dialog.querySelector("form"));
const expiresInDays = Number(form.get("expiresInDays"));
try {
const result = await api("/api/tokens", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: form.get("name"), scope: form.get("scope"), expiresInDays: Number.isFinite(expiresInDays) && expiresInDays > 0 ? expiresInDays : null, username: form.get("username"), password: form.get("password") }) });
await loadApiTokens();
showIssuedApiToken(result);
} catch (error) { toast(error.message, "error"); }
});
document.addEventListener("click", async event => {
const button = event.target.closest('[data-token-action="revoke"]'); if (!button) return;
const row = button.closest("[data-token-id]"); if (!row) return;
try { await api(`/api/tokens/${encodeURIComponent(row.dataset.tokenId)}`, { method: "DELETE" }); await loadApiTokens(); toast("API token revoked."); }
catch (error) { toast(error.message, "error"); }
});
// --- Administration > Backup & restore: history timeline --------------------------------------
// Deliberately never renders a raw .sgbackup filename: every entry is described by what it
// was and when it happened. Filenames stay in the data for the restore/download actions above.
function backupHistoryLabel(event) {
const kind = event.backupType === "complete" ? "Complete backup" : event.backupType === "configuration" ? "Configuration backup" : event.backupType === "safety" ? "Safety backup (pre-restore)" : "Backup";
const when = formatTime(event.createdAt);
const lower = `${kind.charAt(0).toLowerCase()}${kind.slice(1)}`;
if (event.type === "restored") return `Restored from ${lower}${when}`;
if (event.type === "deleted") return `Deleted ${lower}${when}`;
if (event.type === "imported") return `Imported ${lower}${when}`;
return `${kind}${when}`;
}
async function renderBackupHistory() {
const panel = document.querySelector('[data-admin-panel="backups"]'); if (!panel || state.user?.role !== "administrator") return;
let section = panel.querySelector(".backup-history-section");
if (!section) {
section = document.createElement("div");
section.className = "dashboard-panel backup-history-section";
section.innerHTML = '<div class="panel-heading"><div><p class="eyebrow">History</p><h2>Backup history</h2><p class="muted">Every backup, restore, import, and deletion — including failed attempts — recorded independently of what is currently stored on disk.</p></div></div><div id="backup-history-list" class="backup-history-list"><p class="quiet-state">Loading backup history…</p></div>';
panel.append(section);
}
const list = section.querySelector("#backup-history-list");
if (panel.classList.contains("hidden")) return;
try {
const events = await api("/api/backups/history");
list.innerHTML = events.length ? events.map(item => {
const failed = item.status === "failed";
const detail = failed ? `Failed — ${item.errorMessage || "no further detail recorded"}` : [item.sizeBytes ? formatBytes(item.sizeBytes) : "", item.safetyBackupFilename ? "A safety backup was taken first" : ""].filter(Boolean).join(" · ") || "Completed";
return `<div class="activity-tile"><span class="activity-mark ${failed ? "bad" : ""}">${failed ? "!" : "✓"}</span><span class="backup-history-copy"><strong>${extendedEscape(backupHistoryLabel(item))}</strong><small class="${failed ? "failed" : ""}" title="${extendedEscape(formatTime(item.createdAt))}">${extendedEscape(detail)}</small></span></div>`;
}).join("") : '<p class="quiet-state">No backup activity recorded yet.</p>';
} catch (error) { list.innerHTML = `<p class="quiet-state">${extendedEscape(error.message)}</p>`; }
}
// --- Docker container picker ------------------------------------------------------------------
// The Administration toggle is disabled whenever the socket is not mounted, regardless of the
// saved value, so the integration can never be switched on without its prerequisite.
function renderDockerPanel() {
if (state.user?.role !== "administrator") return;
const panel = document.querySelector('[data-admin-panel="system"] .system-integrations'); if (!panel) return;
const socketMounted = state.config?.docker?.socketMounted === true;
const enabled = socketMounted && (state.settings?.dockerIntegration?.enabled === true || state.config?.docker?.enabled === true);
let section = panel.querySelector(".docker-integration-section");
if (!section) {
section = document.createElement("div");
section.className = "docker-integration-section";
section.innerHTML = '<p class="docker-integration-heading">Docker container selection</p><p class="muted" id="docker-integration-help"></p><label class="check-control"><input id="docker-integration-toggle" type="checkbox"><span>Let Proxy and Streaming hosts pick a running container as their target</span></label>';
panel.append(section);
section.querySelector("#docker-integration-toggle").addEventListener("change", async event => {
const checkbox = event.currentTarget;
checkbox.disabled = true;
try { state.settings = await api("/api/settings", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ dockerIntegration: { enabled: checkbox.checked } }) }); toast(checkbox.checked ? "Container selection enabled." : "Container selection disabled."); }
catch (error) { checkbox.checked = !checkbox.checked; toast(error.message, "error"); }
finally { checkbox.disabled = false; renderDockerPanel(); decorateContainerPickers(); }
});
}
const toggle = section.querySelector("#docker-integration-toggle");
toggle.checked = enabled;
toggle.disabled = !socketMounted;
section.querySelector("#docker-integration-help").textContent = socketMounted
? "Site Gateway reads the Docker socket read-only to list running containers, and only offers containers that share a Docker network with it."
: "Docker socket not detected — mount /var/run/docker.sock into this container to enable container selection.";
section.querySelector(".check-control").classList.toggle("is-disabled", !socketMounted);
}
// Adds the "Pick from running containers" button beside every target field, and keeps its
// visibility in step with the integration's current state.
function decorateContainerPickers() {
const available = state.config?.docker?.socketMounted === true && (state.settings?.dockerIntegration?.enabled === true || state.config?.docker?.enabled === true);
for (const selector of ["#proxy-form [name=target]", "#settings-form [name=target]", "#stream-form [name=target]"]) {
const input = document.querySelector(selector); if (!input) continue;
let wrap = input.closest(".target-with-picker");
if (!wrap) {
wrap = document.createElement("span");
wrap.className = "target-with-picker";
input.replaceWith(wrap);
wrap.append(input);
const button = document.createElement("button");
button.type = "button";
button.className = "button secondary container-picker-trigger";
button.textContent = "Pick container";
wrap.append(button);
}
wrap.querySelector(".container-picker-trigger").classList.toggle("hidden", !available);
}
}
document.addEventListener("click", async event => {
const trigger = event.target.closest(".container-picker-trigger"); if (!trigger) return;
event.preventDefault();
const input = trigger.closest(".target-with-picker")?.querySelector("input"); if (!input) return;
const dialog = featureDialog("container-picker-dialog");
dialog.innerHTML = '<form method="dialog" class="dialog-card"><div class="dialog-heading"><div><p class="eyebrow">Docker</p><h2>Running containers</h2></div></div><p class="muted">Loading containers…</p><div class="dialog-actions"><button value="cancel" class="button secondary">Cancel</button></div></form>';
dialog.showModal();
let containers = [];
try { containers = (await api("/api/docker/containers")).containers || []; }
catch (error) {
dialog.innerHTML = `<form method="dialog" class="dialog-card"><div class="dialog-heading"><div><p class="eyebrow">Docker</p><h2>Containers unavailable</h2></div></div><p class="muted">${extendedEscape(error.message)}</p><div class="dialog-actions"><button value="cancel" class="button secondary">Close</button></div></form>`;
return;
}
const choices = containers.map(container => {
const ports = container.ports?.length ? container.ports.join(", ") : "no published container ports";
const detail = container.reachable ? `${container.image} · ports ${ports}` : `${container.image} · ${container.reason}`;
return `<button type="button" class="container-choice ${container.reachable ? "" : "unreachable"}" ${container.reachable ? `data-container-name="${extendedEscape(container.name)}" data-container-port="${container.ports?.[0] || ""}"` : "disabled"}><strong>${extendedEscape(container.name)}</strong><small>${extendedEscape(detail)}</small></button>`;
}).join("");
dialog.innerHTML = `<form method="dialog" class="dialog-card"><div class="dialog-heading"><div><p class="eyebrow">Docker</p><h2>Running containers</h2></div></div><p class="muted">Containers that do not share a Docker network with Site Gateway are dimmed — Site Gateway could not reach them by name. You can always type a target by hand instead.</p><div class="container-picker-list">${choices || '<p class="quiet-state">No running containers were reported.</p>'}</div><div class="dialog-actions"><button value="cancel" class="button secondary">Cancel</button></div></form>`;
dialog.querySelector(".container-picker-list")?.addEventListener("click", pickEvent => {
const choice = pickEvent.target.closest("[data-container-name]"); if (!choice) return;
const name = choice.dataset.containerName, port = choice.dataset.containerPort || "80";
// Docker's embedded DNS resolves the container name on a shared network, so use the
// name rather than an IP address, which changes whenever the container restarts.
input.value = input.type === "url" ? `http://${name}:${port}` : `${name}:${port}`;
input.dispatchEvent(new Event("input", { bubbles: true }));
dialog.close();
toast(`Target set to ${name}:${port}.`);
});
});
// --- System tab: environment/integration status, storage, scheduled jobs, sync, restart --------
function renderSystemPanel() {
if (state.user?.role !== "administrator") return;
const tabs = document.querySelector(".admin-tabs"), users = document.querySelector('[data-admin-panel="users"]');
if (!tabs || !users) return;
let tab = tabs.querySelector('[data-admin-tab="system"]');
if (!tab) { tab = document.createElement("button"); tab.dataset.adminTab = "system"; tab.textContent = "System"; tabs.insertBefore(tab, tabs.firstChild); }
let panel = document.querySelector('[data-admin-panel="system"]');
if (!panel) { panel = document.createElement("section"); panel.dataset.adminPanel = "system"; panel.className = "settings-panel hidden"; users.parentElement.insertBefore(panel, users); }
if (!panel.dataset.ready) {
panel.dataset.ready = "1";
panel.innerHTML = [
'<div class="panel-heading"><div><h2>System</h2><p class="muted">What\u2019s configured, what\u2019s running, and what this deployment can do. Nothing here is customizable except the Docker toggle below and the action buttons \u2014 everything else is status.</p></div></div>',
'<div class="dashboard-panel"><div class="panel-heading"><div><p class="eyebrow">Environment</p><h2>Integrations</h2></div></div><div id="system-env-status" class="health-grid"></div><div class="system-integrations"></div></div>',
'<div class="dashboard-panel"><div class="panel-heading"><div><p class="eyebrow">Environment</p><h2>Security status</h2></div></div><div id="system-security" class="health-grid"></div></div>',
'<div class="dashboard-panel"><div class="panel-heading"><div><p class="eyebrow">Gateway</p><h2>Sync</h2></div><button type="button" id="system-resync" class="button secondary">Resync now</button></div><p id="system-sync-status" class="muted"></p></div>',
'<div class="dashboard-panel"><div class="panel-heading"><div><p class="eyebrow">Operations</p><h2>Scheduled jobs</h2></div></div><div id="system-jobs" class="dashboard-jobs-list"></div></div>',
'<div class="dashboard-panel"><div class="panel-heading"><div><p class="eyebrow">Storage</p><h2>Disk usage</h2></div></div><div id="system-storage" class="health-grid"></div></div>',
'<div class="dashboard-panel"><div class="panel-heading"><div><p class="eyebrow">Build</p><h2>Version</h2></div></div><div id="system-version" class="muted"></div></div>',
'<div class="dashboard-panel"><div class="panel-heading"><div><p class="eyebrow">Gateway</p><h2>Reload & restart</h2></div></div><p class="muted">Reloading re-applies the current configuration to Caddy with no downtime. Restarting stops and restarts the whole application \u2014 only available when a restart policy is set on the container.</p><div class="row-actions"><button type="button" id="system-reload" class="button secondary">Reload gateway config</button><button type="button" id="system-restart" class="button secondary danger-text" disabled>Restart application</button></div><p id="system-restart-status" class="muted"></p></div>',
].join("");
panel.querySelector("#system-resync").addEventListener("click", async event => {
const button = event.currentTarget; button.disabled = true; const original = button.textContent; button.textContent = "Resyncing\u2026";
try { await api("/api/gateway/resync", { method: "POST" }); toast("Gateway configuration re-synced."); await refresh(); }
catch (error) { toast(error.message, "error"); }
finally { button.disabled = false; button.textContent = original; }
});
panel.querySelector("#system-reload").addEventListener("click", async event => {
const button = event.currentTarget; button.disabled = true; const original = button.textContent; button.textContent = "Reloading\u2026";
try { await api("/api/system/reload", { method: "POST" }); toast("Gateway configuration reloaded."); await refresh(); }
catch (error) { toast(error.message, "error"); }
finally { button.disabled = false; button.textContent = original; }
});
panel.querySelector("#system-restart").addEventListener("click", async event => {
if (!await themedConfirm("Restart Site Gateway?", "The application will stop and restart. This takes a few seconds and briefly interrupts hosted sites and the dashboard.", "Restart")) return;
const button = event.currentTarget; button.disabled = true; button.textContent = "Restarting\u2026";
try { await api("/api/system/restart", { method: "POST" }); toast("Restarting \u2014 this dashboard will be unavailable briefly."); }
catch (error) { toast(error.message, "error"); button.disabled = false; button.textContent = "Restart application"; }
});
}
renderSystemStatus(panel);
}
async function renderSystemStatus(panel) {
panel = panel || document.querySelector('[data-admin-panel="system"]');
if (!panel) return;
const security = document.querySelector("#system-security"), storage = document.querySelector("#system-storage"),
version = document.querySelector("#system-version"), jobs = document.querySelector("#system-jobs"),
syncStatus = document.querySelector("#system-sync-status"), restartButton = document.querySelector("#system-restart"),
restartStatus = document.querySelector("#system-restart-status");
if (jobs) jobs.innerHTML = (state.dashboard?.jobs || []).map(job => `<div class="dashboard-list-item"><span class="status-dot ${job.enabled ? "running" : "idle"}"></span><span><strong>${extendedEscape(job.name)}</strong><small>${job.enabled ? `Active \u00b7 ${extendedEscape(job.schedule)}` : "Disabled"}</small></span></div>`).join("") || '<p class="quiet-state">No scheduled jobs reported.</p>';
const envStatus = document.querySelector("#system-env-status");
if (envStatus) {
const encryptionAvailable = Boolean(state.config?.backup?.encryptionAvailable);
envStatus.innerHTML = `<div class="health-tile"><span class="status-dot ${encryptionAvailable ? "running" : "idle"}"></span><span class="health-tile-copy"><strong>BACKUP_PASSWORD</strong><small>${encryptionAvailable ? "Configured \u2014 scheduled backups can be encrypted." : "Not set \u2014 configure it in the container\u2019s environment to enable encrypted scheduled backups."}</small></span></div>`;
}
if (syncStatus) { const drift = (state.dashboard?.attention || []).some(item => item.kind === "drift"); syncStatus.textContent = drift ? "Configuration drift detected \u2014 the running gateway no longer matches the last known-good configuration." : `Gateway configuration is in sync. Last reload: ${state.dashboard?.gateway?.lastReload ? formatTime(state.dashboard.gateway.lastReload) : "unknown"}.`; syncStatus.className = drift ? "muted status-warning" : "muted"; }
if (version) version.innerHTML = `Site Gateway v${extendedEscape(state.config?.version || "unknown")}<br>Access this dashboard at: <code>${extendedEscape(location.origin)}</code><br>Data directory: <code>${extendedEscape(state.config?.storage?.databasePath ? state.config.storage.databasePath.replace(/\/database\/.*/, "") : "/data")}</code> &middot; Site ports: <code>${extendedEscape(String(state.config?.minPort ?? ""))}\u2013${extendedEscape(String(state.config?.maxPort ?? ""))}</code>`;
try {
const [sec, store, policy] = await Promise.all([
api("/api/system/security"),
api("/api/system/storage"),
api("/api/system/restart-policy"),
]);
if (security) security.innerHTML = [
{ ok: !sec.adminPasswordIsDefault, label: "ADMIN_PASSWORD", detail: sec.adminPasswordIsDefault ? "Still using the built-in default \u2014 set this before exposing the dashboard." : "Configured." },
{ ok: !sec.sessionSecretIsDefault, label: "SESSION_SECRET", detail: sec.sessionSecretIsDefault ? "Not set \u2014 sessions are keyed off the admin credentials instead of an independent secret." : "Configured." },
{ ok: sec.acmeEmailConfigured, label: "ACME_EMAIL", detail: sec.acmeEmailConfigured ? "Configured." : "Not set \u2014 certificate issuance will proceed without a registration contact." },
].map(row => `<div class="health-tile"><span class="status-dot ${row.ok ? "running" : "idle"}"></span><span class="health-tile-copy"><strong>${row.label}</strong><small>${row.detail}</small></span></div>`).join("");
if (storage) {
const rows = Object.entries(store.breakdown || {}).map(([key, bytes]) => `<div class="health-tile"><span class="status-dot running"></span><span class="health-tile-copy"><strong>${key[0].toUpperCase()}${key.slice(1)}</strong><small>${formatBytes(bytes)}</small></span></div>`).join("");
const capacity = store.capacity ? `<div class="health-tile"><span class="status-dot ${store.capacity.availableBytes / store.capacity.totalBytes > 0.1 ? "running" : "idle"}"></span><span class="health-tile-copy"><strong>Disk</strong><small>${formatBytes(store.capacity.availableBytes)} free of ${formatBytes(store.capacity.totalBytes)}</small></span></div>` : "";
storage.innerHTML = rows + capacity || '<p class="quiet-state">Storage usage unavailable.</p>';
}
if (restartButton) { restartButton.disabled = !policy.restartAvailable; if (restartStatus) restartStatus.textContent = policy.reason || (policy.policyName ? `Restart policy: ${policy.policyName}.` : ""); }
} catch { /* Status widgets keep their last-known values if a refresh call fails. */ }
}
// --- Wire the new panels into the shared refresh entry point ----------------------------------
const baseRenderExtendedViews = window.renderExtendedViews;
window.renderExtendedViews = function () {
baseRenderExtendedViews();
renderApiTokensPanel();
renderSystemPanel();
renderDockerPanel();
decorateContainerPickers();
renderBackupHistory();
normalizeAdminTabOrder();
hideRestrictedControls();
};