Files
gandalf/templates/base.html
Jared Vititoe 0278dad502 feat: inspector page, link debug enhancements, security hardening
- Add /inspector page: visual model-accurate switch chassis diagrams
  (USF5P, USL8A, US24PRO, USPPDUP, USMINI), clickable port blocks
  with color coding (green=up, amber=PoE, cyan=uplink, grey=down),
  detail panel with stats/PoE/LLDP, LLDP-based path debug side-by-side

- Link Debug: port number badges (#N), LLDP neighbor line, PoE class/max,
  collapsible host/switch panels with sessionStorage persistence

- monitor.py: collect LLDP neighbor map + PoE class/max/mode per switch
  port; PulseClient uses requests.Session() for HTTP keep-alive; add
  shlex.quote() around interface names (defense-in-depth)

- Security: suppress buttons use data-* attrs + delegated click handler
  instead of inline onclick with Jinja2 variable interpolation; remove
  | safe filter from user-controlled fields in suppressions.html;
  setDuration() takes explicit el param instead of implicit event global

- db.py: thread-local connection reuse with ping(reconnect=True) to
  avoid a new TCP handshake per query

- .gitignore: add config.json (contains credentials), __pycache__

- README: full rewrite covering architecture, all 4 pages, alert logic,
  config reference, deployment, troubleshooting, security notes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 15:39:48 -05:00

48 lines
1.5 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}GANDALF{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<header class="header">
<div class="header-left">
<div class="header-brand">
<span class="header-title">GANDALF</span>
<span class="header-sub">Network Monitor // LotusGuild</span>
</div>
<nav class="header-nav">
<a href="{{ url_for('index') }}"
class="nav-link {% if request.endpoint == 'index' %}active{% endif %}">
Dashboard
</a>
<a href="{{ url_for('links_page') }}"
class="nav-link {% if request.endpoint == 'links_page' %}active{% endif %}">
Link Debug
</a>
<a href="{{ url_for('inspector') }}"
class="nav-link {% if request.endpoint == 'inspector' %}active{% endif %}">
Inspector
</a>
<a href="{{ url_for('suppressions_page') }}"
class="nav-link {% if request.endpoint == 'suppressions_page' %}active{% endif %}">
Suppressions
</a>
</nav>
</div>
<div class="header-right">
<span class="header-user">{{ user.name or user.username }}</span>
</div>
</header>
<main class="main">
{% block content %}{% endblock %}
</main>
<script src="{{ url_for('static', filename='app.js') }}"></script>
{% block scripts %}{% endblock %}
</body>
</html>