Files
intrusion-detection/app/templates/blocklist.html
T

135 lines
3.3 KiB
HTML

{% extends "base.html" %} {% block title %}Blocklist — Intrusion Detection{%
endblock %} {% block content %}
<h1>Blocklist</h1>
<p class="muted">
Current consolidated blocklist (from the latest scan). Adding/removing touches
the MikroTik router.
</p>
<div class="panel">
<div class="panel-head"><h2>Add / remove entry</h2></div>
<div class="panel-actions" style="margin-top: 0">
<input
id="ip"
placeholder="IP or CIDR, e.g. 1.2.3.4 or 1.2.0.0/16"
style="min-width: 260px"
/>
<button class="btn primary" id="add-btn">Add to Blocked</button>
<button class="btn danger" id="remove-btn">Remove from Blocked</button>
</div>
</div>
<div class="panel">
<div class="panel-head">
<h2>IPv4 <span id="v4-count"></span></h2>
</div>
<table class="table">
<thead>
<tr>
<th>Address</th>
<th></th>
</tr>
</thead>
<tbody id="v4"></tbody>
</table>
</div>
<div class="panel">
<div class="panel-head">
<h2>IPv6 <span id="v6-count"></span></h2>
</div>
<table class="table">
<thead>
<tr>
<th>Address</th>
<th></th>
</tr>
</thead>
<tbody id="v6"></tbody>
</table>
</div>
{% endblock %} {% block scripts %}
<script>
async function loadBlocklist() {
try {
const data = await api("/api/blocklist");
render("v4", data.ipv4 || [], "v4-count");
render("v6", data.ipv6 || [], "v6-count");
} catch (e) {
toast(e.message, "error");
}
}
function render(tbodyId, entries, countId) {
const body = document.getElementById(tbodyId);
body.innerHTML = "";
document.getElementById(countId).textContent = `(${entries.length})`;
if (!entries.length) {
body.innerHTML =
'<tr><td colspan="2" class="muted">No entries.</td></tr>';
return;
}
for (const ip of entries) {
body.append(
el(
"tr",
el("td", { class: "mono", text: ip }),
el(
"td",
{ style: "text-align:right" },
el("button", {
class: "btn danger",
text: "Remove",
onclick: () => remove(ip),
}),
),
),
);
}
}
async function act(action) {
const ip = document.getElementById("ip").value.trim();
if (!ip) {
toast("Enter an IP or CIDR", "warn");
return;
}
try {
const data = await api(`/api/blocklist/${action}`, {
method: "POST",
body: { ip },
});
toast(
`Removed ${ip}`.replace(
"Removed",
action === "add" ? "Added" : "Removed",
),
"ok",
);
document.getElementById("ip").value = "";
loadBlocklist();
} catch (e) {
toast(e.message, "error");
}
}
async function remove(ip) {
try {
await api("/api/blocklist/remove", { method: "POST", body: { ip } });
toast(`Removed ${ip}`, "ok");
loadBlocklist();
} catch (e) {
toast(e.message, "error");
}
}
document
.getElementById("add-btn")
.addEventListener("click", () => act("add"));
document
.getElementById("remove-btn")
.addEventListener("click", () => act("remove"));
loadBlocklist();
</script>
{% endblock %}