125 lines
4.2 KiB
HTML
125 lines
4.2 KiB
HTML
{% extends "base.html" %} {% block title %}Reports — Intrusion Detection{% endblock %} {% block content %}
|
|
<h1>Reports</h1>
|
|
<p class="muted">Browse the timestamped reports written by each scanner.</p>
|
|
|
|
<div class="panel">
|
|
<div class="panel-actions" style="margin-top: 0">
|
|
<label style="flex-direction: row; align-items: center; gap: 0.5rem"
|
|
>Source
|
|
<select id="source">
|
|
<option value="copyparty">copyparty</option>
|
|
<option value="npm">npm</option>
|
|
<option value="app">app</option>
|
|
<option value="mikrotik">mikrotik</option>
|
|
</select>
|
|
</label>
|
|
<button class="btn" id="refresh-btn">Refresh</button>
|
|
</div>
|
|
<div class="list" id="files"></div>
|
|
</div>
|
|
|
|
<div class="panel">
|
|
<div class="panel-head"><h2 id="content-title">Report content</h2></div>
|
|
<pre class="content" id="content">Select a report on the left to view it.</pre>
|
|
</div>
|
|
{% endblock %} {% block scripts %}
|
|
<script>
|
|
let nextCursor = null;
|
|
|
|
function addReportLink(list, label, onClick) {
|
|
const link = document.createElement("a");
|
|
link.href = "#";
|
|
link.textContent = label;
|
|
link.addEventListener("click", (event) => {
|
|
event.preventDefault();
|
|
onClick();
|
|
});
|
|
list.append(link);
|
|
}
|
|
|
|
async function loadFiles(append = false) {
|
|
const source = document.getElementById("source").value;
|
|
const list = document.getElementById("files");
|
|
if (!append) {
|
|
nextCursor = null;
|
|
list.innerHTML = '<div class="muted">Loading…</div>';
|
|
} else {
|
|
document.getElementById("load-more")?.remove();
|
|
}
|
|
|
|
let importedPaths = new Set();
|
|
try {
|
|
const query = new URLSearchParams({ source, limit: "50" });
|
|
if (append && nextCursor) query.set("cursor", nextCursor);
|
|
const data = await api(`/api/reports?${query}`);
|
|
if (!append) list.innerHTML = "";
|
|
for (const artifact of data.items || []) {
|
|
importedPaths.add(artifact.original_path);
|
|
addReportLink(list, `${artifact.generated_at} | ${artifact.report_type} | ${artifact.original_path}`, () =>
|
|
openArtifact(artifact.id),
|
|
);
|
|
}
|
|
nextCursor = data.next_cursor;
|
|
} catch (e) {
|
|
if (append) {
|
|
list.append(el("div", { className: "muted", text: e.message }));
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!append) {
|
|
try {
|
|
const data = await api(`/api/reports/${source}`);
|
|
for (const name of data.files || []) {
|
|
if (importedPaths.has(`${source}/${name}`)) continue;
|
|
addReportLink(list, `${name} | legacy file`, () => openReport(name));
|
|
}
|
|
} catch (e) {
|
|
if (!list.childElementCount) list.append(el("div", { className: "muted", text: e.message }));
|
|
}
|
|
}
|
|
|
|
if (nextCursor) {
|
|
const button = document.createElement("button");
|
|
button.id = "load-more";
|
|
button.className = "btn";
|
|
button.textContent = "Load more";
|
|
button.addEventListener("click", () => loadFiles(true));
|
|
list.append(button);
|
|
}
|
|
if (!list.childElementCount) list.innerHTML = '<div class="muted">No reports in this source.</div>';
|
|
}
|
|
|
|
async function openArtifact(id) {
|
|
document.getElementById("content-title").textContent = "Database report";
|
|
const pre = document.getElementById("content");
|
|
pre.textContent = "Loading…";
|
|
try {
|
|
const data = await api(`/api/report-artifacts/${id}`);
|
|
document.getElementById("content-title").textContent = data.original_path;
|
|
const payload = data.payload || {};
|
|
pre.textContent = payload.format === "text" ? payload.content || "" : JSON.stringify(payload, null, 2);
|
|
} catch (e) {
|
|
pre.textContent = `Error: ${e.message}`;
|
|
}
|
|
}
|
|
|
|
async function openReport(name) {
|
|
const source = document.getElementById("source").value;
|
|
document.getElementById("content-title").textContent = name;
|
|
const pre = document.getElementById("content");
|
|
pre.textContent = "Loading…";
|
|
try {
|
|
const data = await api(`/api/reports/${source}/${name}`);
|
|
pre.textContent = data.content;
|
|
} catch (e) {
|
|
pre.textContent = `Error: ${e.message}`;
|
|
}
|
|
}
|
|
|
|
document.getElementById("refresh-btn").addEventListener("click", () => loadFiles());
|
|
document.getElementById("source").addEventListener("change", () => loadFiles());
|
|
loadFiles();
|
|
</script>
|
|
{% endblock %}
|