Implements a master toggle for security features across config, CLI, and application logic. This allows granular control over whether the advanced security middleware and protections are active globally.
107 lines
4.3 KiB
JavaScript
107 lines
4.3 KiB
JavaScript
(() => {
|
|
const menuController = window.WarpBoxUI?.bindMenuBar?.() || { close() {} };
|
|
const dataNode = document.getElementById("activity-data");
|
|
const body = document.getElementById("activity-body");
|
|
const searchInput = document.getElementById("activity-search");
|
|
const severityFilter = document.getElementById("activity-severity");
|
|
const kindFilter = document.getElementById("activity-kind");
|
|
const statusLeft = document.getElementById("activity-status-left");
|
|
const toast = document.getElementById("toast");
|
|
|
|
if (!dataNode || !body || !searchInput) return;
|
|
const events = parseData();
|
|
const initialQuery = new URLSearchParams(window.location.search).get("q");
|
|
if (initialQuery) searchInput.value = initialQuery;
|
|
|
|
function parseData() {
|
|
try {
|
|
return JSON.parse(dataNode.textContent || "[]");
|
|
} catch (_) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
function showToast(message, type = "info", duration = 1800) {
|
|
window.WarpBoxUI?.toast?.(message, type, { target: toast, duration });
|
|
}
|
|
|
|
function renderKindFilter() {
|
|
const kinds = new Set(events.map((event) => event.kind || "unknown"));
|
|
Array.from(kinds).sort().forEach((kind) => {
|
|
const option = document.createElement("option");
|
|
option.value = kind;
|
|
option.textContent = kind;
|
|
kindFilter.appendChild(option);
|
|
});
|
|
}
|
|
|
|
function createdLabel(value) {
|
|
const parsed = new Date(value);
|
|
if (Number.isNaN(parsed.getTime())) return "-";
|
|
return parsed.toISOString().replace("T", " ").slice(0, 16) + " UTC";
|
|
}
|
|
|
|
function filtered() {
|
|
const query = searchInput.value.trim().toLowerCase();
|
|
const severity = severityFilter.value;
|
|
const kind = kindFilter.value;
|
|
return events.filter((event) => {
|
|
const haystack = [event.kind, event.message, event.ip, event.path, event.method].join(" ").toLowerCase();
|
|
const matchesQuery = !query || haystack.includes(query);
|
|
const matchesSeverity = severity === "all" || event.severity === severity;
|
|
const matchesKind = kind === "all" || event.kind === kind;
|
|
return matchesQuery && matchesSeverity && matchesKind;
|
|
});
|
|
}
|
|
|
|
function render() {
|
|
const rows = filtered();
|
|
body.innerHTML = "";
|
|
rows.forEach((event) => {
|
|
const row = document.createElement("tr");
|
|
row.innerHTML = `
|
|
<td>${createdLabel(event.created_at)}</td>
|
|
<td>${escapeHtml(event.kind || "-")}</td>
|
|
<td>${escapeHtml(event.severity || "-")}</td>
|
|
<td>${escapeHtml(event.ip || "-")}</td>
|
|
<td>${escapeHtml(event.method || "-")}</td>
|
|
<td title="${escapeHtml(event.path || "-")}">${escapeHtml(event.path || "-")}</td>
|
|
<td title="${escapeHtml(event.message || "-")}">${escapeHtml(event.message || "-")}</td>
|
|
`;
|
|
body.appendChild(row);
|
|
});
|
|
statusLeft.textContent = `${rows.length} activity event(s) visible`;
|
|
}
|
|
|
|
function escapeHtml(value) {
|
|
return window.WarpBoxUI?.htmlEscape?.(value) || String(value ?? "");
|
|
}
|
|
|
|
[searchInput, severityFilter, kindFilter].forEach((element) => {
|
|
element.addEventListener(element.tagName === "INPUT" ? "input" : "change", render);
|
|
});
|
|
|
|
document.querySelectorAll("[data-command]").forEach((button) => {
|
|
button.addEventListener("click", () => {
|
|
menuController.close();
|
|
if (button.dataset.command === "refresh") {
|
|
window.location.reload();
|
|
return;
|
|
}
|
|
if (button.dataset.command === "export") {
|
|
const blob = new Blob([JSON.stringify(filtered(), null, 2)], { type: "application/json;charset=utf-8" });
|
|
const url = URL.createObjectURL(blob);
|
|
const anchor = document.createElement("a");
|
|
anchor.href = url;
|
|
anchor.download = `warpbox-activity-${new Date().toISOString().replaceAll(":", "-")}.json`;
|
|
anchor.click();
|
|
URL.revokeObjectURL(url);
|
|
showToast("Visible activity exported");
|
|
}
|
|
});
|
|
});
|
|
|
|
renderKindFilter();
|
|
render();
|
|
})();
|