This commit is contained in:
Mateusz Gruszczyński committed 2026-10-07 13:40:21 +02:00
1 parent 3a2eb4fe79
commit e0194fbaff
63 files changed
+1553 -379

No files matched your search

+16 -3
View File
@@ -192,8 +192,21 @@ function enhanceEnabledControl(input, hintKey = "entityEnableHint") {
}
window.rustProxyEnableControl = enhanceEnabledControl;
function action(label, fn) { const b = el("button", label, "quiet"); b.type = "button"; b.addEventListener("click", fn); return b; }
function renderAboutRuntime(status = latestStatus) {
const value = status?.runtime?.certificate_runtime || {};
const availability = flag => flag === true ? t("runtimeAvailable") : flag === false ? t("runtimeUnavailable") : t("unavailable");
const mode = value.status === "unavailable" ? t("certificateRuntimeUnavailable") : value.status === "ready" && value.mode === "managed" ? t("certificateRuntimeManaged") : value.status === "ready" && value.mode === "system" ? t("certificateRuntimeSystem") : t("certificateRuntimePreparing");
const modeNode = $("about-acme-mode"), runtimeNode = $("about-python-runtime"), details = $("about-python-details");
if (modeNode) modeNode.textContent = mode;
if (runtimeNode) runtimeNode.textContent = `${t("runtimePython")}: ${availability(value.python)} · ${t("runtimePip")}: ${availability(value.pip)} · ${t("runtimeCertbot")}: ${availability(value.certbot)}`;
if (details) {
const parts = [value.message ? t(value.message) : ""];
if (value.managed_directory) parts.push(`${t("certificateRuntimePath")}: ${value.managed_directory}`);
details.textContent = parts.filter(Boolean).join(" · ");
}
}
function renderStatus(s) {
const firstStatus = latestStatus === null; latestStatus = s; window.rustProxySettings?.render(); if (firstStatus) renderSettings();
const firstStatus = latestStatus === null; latestStatus = s; renderAboutRuntime(s); window.rustProxySettings?.render(); if (firstStatus) renderSettings();
connected = true; $("connection-label").textContent = t("connected"); $("signal").classList.remove("status-error"); const m = s.metrics;
$("metric-ws").textContent = m.websocket_active || 0;
$("metric-ws-h1").textContent = m.websocket_h1_active || 0;
@@ -334,7 +347,7 @@ function lock(notify = true) {
if (navigating) { document.documentElement.classList.add("app-loading"); location.replace(destination); }
}
async function activate(info) { pendingAuthDestination = null; authMessage(""); $("api-docs").hidden = false; $("logs-menu").hidden = false; $("logs-open").hidden = false; $("file-logs-open").hidden = false; authEpoch++; sessionInfo = info; csrf = info.csrf_token; authenticated = true; const preferences = await loadAdminPreferences(); window.rustProxyLogs?.applyPreferences(preferences); window.rustProxyFileLogs?.applyPreferences(preferences); window.rustProxyVhosts?.applyPreferences(preferences); await loadConfig(); $("password").value = ""; $("password-confirm").value = ""; $("setup-token").value = ""; $("login").hidden = true; $("workspace").hidden = false; $("logout").hidden = false; renderSession(); await refresh(true); startLive(); document.documentElement.classList.remove("app-loading"); }
async function activate(info) { pendingAuthDestination = null; authMessage(""); $("api-docs").hidden = false; $("logs-menu").hidden = false; $("logs-open").hidden = false; $("file-logs-open").hidden = false; authEpoch++; sessionInfo = info; csrf = info.csrf_token; authenticated = true; const preferences = await loadAdminPreferences(); window.rustProxyLogs?.applyPreferences(preferences); window.rustProxyFileLogs?.applyPreferences(preferences); window.rustProxyVhosts?.applyPreferences(preferences); window.rustProxyDocker?.applyPreferences(preferences); window.rustProxyRedirects?.applyPreferences(preferences); window.rustProxyNotFound?.applyPreferences(preferences); window.rustProxyStreams?.applyPreferences(preferences); await loadConfig(); $("password").value = ""; $("password-confirm").value = ""; $("setup-token").value = ""; $("login").hidden = true; $("workspace").hidden = false; $("logout").hidden = false; renderSession(); await refresh(true); startLive(); document.documentElement.classList.remove("app-loading"); }
async function loadAudit() { if (!authenticated) return; const epoch = authEpoch; try { const data = await api("/api/audit"); if (!authenticated || epoch !== authEpoch) return; const rows = data.entries.map(item => { const tr = el("tr"); for (const value of [formatDateTime(item.time * 1000), item.actor, item.action, item.detail]) { const td = el("td", value); td.title = value; tr.append(td); } return tr; }); $("audit-rows").replaceChildren(...rows); $("empty-audit").hidden = rows.length > 0; } catch (e) { toast(e.message, true); } }
let tunnelRefreshTimer = null;
function tunnelMessage(value = "", error = false) { const node = $("tunnels-status"); if (!node) return; node.textContent = value; node.classList.toggle("error", !!error); }
@@ -371,7 +384,7 @@ function stopTunnelRefresh() { if (tunnelRefreshTimer) clearInterval(tunnelRefre
function startTunnelRefresh() { stopTunnelRefresh(); tunnelRefreshTimer = setInterval(() => { if ($("tunnels-dialog")?.open) void loadTunnels(); }, 2000); }
$("login-form").addEventListener("submit", async event => { event.preventDefault(); const form = event.currentTarget; authMessage(""); try { await withFormSubmitState(form, event.submitter, async () => { const username = $("username").value.trim(); const password = $("password").value; if (setupRequired) { if (password !== $("password-confirm").value) throw fieldError("password-confirm", t("passwordMismatch")); await api("/api/auth/setup", { method: "POST", body: JSON.stringify({ token: $("setup-token").value.trim(), username, password }) }); setupRequired = false; syncAuthForm(); } const info = await api("/api/auth/login", { method: "POST", body: JSON.stringify({ username, password }) }); await activate(info); clearTimeout(toastTimer); hideToast(); }); } catch (e) { if (e.code === "auth.already_initialized") { setupRequired = false; syncAuthForm(); } $("password").value = ""; $("password-confirm").value = ""; authMessage(e.message); } });
$("logout").addEventListener("click", async () => { try { await api("/api/auth/logout", { method: "POST" }); lock(); toast(t("locked")); } catch (e) { if (e.status === 401) lock(); toast(e.message, true); } });
$("about-open").addEventListener("click", () => { const dialog = $("about-dialog"); if (!dialog.open) dialog.showModal(); });
$("about-open").addEventListener("click", () => { renderAboutRuntime(); const dialog = $("about-dialog"); if (!dialog.open) dialog.showModal(); });
$("about-close").addEventListener("click", () => $("about-dialog").close());
const mobileMenuToggle = $("mobile-menu-toggle"), dashboardSidebar = document.querySelector(".sidebar");
function setMobileMenu(open) {
+4
View File
@@ -136,6 +136,10 @@ function applyAdminPreferences(value, cache = true) {
};
adminPreferences = normalized;
window.rustProxyVhosts?.applyPreferences(normalized);
window.rustProxyDocker?.applyPreferences(normalized);
window.rustProxyRedirects?.applyPreferences(normalized);
window.rustProxyNotFound?.applyPreferences(normalized);
window.rustProxyStreams?.applyPreferences(normalized);
if (languagePacks.size) translate();
refreshAppearanceUi(); return normalized;
}