This commit is contained in:
Mateusz Gruszczyński committed 2026-10-04 23:13:27 +02:00
1 parent e6604e41fc
commit 1dea7f55c8
49 files changed
+4499 -4025

No files matched your search

+32 -1
View File
@@ -1,4 +1,4 @@
let configHistoryEntries = [];
let configHistoryEntries = [], configHistorySelectedRevision = null;
function historyDate(value, options = {}) {
try { return new Intl.DateTimeFormat(locale(), options).format(new Date(Number(value) * 1000)); }
catch { return new Date(Number(value) * 1000).toLocaleString(); }
@@ -13,6 +13,12 @@ function historyValue(value) {
const text = JSON.stringify(value, null, 2);
return text.length > 6000 ? `${text.slice(0, 6000)}\n...` : text;
}
function syncConfigHistoryRestoreButton() {
const button = $("config-history-restore"), revision = Number(configHistorySelectedRevision);
if (!button) return;
button.hidden = configHistorySelectedRevision === null;
button.disabled = busy || !envelope || !Number.isSafeInteger(revision) || revision >= Number(envelope.revision);
}
function configDiff(before, after, path = "$", output = [], depth = 0) {
if (output.length >= 200) return output;
if (Object.is(before, after)) return output;
@@ -29,8 +35,10 @@ function configDiff(before, after, path = "$", output = [], depth = 0) {
function renderConfigRevisionDetail(detail) {
const entry = detail?.revision;
if (!entry) return;
configHistorySelectedRevision = Number(entry.revision);
$("config-history-detail-title").textContent = `${t("configHistoryRevision")} ${entry.revision}`;
$("config-history-detail-meta").textContent = `${historyDate(entry.time, { dateStyle: "medium", timeStyle: "short" })} · ${entry.actor}`;
syncConfigHistoryRestoreButton();
document.querySelectorAll(".config-history-revision").forEach(button => button.classList.toggle("active", Number(button.dataset.revision) === Number(entry.revision)));
const diff = configDiff(entry.previous_config, entry.config);
const box = $("config-history-diff"); box.replaceChildren();
@@ -95,7 +103,29 @@ function renderConfigHistory() {
}
if (!months.length) calendar.append(el("p", t("configHistoryEmpty"), "empty"));
}
async function restoreConfigRevision() {
const revision = Number(configHistorySelectedRevision);
if (!envelope || busy || !Number.isSafeInteger(revision) || revision >= Number(envelope.revision)) return;
const expectedRevision = Number(envelope.revision);
const message = t("configHistoryRestoreConfirm").replace("{revision}", revision).replace("{current}", expectedRevision);
if (!(await appConfirm(message, { danger: true, confirmLabel: t("configHistoryRestoreAction") }))) return;
const button = $("config-history-restore"), epoch = authEpoch;
busy = true; syncConfigHistoryRestoreButton();
try {
const value = await api("/api/config/history/restore", { method: "POST", body: JSON.stringify({ revision, expected_revision: expectedRevision }) });
if (!authenticated || epoch !== authEpoch) return;
envelope = value;
await refreshCertificateInventory();
if (!authenticated || epoch !== authEpoch) return;
renderConfig();
toast(t("configHistoryRestored").replace("{revision}", revision).replace("{new_revision}", value.revision));
await refresh(true);
if (authenticated && epoch === authEpoch) await loadConfigHistory();
} catch (error) { toast(error.message, true); if (error.status === 401) lock(); }
finally { busy = false; if (button?.isConnected) syncConfigHistoryRestoreButton(); }
}
async function loadConfigHistory() {
configHistorySelectedRevision = null; syncConfigHistoryRestoreButton();
$("config-history-summary").textContent = t("configHistoryLoading");
try {
const result = await api("/api/config/history?limit=512"); configHistoryEntries = result.revisions || []; renderConfigHistory();
@@ -105,3 +135,4 @@ async function loadConfigHistory() {
$("config-history-open").addEventListener("click", () => { const dialog = $("config-history-dialog"); if (!dialog.open) dialog.showModal(); void loadConfigHistory(); });
$("config-history-close").addEventListener("click", () => $("config-history-dialog").close());
$("config-history-reload").addEventListener("click", () => void loadConfigHistory());
$("config-history-restore").addEventListener("click", () => void restoreConfigRevision());
+1 -1
View File
@@ -6,7 +6,7 @@ function renderSettings() {
if (!settingsDirty.has("response-form")) {
const server = config.server_header || {}, compression = config.compression || {}, diagnostics = config.diagnostic_headers || {};
$("expose-request-id").checked = !!diagnostics.request_id;
$("server-mode").value = server.mode || "preserve"; $("server-value").value = server.value || "RustProxy/v0.25.3";
$("server-mode").value = server.mode || "preserve"; $("server-value").value = server.value || "RustProxy/v0.25.4";
for (const name of ["gzip", "br", "zstd", "deflate"]) $(`compress-${name}`).checked = !!compression[name];
$("compress-min").value = compression.min_bytes ?? 1024; syncServerMode();
}