Full firewall management — UFW rules + Fail2Ban + IP lists

- New firewall.php endpoint: status, enable/disable, add-rule (full UFW
  syntax: action/direction/port/proto/from/to/comment), delete-rule by
  number, quick allow-port/deny-port, allow-ip/block-ip with DB storage,
  ip-lists, reset to defaults, default-policy, set-logging, f2b-status
  (all jails with banned counts), f2b-jail detail, f2b-ban, f2b-unban
  (single jail or all), f2b-reload, f2b-restart, raw ufw command (whitelisted)
- admin.js: full firewall page — UFW status badge + enable/disable toggle,
  default policy dropdowns, numbered rules table with delete, quick rule
  inline form, full add-rule modal, trusted IP chip list, blocked IP chip
  list, Fail2Ban jails table with banned counts, per-jail banned IP modal
  with individual unban buttons, manual ban modal, logging level control
- nova.js: add Nova.escHtml() used across all new pages
- admin.js: remove git_remote field from admin settings panel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 16:03:35 +00:00
parent 3af01ab614
commit 910427c46c
3 changed files with 753 additions and 51 deletions
+5 -1
View File
@@ -116,10 +116,14 @@ window.Nova = (() => {
return `<span class="service-dot ${cls}"></span>`;
}
function escHtml(str) {
return String(str ?? '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}
// Inject global CSS animation
const style = document.createElement('style');
style.textContent = '@keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}';
document.head.appendChild(style);
return { api, toast, modal, confirm, initNav, loadPage, progressBar, bytes, relTime, badge, serviceDot };
return { api, toast, modal, confirm, initNav, loadPage, progressBar, bytes, relTime, badge, serviceDot, escHtml };
})();