Commit Graph
10 Commits
Author SHA1 Message Date
alientim 1a0b55ed44 DHCP: manuelle Reservierungen, Options-Schutz+Dropdown-UI, Lease-Countdown-Fix
1. Manuelle Reservierungen (dhcp_manual_reservations) fuer Geraete, die
   nicht als Client in dieser App gepflegt werden -- bewusst eine eigene,
   explizite Aktion (MAC/IP/Name), damit kein externes Geraet unueberwacht
   automatisch eine feste IP bekommt. _dhcp_reservation_candidates fuehrt
   automatische (aus devices) und manuelle Reservierungen jetzt zusammen,
   case-insensitiv nach MAC dedupliziert (automatisch gewinnt bei Konflikt).
   Automatische Reservierungen sind in der Tabelle nicht loeschbar
   (Schloss-Symbol statt Button, sie entstehen/verschwinden mit den
   Client-Stammdaten), manuelle schon. Live verifiziert: Hinzufuegen,
   doppelte MAC ablehnen, ungueltige MAC ablehnen, generierte Kea-Config
   mit gemischten Auto-/manuellen Reservierungen besteht kea-dhcp4 -t.

2. Standard-DHCP-Optionen um 10 weitere verifizierte Optionen erweitert
   (u.a. host-name/12 -- Kea-Name mit Bindestrich, NICHT "hostname", live
   gegen echtes Kea geprueft) -- jetzt 57 insgesamt. Standard-Optionen sind
   nicht mehr loeschbar (Backend lehnt es ab, UI zeigt ein Schloss-Symbol
   statt Loeschen-Button) -- vorher liess sich eine vorbefuellte Options-
   Definition versehentlich entfernen.

3. Options-Tabellen (global UND pro Reservierung) zeigen jetzt nur noch
   tatsaechlich genutzte Options -- eigene immer, Standard-Optionen nur mit
   gesetztem Wert. Weitere Standard-Optionen kommen ueber ein Dropdown
   "+ Option hinzufuegen" dazu statt permanent alle 57 als leere Felder zu
   zeigen. Das neu eingeblendete Feld wird automatisch in den sichtbaren
   Bereich gescrollt und fokussiert (bei bis zu 57 moeglichen Optionen kann
   das Feld sonst weit unterhalb des sichtbaren Modal-Ausschnitts liegen
   und es wirkt so, als waere nichts passiert).

4. Lease-Countdown-Fix: die Ablaufzeit wird jetzt explizit als UTC
   ausgewiesen (Kea arbeitet intern in UTC-Epoch) und zusaetzlich als live
   tickender Countdown angezeigt (gleiches Prinzip wie der bestehende
   "Naechste Pruefung"-Timer). Vorher wirkte eine reine Absolutzeit auf der
   nicht selbst aktualisierenden Seite bei den kurzen Standard-Lease-Zeiten
   (600s) schnell "schon abgelaufen", sobald etwas Zeit vergangen war, bis
   man tatsaechlich hinschaut -- live im echten Betrieb genau als dieses
   Missverstaendnis beobachtet und anhand der rohen Kea-CSV verifiziert,
   dass die richtige Spalte (expire) korrekt gelesen wird.

5. UI-Feinschliff: "In Datei schreiben" bei den Reservierungen heisst jetzt
   "Speichern" und ist der primaere (orange) Button, "Reservierung
   hinzufuegen" sekundaer -- das Hinzufuegen legt nur einen Datensatz an,
   erst "Speichern" schreibt die tatsaechlich wirksame Kea-Config.

Alles live auf der Test-VM deployt und verifiziert (Playwright fuer die
Dropdown-Sichtbarkeit/Fokus-Interaktion, curl fuer die Backend-Validierung,
kea-dhcp4 -t fuer die generierte Konfiguration), keine Fehler im
journalctl-Log.
2026-08-11 15:52:52 +02:00
alientim 182457629d Fix: 'Jetzt pruefen' aktualisierte Topbar-Countdown nur auf dem Dashboard
Der Klick loeste den Neustart von rpi-check.service und damit einen
echten, sofortigen Pruef-Durchlauf immer korrekt aus -- nur die
Topbar-Anzeige 'Naechste Pruefung in Xs' wurde ausserhalb des Dashboards
nie aktualisiert, da nur index.html einen Listener fuer das
poe:check-triggered-Event registrierte. Auf allen anderen Seiten (DHCP,
Switches, Settings, ...) lief der Countdown deshalb sichtbar mit dem alten
Zeitpunkt weiter, obwohl im Hintergrund laengst neu geprueft wurde.

Fix (klein gehalten, kein neuer Endpunkt): run_check_now() wartet kurz auf
den ersten Log-Eintrag des frisch gestarteten Dienstes und liefert den
neuen Zeitpunkt direkt in seiner bestehenden JSON-Antwort mit. app.js
schreibt diesen Wert danach unabhaengig von der aktuellen Seite ins
global-timer-pill-Element -- der laufende Countdown liest seine Werte
ohnehin bei jedem Tick frisch aus dem DOM.

Live auf der Test-VM verifiziert (mehrere echte Durchlaeufe ueber
/check/run-now, frischer last_run_epoch_ms in der Antwort, keine Fehler
im journalctl-Log).
2026-08-11 14:51:07 +02:00
alientimandClaude Sonnet 5 4d7433e832 Fix: SSH-Terminal-Login (No auth methods), kaputtes DOM in Bearbeiten-Modals
Quelltext-Huerde wieder entfernt (auf Wunsch) - siehe vorherigen Commit,
hier nur der Revert von initSourceProtection() und der README-Erwaehnung.

SSH-Terminal-Login war komplett kaputt (von dir gemeldet + Screenshot):
- Root Cause: das Init-Payload vom Browser enthielt nie ein Passwort,
  SSHClient.connect() bekam also weder Passwort noch Key noch Agent und
  scheiterte sofort mit "No authentication methods available" - noch
  bevor ueberhaupt eine interaktive Passwortabfrage moeglich gewesen
  waere (die High-Level-API erledigt Host-Key-Pruefung UND
  Authentifizierung in einem blockierenden Aufruf).
- Fix: Umstieg auf die Low-Level paramiko.Transport-API. Nach
  Host-Key-Bestaetigung wird aktiv erfragt, welche Auth-Methoden der
  Server anbietet (auth_none), und bei Bedarf interaktiv ueber das
  Browser-Terminal nach Passwort/keyboard-interactive-Prompts gefragt
  -- genau das Verhalten, das der bestehende Hinweistext im Modal schon
  immer versprach, aber nie tatsaechlich implementiert war.
  Host-Key-Verifikation dabei manuell nachgebaut (_verify_host_key_interactive)
  inkl. hartem Ablehnen bei GEAENDERTEM (nicht nur unbekanntem) Host-Key,
  wie ein echtes ssh-CLI bei einer moeglichen MITM-Situation.
- Waehrend der Live-Verifikation gegen ein echtes Geraet zwei weitere
  Bugs gefunden und gefixt: ws.receive() wirft in diesem Setup
  ConnectionClosed statt None zurueckzugeben (crashte
  _terminal_read_line unbehandelt -> "Invalid frame header" beim
  Client); _send_and_close() crashte ebenso, wenn der Client bereits weg
  war. Beide jetzt defensiv abgefangen.
- Live gegen ein echtes Zielgeraet verifiziert (Host-Key-Bestaetigung,
  Passwort-Prompt, erfolgreicher Login) sowie manuell von dir bestaetigt.

Kaputtes DOM in zwei Bearbeiten-Modals (von dir gemeldet: "Verbindung
testen" oeffnete beim Switch bearbeiten kein Fenster, obwohl es beim
Neuanlegen funktionierte):
- Root Cause: <div class="modal-overlay">...</div> stand direkt in
  <tbody> (nur <tr> ist dort gueltig). Browser "foster-parenten"
  ungueltigen Tbody-Inhalt aus der Tabelle heraus und zerreissen dabei
  teils die Eltern-Kind-Beziehung zwischen <form> und seinen Buttons --
  this.closest("form") lieferte dadurch null statt des Formulars.
  Betroffen: editSwitchModal (switches.html), deviceOptionsModal
  (settings_dhcp.html). Fix: beide Modal-Bloecke aus der Tabelle heraus
  in eine eigene Schleife direkt danach verschoben (gleiches Muster wie
  die bereits korrekten Neuanlegen-Modals).
- Per DOM-Inspektion verifiziert: this.closest("form") lieferte vorher
  null, danach das korrekte Formular fuer alle Zeilen; End-to-End-Test
  bestaetigt, dass sich das Terminal-Modal jetzt oeffnet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 12:00:22 +02:00
alientimandClaude Sonnet 5 6803929140 Hostname-Einstellung, DHCP-Range-Pflicht, Topbar-Ampel, Text-Straffung, Quelltext-Huerde
Hostname (Systemeinstellungen, neben Pruefintervall):
- hostnamectl set-hostname ueber die App, Validierung (RFC-1123-artiges
  Label), kein Revert-Timer noetig (kappt die Erreichbarkeit nicht wie
  eine IP-Aenderung). Live getestet inkl. Validierung und Revert.

DHCP: Range ist jetzt Pflicht, kein geratener Default mehr:
- dhcp_range_start/end/dns starten leer (Platzhaltertext statt fake-
  echt aussehendem Default) - ein Zufalls-Range haette den Dienst sonst
  unbemerkt mit einer zum echten Netz nicht passenden Konfiguration
  starten lassen koennen.
- write_dhcp_file und dhcp_service_action=enable_restart verweigern sich
  ohne eingetragene Range; _render_kea_config laesst "pools" ohne Range
  komplett weg statt einen kaputten Pool-String zu erzeugen.
- Neues, separates dhcp_gateway-Feld (optional) fuer einen vom
  automatisch erkannten Gateway abweichenden Router fuer die Clients.

Topbar-Ampel fuer den Kea-Dienst:
- Gruener/roter Punkt neben dem Pruefintervall-Timer, nur sichtbar mit
  settings_dhcp.view (ein einzelner, kurzer systemctl-Aufruf pro Request,
  nicht die volle Status-Erkennung). Live verifiziert (rot wenn gestoppt,
  gruen wenn gestartet).

Reservierungstabelle zeigt jetzt pro Client, welche eigene DHCP-Option
greift (global oder Client-Override, mit Wert im Tooltip).

Text-Straffung: die laengsten Hint-Texte und Code-Kommentare in
Templates/app.py gekuerzt (u.a. groups.html, settings_dhcp.html,
account.html, devices/switches/users/credentials.html, zwei grosse
Migrations-/DHCP-Kommentarbloecke in app.py) - Kernaussagen erhalten,
Redundanz entfernt.

Quelltext-Huerde (KEINE echte Sicherheit, nur Abschreckung): Rechtsklick
und DevTools-/Quelltext-Shortcuts per JS blockiert. Klar dokumentiert
in Kommentar + README, dass der Browser HTML/CSS/JS immer vollstaendig
ausliefert und das in Sekunden umgehbar ist - echte Absicherung bleiben
ausschliesslich die serverseitigen Rechteprüfungen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 11:28:29 +02:00
alientimandClaude Sonnet 5 7d7239e1af Fix: Benutzer-Löschen im Browser kaputt (JS), Gruppen-Rechtetabelle überarbeitet
Bugfix (von dir gemeldet, live auf Port 5000 gefunden):
- initConfirmables() in app.js rief beim bestätigten Absenden
  form.requestSubmit() OHNE den ursprünglichen Submitter auf. Laut Spec
  wird dann KEIN Submit-Button-Name/Value mitgeschickt. users.html trug
  die Benutzer-ID als name/value des Löschen-Buttons selbst (statt eines
  verstecken Inputs wie überall sonst) — dadurch kam "delete_user" nie
  im Request an, der Klick tat scheinbar nichts. Fix: e.submitter beim
  ersten Klick merken und an requestSubmit(submitter) weiterreichen
  (behebt es grundsätzlich für alle Formulare dieser Art); zusätzlich
  users.html auf das robustere hidden-input-Muster umgestellt wie
  credentials/devices/groups. Mit echtem Playwright-Browserklick
  (nicht nur curl) verifiziert.

Gruppen-Rechtetabelle, mehrere Korrekturrunden nach deinem Mockup:
- Bereichsname + Kill-Switch-Kästchen jetzt eng nebeneinander in der
  Tabellen-Kopfzeile (nicht mehr an den Rand gestellt), R/W/E/D-Spalten
  in derselben Zeile statt einer zweiten.
- Nur die von einem Bereich tatsächlich genutzten Spalten werden gezeigt
  (GROUP_ROW_TYPES) — Logs zeigt nur R, Einstellungen nur R/W/E, nur
  Geräte zeigt zusätzlich D.
- Bugfix: D-Spalte bei Geräte verschwand durch zu schmale Flex-Breite der
  Spalte im Overflow, obwohl serverseitig korrekt gerendert — behoben
  durch flex:0 0 auto statt fester Breite.
- Checkbox-Zentrierung robust per display:block+margin:auto statt sich
  auf native Checkbox-Ränder zu verlassen (waren leicht asymmetrisch).
- Unterpunkte deutlich weiter eingerückt (34px) für klare Hierarchie.
- Sichtbares Ausgrauen (nicht nur natives disabled) der Unterpunkte,
  solange der Bereich-Kill-Switch aus ist (JS setzt .permission-locked).
- Legende jetzt UNTER der Rechtetabelle statt darüber.
- Rechte lassen sich jetzt direkt beim Anlegen einer neuen Gruppe setzen
  (Modal zeigt dieselbe Rechtetabelle, add_group-Route verarbeitet
  mitgesendete permissions[] im selben Request) statt sie erst danach
  über die Gruppentabelle nachzupflegen.

Alles inkl. Erstellen-mit-Rechten und Bearbeiten-Regression live per
Playwright verifiziert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 09:52:01 +02:00
alientimandClaude Sonnet 5 c4f682b5de UI-Fixes (Button-Wrap, Suchfeld-Icon, Log-Farben, Nav-Persistenz), manueller Check-Trigger, echter Live-Refresh
- section-head: Button ("+ Neue Zugangsdaten" etc.) rutscht bei langer
  Beschreibung nicht mehr in die nächste Zeile — bleibt immer rechts oben,
  der Beschreibungstext wickelt stattdessen innerhalb seiner eigenen Spalte.
- Suchfeld-Icon überlappte den Platzhaltertext: eine spätere, generische
  Input-Regel mit gleicher Spezifität hat die padding-left-Regel des
  Lupe-Icons überschrieben (reine Reihenfolge-im-Stylesheet-Sache) — Selektor
  spezifischer gemacht.
- Live-Log: Neustart-bezogene Zeilen (manueller Neustart, automatischer
  PoE-Restart bei Ausfall) werden jetzt orange markiert statt farblos.
- Aufgeklappte Nav-Gruppen bleiben über Seitenwechsel hinweg erhalten
  (localStorage), zusätzlich zur automatischen Aufklappung der Gruppe der
  aktuell aktiven Seite.
- Datei-Auswahl (Import) im Dark Mode gestylt (Text + Button), inkl.
  color-scheme-bewusster Browser-Widgets.
- Manueller "Jetzt prüfen"-Trigger (Icon neben dem globalen Timer, nur
  Admins): startet rpi-check.service neu -> frisches Logfile + sofortiger
  Durchlauf, Countdown synchronisiert sich auf den manuellen Zeitpunkt.
- Dashboard und Live-Log aktualisieren sich jetzt per AJAX im Hintergrund
  (kein voller Seiten-Reload mehr): neue Route /dashboard/tiles liefert das
  Kachel-Fragment (_dashboard_tiles.html, von index.html eingebunden und vom
  Live-Update nachgeladen), get_log() liefert den aktuellen Dateinamen als
  Header mit, damit die Anzeige nach einem Service-Neustart aktuell bleibt.
- Root-Cause für "Intervall bleibt immer bei 300s": in der WSL-Testumgebung
  lief poe_wrapper.py nur als manuell gestarteter Hintergrundprozess statt
  als echter rpi-check.service — "systemctl restart" lief dadurch ins Leere.
  Echten systemd-Service in WSL eingerichtet und Intervalländerung end-to-end
  verifiziert (Log-Zeilenabstand folgt jetzt dem neu gesetzten Intervall).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:53:15 +02:00
alientimandClaude Sonnet 5 0fcb6c94cb Topbar auf globalen Prüf-Timer reduziert, Aktionen+Beschreibung über Tabellen, sortierbare Listen
- Topbar zeigt rechts jetzt ausschließlich den "Nächste Prüfung"-Countdown,
  konsistent auf jeder Seite (auch anonymes Dashboard) statt nur auf dem
  Dashboard. Neuer Context-Processor inject_check_timer()/get_last_run_at()
  liefert last_run/interval global, ohne dass jede Route das selbst
  berechnen muss.
- "+ Neu ..."-Buttons (Devices, Switches, Zugangsdaten, Benutzer, Gruppen)
  aus der Topbar entfernt und stattdessen in einen .section-head direkt
  über der jeweiligen Tabelle verschoben, zusammen mit einer kurzen
  Beschreibung der Seite (bisher nur bei Zugangsdaten/Gruppen vorhanden,
  jetzt auch bei Geräte/Switche/Benutzer).
- Live-Log: eigene lokale Timer-Pill entfernt (redundant zum globalen
  Timer), "Aktualisieren"-Button in denselben section-head verschoben.
  Dashboard: Suchfeld aus der Topbar in den Seiteninhalt verschoben, lokale
  Timer-Anzeige entfernt (übernimmt die globale Topbar-Pill), Reload-bei-
  Intervallende-Logik bleibt als separater, unsichtbarer Scheduler erhalten.
- Neue generische Tabellen-Sortierung (app.js: initSortableTables): Klick
  auf eine Spaltenüberschrift mit data-sort-key sortiert die Zeilen anhand
  von data-sort-<key>-Attributen. Unterstützt auch Akkordeon-Tabellen mit
  mehreren <tbody> (Gruppen: Haupt- + Detail-Zeile bleiben als Einheit
  zusammen, die virtuelle "Admin"-Zeile bleibt über data-sort-pinned immer
  oben). Angewendet auf Geräte, Switche, Zugangsdaten, Benutzer, Gruppen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:21:30 +02:00
alientimandClaude Sonnet 5 a7a23b7c12 Audit-Log, Import/Export, eigenes Profil & anpassbare Navigation
- Änderungslog: audit_log-Tabelle + last_modified_by/at an Devices und
  Switches; log_action()/touch_record() in allen Verwaltungsrouten
  (Devices, Switches, Zugangsdaten, Benutzer, Gruppen, Settings) verdrahtet.
  Neue Admin-Seite "Änderungslog" unter /logs/aenderungen. PoE-Neustarts
  werden bewusst nicht geloggt.
- Verschlüsseltes Import/Export für Devices/Switches/Zugangsdaten unter
  Settings, passphrasenbasiert (PBKDF2 + Fernet), für Umzug auf neue
  Umgebungen. Referenziert Zugangsdaten/Switche über Name/Hostname statt
  interner ID für stabilen Re-Import.
- Eigenes Profil: Klick auf den Namen in der Sidebar öffnet ein Modal zum
  Ändern von Vor-/Nachname, eigenem Passwort (mit Prüfung des aktuellen
  Passworts) und Profilbild-Upload (Anzeige in Sidebar + Änderungslog).
- Anpassbare Navigation: Reihenfolge der Sidebar-Punkte ist unter Settings
  per Auf-/Ab-Buttons konfigurierbar (settings.nav_order); "Devices"/
  "Users"/"Settings" umbenannt zu "Geräte"/"Benutzer"/"Einstellungen";
  "Live-Log" und "Änderungslog" zu aufklappbarer "Logs"-Gruppe
  zusammengefasst. Jeder Benutzer sieht weiterhin nur, wofür er berechtigt
  ist.
- create_db.py mit allen Schema-Erweiterungen synchronisiert (audit_log,
  last_modified_by/at, avatar_filename) für Frischinstallationen.
- venv-Umgebung im WSL neu aufgesetzt (war fälschlich unter dem
  Erstellungspfad venv-linux verankert und daher nicht aktivierbar).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 14:27:46 +02:00
alientimandClaude Sonnet 5 fa6bb2935f Zugangsdaten-Entitaet, Gruppen-Tabelle mit Aufklappansicht, Vor-/Nachname, Dashboard-Sektionen
- Zugangsdaten (SSH-Logins) als eigenstaendige, wiederverwendbare Entitaet
  statt direkt am Switch; inline Neuanlage beim Switch-Erstellen moeglich;
  automatische Migration bestehender Switch-Logins
- Gruppen-Seite als Tabelle mit Aufklapp-Zeile fuer Rechte (Akkordeon),
  Admin als feste Systemzeile (Mitgliederverwaltung ueber is_admin),
  Standardgruppe 'Benutzer' mit allen Ansichtsrechten (devices.view,
  switches.view), automatische Zuordnung neuer/verwaister Benutzer
- Users-Seite: Icon-Buttons statt Text, Bearbeiten+Passwortaenderung in
  einem Modal zusammengefuehrt, Gruppe/Admin-Zuweisung ueber eigenen
  Zuweisen-Button (wie Switch-Zuordnung bei Devices), Vor-/Nachname
- Dashboard: einheitliche Kachelansicht mit/ohne Login, drei sortierte
  Abschnitte (Offline/Online/Deaktiviert), Kachel-Suchfilter, Bootstrap-
  artiges Grid (max. 6 Spalten), Aktivieren-Option im Popup fuer
  deaktivierte Geraete, Countdown serverseitig korrekt geseedet
- Sidebar dauerhaft einklappbar (Desktop, persistent via localStorage)
- Devices-Tabelle: Aktions-Buttons nebeneinander statt untereinander

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 13:30:47 +02:00
alientimandClaude Sonnet 5 82bfeb17ed Initial commit: PoE Manager modern UI rebuild
- Neues, eigenständiges Frontend (Sidebar, zentriertes Logo in der Topbar,
  Dark/Light-Theme, Karten-Dashboard, Toasts/Modals statt Bootstrap)
- Oeffentliches Kurz-Dashboard ohne Login (Status-Uebersicht)
- Browser-SSH-Terminal (paramiko, plattformunabhaengig) zum Testen von
  Switch-Zugangsdaten inkl. interaktiver Host-Key-Bestaetigung
- Granulares Rechtesystem mit Gruppen (Devices/Switches-Berechtigungen)
- Aufgeraeumtes Backend mit konfigurierbaren Pfaden, auto-generierten
  Secrets statt hart codierter Werte im Original

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 12:18:49 +02:00