You've already forked caddy-opnsense-blocker
Cache IP intelligence and add allowed filter
This commit is contained in:
@@ -398,6 +398,7 @@ const overviewHTML = `<!doctype html>
|
||||
<h2>Recent IPs</h2>
|
||||
<div class="toolbar-right">
|
||||
<label class="toggle"><input id="show-bots-toggle" type="checkbox" checked onchange="toggleKnownBots()">Show known bots</label>
|
||||
<label class="toggle"><input id="show-allowed-toggle" type="checkbox" checked onchange="toggleAllowed()">Show allowed</label>
|
||||
<div class="meta">Last 24 hours · click a column to sort</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -421,6 +422,7 @@ const overviewHTML = `<!doctype html>
|
||||
const recentHours = 24;
|
||||
const storageKeys = {
|
||||
showKnownBots: 'caddy-opnsense-blocker.overview.showKnownBots',
|
||||
showAllowed: 'caddy-opnsense-blocker.overview.showAllowed',
|
||||
sortKey: 'caddy-opnsense-blocker.overview.sortKey',
|
||||
sortDirection: 'caddy-opnsense-blocker.overview.sortDirection',
|
||||
};
|
||||
@@ -436,6 +438,7 @@ const overviewHTML = `<!doctype html>
|
||||
let currentItems = [];
|
||||
let currentSort = loadSortPreference();
|
||||
let showKnownBots = loadShowKnownBotsPreference();
|
||||
let showAllowed = loadShowAllowedPreference();
|
||||
|
||||
function renderStats(data) {
|
||||
const stats = [
|
||||
@@ -477,6 +480,25 @@ const overviewHTML = `<!doctype html>
|
||||
}
|
||||
}
|
||||
|
||||
function loadShowAllowedPreference() {
|
||||
try {
|
||||
const rawValue = window.localStorage.getItem(storageKeys.showAllowed);
|
||||
if (rawValue === null) {
|
||||
return true;
|
||||
}
|
||||
return rawValue !== 'false';
|
||||
} catch (_) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function saveShowAllowedPreference(value) {
|
||||
try {
|
||||
window.localStorage.setItem(storageKeys.showAllowed, value ? 'true' : 'false');
|
||||
} catch (_) {
|
||||
}
|
||||
}
|
||||
|
||||
function loadSortPreference() {
|
||||
const fallback = { key: 'events', direction: 'desc' };
|
||||
try {
|
||||
@@ -563,9 +585,13 @@ const overviewHTML = `<!doctype html>
|
||||
}
|
||||
|
||||
function updateSortButtons() {
|
||||
const toggle = document.getElementById('show-bots-toggle');
|
||||
if (toggle) {
|
||||
toggle.checked = showKnownBots;
|
||||
const botsToggle = document.getElementById('show-bots-toggle');
|
||||
if (botsToggle) {
|
||||
botsToggle.checked = showKnownBots;
|
||||
}
|
||||
const allowedToggle = document.getElementById('show-allowed-toggle');
|
||||
if (allowedToggle) {
|
||||
allowedToggle.checked = showAllowed;
|
||||
}
|
||||
document.querySelectorAll('button[data-sort]').forEach(button => {
|
||||
const key = button.dataset.sort;
|
||||
@@ -619,7 +645,7 @@ const overviewHTML = `<!doctype html>
|
||||
}
|
||||
|
||||
function renderIPs(items) {
|
||||
const filteredItems = items.filter(item => showKnownBots || !item.bot);
|
||||
const filteredItems = items.filter(item => (showKnownBots || !item.bot) && (showAllowed || item.state !== 'allowed'));
|
||||
const rows = sortItems(filteredItems).map(item => [
|
||||
'<tr>',
|
||||
' <td class="mono"><div class="ip-cell">' + renderBotChip(item.bot) + '<a href="/ips/' + encodeURIComponent(item.ip) + '">' + escapeHtml(item.ip) + '</a></div></td>',
|
||||
@@ -631,7 +657,14 @@ const overviewHTML = `<!doctype html>
|
||||
' <td>' + renderActions(item) + '</td>',
|
||||
'</tr>'
|
||||
].join(''));
|
||||
const emptyMessage = showKnownBots ? 'No IPs seen in the last 24 hours.' : 'No non-bot IPs seen in the last 24 hours.';
|
||||
let emptyMessage = 'No IPs seen in the last 24 hours.';
|
||||
if (!showKnownBots && !showAllowed) {
|
||||
emptyMessage = 'No non-bot, non-allowed IPs seen in the last 24 hours.';
|
||||
} else if (!showKnownBots) {
|
||||
emptyMessage = 'No non-bot IPs seen in the last 24 hours.';
|
||||
} else if (!showAllowed) {
|
||||
emptyMessage = 'No non-allowed IPs seen in the last 24 hours.';
|
||||
}
|
||||
document.getElementById('ips-body').innerHTML = rows.length > 0 ? rows.join('') : '<tr><td colspan="7" class="muted">' + escapeHtml(emptyMessage) + '</td></tr>';
|
||||
}
|
||||
|
||||
@@ -658,6 +691,13 @@ const overviewHTML = `<!doctype html>
|
||||
render();
|
||||
}
|
||||
|
||||
function toggleAllowed() {
|
||||
const toggle = document.getElementById('show-allowed-toggle');
|
||||
showAllowed = !toggle || toggle.checked;
|
||||
saveShowAllowedPreference(showAllowed);
|
||||
render();
|
||||
}
|
||||
|
||||
async function sendAction(ip, action, promptLabel) {
|
||||
const reason = window.prompt(promptLabel, '');
|
||||
if (reason === null) {
|
||||
@@ -994,7 +1034,7 @@ const ipDetailsHTML = `<!doctype html>
|
||||
renderAll(data);
|
||||
}
|
||||
|
||||
refresh().then(() => investigate());
|
||||
refresh();
|
||||
</script>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
@@ -80,6 +80,9 @@ func TestHandlerServesOverviewAndManualActions(t *testing.T) {
|
||||
if !strings.Contains(recorder.Body.String(), "Show known bots") {
|
||||
t.Fatalf("overview page should expose the known bots toggle")
|
||||
}
|
||||
if !strings.Contains(recorder.Body.String(), "Show allowed") {
|
||||
t.Fatalf("overview page should expose the allowed toggle")
|
||||
}
|
||||
if !strings.Contains(recorder.Body.String(), "localStorage") {
|
||||
t.Fatalf("overview page should persist preferences in localStorage")
|
||||
}
|
||||
@@ -97,6 +100,9 @@ func TestHandlerServesOverviewAndManualActions(t *testing.T) {
|
||||
if strings.Contains(body, `const ip = "\"203.0.113.10\"";`) {
|
||||
t.Fatalf("ip details page still renders a doubly quoted IP")
|
||||
}
|
||||
if strings.Contains(body, `refresh().then(() => investigate());`) {
|
||||
t.Fatalf("ip details page should not auto-refresh investigation on load")
|
||||
}
|
||||
}
|
||||
|
||||
type stubApp struct {
|
||||
|
||||
Reference in New Issue
Block a user