69 Commits
Author SHA1 Message Date
alientimandClaude Sonnet 5 9a390e740d Gruppen-Dropdown: kompaktere Rechtetabelle, Modal bleibt unveraendert
- permission_tree() bekommt einen dritten Parameter compact=false, der
  nur im Dropdown der Hauptseite (Admin-/System-/editierbare Gruppen)
  auf true gesetzt wird, nicht im "Neue Gruppe"-Modal.
- .permission-groups-row--compact verkleinert Zeilen-/Spalten-Padding
  und die Einrueckung der Unterpunkte (32px statt 48px) NUR fuer diese
  Instanzen - das Modal behaelt exakt sein bisheriges Aussehen.
- Modal und Dropdown nutzen weiterhin denselben Code/dieselbe Struktur
  (permission_table()-Macro, Kill-Switch-Logik, JS-Gating), nur die
  Abstaende unterscheiden sich ueber die Zusatzklasse.
- Verifiziert per Screenshot: Dropdown jetzt sichtbar kompakter (engere
  Zellen, kuerzere Zeilen), Modal unveraendert; Gruppen anlegen-mit-
  Rechten und Gruppen-Bearbeiten-Regression funktionieren weiterhin.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 10:25:13 +02:00
alientimandClaude Sonnet 5 3d17728e75 Alle Anlegen-Modals einheitlich auf max-width:1000px
- addGroupModal, addCredentialModal, addOptionModal (DHCP), addSwitchModal,
  deviceModal (Gerät anlegen), userModal (Benutzer anlegen) — bisher
  unterschiedliche/keine explizite Breite, jetzt einheitlich 1000px für
  ein konsistentes Erscheinungsbild. Bearbeiten-/Zuweisen-Modals bleiben
  bei ihrer bisherigen (kleineren) Breite, da dort keine so breite
  Rechtetabelle wie bei Neue Gruppe eingebettet ist.
- Live verifiziert: Modal-Breite tatsächlich 1000px (vorher lieferte ein
  vergessener Flask-Neustart fälschlich 900px trotz bereits geänderter
  Vorlage — Erinnerung: Template-Änderungen brauchen ohne
  TEMPLATES_AUTO_RELOAD einen Neustart, anders als CSS/JS).
- Gruppen-Rechtetabelle bei 1440px (typische Breite dieser App) identisch
  zum Neue-Gruppe-Modal nebeneinander, ohne Umbruch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 10:05:58 +02:00
alientimandClaude Sonnet 5 bb3a6ab3a5 Gruppen-Rechtetabelle: Einrückung der Unterpunkte auf 48px erhöht
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 09:53:27 +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 8e4a874943 DHCP: Subnet/Netzmaske/Gateway immer aus System-Netzwerkkonfiguration ableiten
- Neue Helfer _list_network_interfaces() (echte Interfaces aus
  /sys/class/net) und _detect_interface_network() (IPv4/Prefix per
  "ip addr show", Gateway per "ip route show default") — Subnet/
  Netzmaske/Router werden dadurch bei jeder Anzeige/Generierung live vom
  System gelesen statt manuell gepflegt zu werden.
- dhcp_subnet/dhcp_netmask als manuelle Settings entfernt; Interface ist
  jetzt ein Dropdown mit den tatsächlich vorhandenen Interfaces statt
  Freitext, serverseitig zusätzlich gegen die echte Liste validiert.
- _dhcp_reservation_candidates()/_render_kea_config() nehmen jetzt das
  erkannte Netz (ipaddress.IPv4Network) bzw. net_info entgegen statt
  Subnet/Netzmaske aus der Konfiguration zu lesen; Router kommt vom
  erkannten Gateway (Fallback: erster DNS-Eintrag, wie zuvor).
- UI zeigt das erkannte Netz (IP/Prefix, Subnet, Gateway) read-only an;
  Schreiben/Vorschau werden blockiert bzw. liefern eine leere
  Reservierungsliste, wenn die Erkennung fehlschlägt, statt eine mit
  Sicherheit falsche Konfiguration zu erzeugen.
- Live getestet: Erkennung liefert korrekt das tatsächliche WSL-NAT-Netz
  (172.25.64.0/20) samt Gateway; generierte Config besteht kea-dhcp4 -t;
  ein Testgerät mit IP im erkannten Netz erscheint korrekt als
  Reservierung, Geräte außerhalb werden weiterhin sauber übersprungen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 08:28:11 +02:00
alientimandClaude Sonnet 5 c3d69a9870 DHCP: Backend auf Kea umgestellt, eigene Options (global + pro Client), echte Install-/Dienststeuerung
- Backend-Wechsel von isc-dhcp-server (seit 2022 EOL) auf Kea DHCP
  (kea-dhcp4-server) — aktiv weiterentwickelt, bildet "globaler Wert, pro
  Client überschreibbar" nativ über Kea-Reservation-Option-Data ab.
- Neue Tabellen dhcp_option_defs/dhcp_option_values: eigene/herstellerspezifische
  Options mit Code/Name/Typ/Beschreibung, Wert global sowie optional pro
  Client (device_mac="" für global, siehe Kommentar zur SQLite-NULL-
  UNIQUE-Falle). UI dafür: Optionen-Tabelle + "Neue Option"-Modal +
  Pro-Client-Overrides-Modal je Reservierung.
- Kea-JSON-Generator (_render_kea_config): option-def für jede eigene
  Option, globale Werte im Top-Level option-data, Client-Overrides im
  option-data der jeweiligen Reservierung.
- Reservierungen werden jetzt zusätzlich auf Zugehörigkeit zum
  konfigurierten Subnet gefiltert (_dhcp_reservation_candidates) — beim
  Live-Test gegen echtes Kea gefunden: Kea lehnt Reservierungen außerhalb
  ihres Subnets als Konfigurationsfehler ab, das muss also schon bei der
  Generierung berücksichtigt werden statt erst beim Laden zu crashen.
- Neue, einzeln bestätigte Aktionen: "kea-dhcp4-server installieren"
  (apt-get), "Aktivieren & (neu) starten" sowie "Stoppen"
  (systemctl) — bewusst getrennt von "Konfiguration speichern"/"In
  Datei schreiben".
- Live gegen eine echte, frisch installierte Kea-3.0.3-Instanz verifiziert:
  Installation erfolgreich, generierte Config besteht "kea-dhcp4 -t",
  Dienst übernimmt sie beim Neustart fehlerfrei (DHCP4_CONFIG_COMPLETE),
  globaler Options-Wert und Client-Override erscheinen korrekt getrennt.
  Danach wieder gestoppt; Paket bleibt installiert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 21:47:54 +02:00
alientimandClaude Sonnet 5 9eb9cfdda6 Neu: DHCP-Reservierungen aus Client-Stammdaten (Systemeinstellungen -> DHCP)
- Neue Unterseite unter Einstellungen (eigenes Rechtepaar
  settings_dhcp.view/settings_dhcp.edit, in PERMISSIONS/NAV_ITEMS/
  _nav_key_visible integriert, Kill-Switch über settings_group.view
  greift wie bei den anderen Einstellungen-Unterpunkten).
- Rein lesende Installations-/Status-Erkennung (shutil.which("dhcpd"),
  systemctl is-active isc-dhcp-server) — die App installiert/startet nie
  selbst einen DHCP-Dienst, sondern zeigt bei fehlender Installation den
  passenden manuellen Befehl an.
- Konfigurierbare Netzwerkparameter (Interface/Subnet/Netzmaske/Range/
  DNS/Domain/Lease-Zeiten/Ausgabepfad), gespeichert als dhcp_*-Schlüssel
  in der bestehenden settings-Tabelle.
- Reservierungen werden aus aktiven Geräten mit gültiger MAC+IP generiert
  (Hostname aus Gerätename abgeleitet, Kollisionen automatisch
  durchnummeriert, Geräte ohne MAC/IP werden übersprungen).
- "In Datei schreiben" (nur mit settings_dhcp.edit) schreibt eine
  separate Include-Datei statt der aktiven dhcpd.conf; kein automatischer
  Dienst-Reload/-Restart durch die App.
- Live getestet: Status-Erkennung, Config speichern, Reservierungs-
  Generierung inkl. Namenskollisionen, Datei-Schreiben in sicheren
  Testpfad, View-only-Gating (Formular ausgeblendet, POST blockiert),
  Kill-Switch über settings_group.view.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 21:10:05 +02:00
alientimandClaude Sonnet 5 06db4c1382 Switche: optionaler SSH-Port statt fest 22
- Neue Spalte switches.ssh_port (nullable INTEGER), Migration für
  bestehende DBs in _ensure_schema(), Feld in create_db.py ergänzt.
- Formular (Anlegen/Bearbeiten): optionales SSH-Port-Feld, Validierung
  1-65535, leer -> NULL (= Standard 22 überall, SWITCH_DEFAULT_SSH_PORT).
  Switch-Liste zeigt den effektiven Port inkl. "(Standard)"-Hinweis.
- generate_ips.py liefert den effektiven Port (Fallback 22) als eigenes
  Pipe-Feld an poe.sh; poe.sh übernimmt es in disable_poe/enable_poe und
  reicht es als "ssh -p <port>" an die expect-Skripte durch (Default
  weiterhin 22 falls Parameter fehlt).
- Web-Terminal (Verbindungstest) sendet den im Formular eingetragenen
  Port statt hartkodiert 22.
- Live getestet: gültiger/leerer/ungültiger Port beim Anlegen, korrekte
  Weitergabe durch generate_ips.py inkl. Feldreihenfolge, die poe.sh
'read' erwartet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 19:56:23 +02:00
alientimandClaude Sonnet 5 813b17d002 Rechtesystem: Löschen überall in Ändern falten, Gruppen-Tabelle transponieren
- "Ändern" deckt jetzt ausnahmslos überall Löschen mit ab (auch bei
  Clients) — es gibt kein eigenes *.delete-Recht mehr. Betroffen:
  devices/switches/credentials/users/groups.
- "D" in der Rechtetabelle bedeutet ausschließlich Dashboard-Neustart
  (devices.restart, PoE-Neustart über das Dashboard-Popup) und existiert
  nur bei Clients. Automatische Neustarts bei Ausfall (poe.sh) bleiben
  davon komplett unabhängig.
- Gruppen-Rechtetabelle transponiert: Kategorien jetzt als Zeilen,
  Rechte R(ead)/W(rite)/E(dit)/D(ashboard-Neustart) nebeneinander als
  Spalten statt untereinander. Deckt sich besser mit dem Legenden-Format
  und braucht weniger vertikalen Platz.
- Neue, einmalig laufende Migration (_migrated_permission_delete_fold_v2)
  überführt bestehende *.delete-Grants verlustfrei in *.edit, bevor die
  veralteten Rechte-Zeilen entfernt werden.
- Routen (delete_device/delete_switch/delete_credential/delete_user/
  delete_group) und die zugehörigen can_delete-Template-Variablen prüfen
  jetzt einheitlich *.edit statt *.delete.
- README-Rechtesystem-Abschnitt und Legende an das neue Tabellen-Layout
  angepasst.
- Live getestet: Kill-Switch, alle 5 Delete-Foldings (mit/ohne Recht),
  devices.restart-Gating unabhängig von devices.edit, Eskalationsschutz
  (Admin-Löschschutz, Systemgruppen-Schutz) — alles bestätigt korrekt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 19:49:28 +02:00
alientimandClaude Sonnet 5 4b7403f476 Vollständig granulares, an der Navbar gespiegeltes Rechtesystem
Kompletter Umbau des Permission-Systems weg von groben is_admin-Gates hin zu
einem zweistufigen, an die Sidebar-Struktur gespiegelten Rechtebaum:

  Geräte (devices_group.view)
   ├─ Clients      Lesen/Schreiben/Ändern/Löschen (+ PoE-Neustart)
   ├─ Switche      Lesen/Schreiben/Ändern/Löschen
   └─ Zugangsdaten Lesen/Schreiben/Ändern/Löschen (jetzt eigene Rechte,
                    vorher an switches.* gekoppelt)
  Logs (logs_group.view)
   ├─ Live         Lesen
   └─ Änderungen   Lesen
  Einstellungen (settings_group.view)
   ├─ Benutzer            Lesen/Schreiben/Ändern/Löschen
   ├─ Gruppen             Lesen/Schreiben/Ändern/Löschen
   ├─ Systemeinstellungen Lesen/Ändern
   └─ Im-/Export          Lesen (Export)/Ändern (Import)

- User.has_permission() ist jetzt hierarchisch: das "Bereich anzeigen"-Recht
  einer Top-Level-Gruppe wirkt als Kill-Switch für alle Kind-Rechte
  darunter, auch wenn ein Kind-Recht einzeln noch gesetzt ist. Mit
  Testgruppe verifiziert (devices.view ohne devices_group.view -> /devices
  liefert 302, "Geräte" verschwindet komplett aus der Sidebar; nach
  Zurücksetzen sofort wieder 200).
- devices.toggle entfällt, ist jetzt Teil von devices.edit (Ändern).
- Neue eigenständige credentials.*-Rechte statt Kopplung an switches.*.
- Benutzer- und Gruppenverwaltung sind jetzt ebenfalls granular/delegierbar
  (users.*/groups.*) statt fest is_admin-exklusiv — dafür neue,
  fest einprogrammierte Eskalationsschranken: Admin-Konten anlegen/ändern/
  löschen sowie Admin-Zuweisung bleiben unabhängig von delegierten Rechten
  echten Admins vorbehalten (mit Testgruppe verifiziert: Anlegen als Admin,
  Bearbeiten/Löschen bestehender Admin-Konten und Zuweisen zu "admin"
  wurden alle korrekt blockiert, normale Benutzerverwaltung funktioniert).
- "Admin" (virtuell) und "Benutzer" (Standardgruppe, neues is_system-Flag)
  sind jetzt echte Systemgruppen: weder umbenennbar noch in ihren Rechten
  änderbar, auch nicht durch Admins über die UI — Mitgliedschaft bleibt frei
  verwaltbar. Mit direktem POST verifiziert: Umbenennen/Löschen/Rechte-Reset
  von "Benutzer" werden blockiert, Mitgliederverwaltung funktioniert weiter.
- groups.html zeigt den Baum jetzt als 3 Zeilen (Geräte/Logs/Einstellungen)
  mit eingerückten Unterpunkten statt einer flachen Liste von Kategorien mit
  wiederholtem Bereichsnamen im Label.
- Migration in _ensure_schema() (Altrechte übertragen, neue Bereichs-Rechte
  für bestehende Gruppen nachtragen) läuft jetzt über einen Einmal-Guard in
  der settings-Tabelle — lief anfangs bei jedem Neustart erneut und hat
  damit den Kill-Switch-Mechanismus untergraben (ein deaktiviertes
  Bereichs-Recht wäre bei jedem Neustart automatisch wieder gesetzt worden,
  solange irgendein Kind-Recht noch aktiv war); im Test entdeckt und behoben.
- create_db.py synchronisiert (is_system-Spalte, neuer Rechtesatz für
  Frischinstallationen).
- README: Rechtesystem-Abschnitt komplett neu beschrieben (Baum, Kill-Switch,
  Systemgruppen, Eskalationsschutz).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 18:28:42 +02:00
alientimandClaude Sonnet 5 52b14b8ef7 Rechtesystem-Lücke schließen: Live-Log war nur @login_required statt admin-geschützt
Vollständiges Audit aller Routen gegen das Rechtesystem durchgeführt. Die
Nav-Sichtbarkeit stufte "Live" (Live-Log) bereits korrekt als admin-only ein
(_nav_key_visible: logs_live -> user.is_admin), die zugehörigen Routen
/logs und /get_log prüften das aber nie tatsächlich — nur @login_required.
Jeder eingeloggte Benutzer, unabhängig von seinen Gruppen-Rechten, konnte
das Live-Log damit direkt per URL aufrufen, obwohl die Sidebar es korrekt
ausblendete.

- /logs: fehlende is_admin-Prüfung ergänzt (Flash + Redirect, konsistent zu
  activity_log()/users()/groups()/settings()).
- /get_log: fehlende is_admin-Prüfung ergänzt (403, da per AJAX abgerufen).

Alle anderen neu hinzugekommenen Seiten (Benutzer, Gruppen, Systemein-
stellungen, Im-/Export, Änderungslog, Jetzt-prüfen-Trigger) waren bereits
korrekt und bewusst exklusiv auf is_admin geprüft — dort gibt es keine
sinnvolle granularere Rechte-Stufe unterhalb von Admin (Gruppenverwaltung
steuert das Rechtesystem selbst, Systemeinstellungen/Import-Export/manuelle
Prüfung wirken global). Zugangsdaten bleiben bewusst an switches.*-Rechte
gekoppelt (bestehende, dokumentierte Design-Entscheidung). README um eine
Übersicht ergänzt, welche Bereiche bewusst ohne granulare Rechte auskommen
und warum.

Mit Testbenutzer ohne jede Gruppenzugehörigkeit verifiziert: /logs liefert
jetzt 302 (Redirect), /get_log liefert 403 statt beide zuvor 200.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 16:01:39 +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 e4cceb4091 poe.sh: CRLF-Zeilenenden, Feldanzahl und Switch-Gating fixen
- Datei hatte CRLF-Zeilenenden (vermutlich aus einer Windows-Bearbeitung),
  wodurch das Skript unter Linux/WSL mit "command not found: $'\r'" und
  Syntaxfehlern abbrach. Auf LF normalisiert.
- Die Haupt-Check-Schleife las per `read` nur 7 Felder aus
  generate_ips.py, das aber inzwischen 8 Felder liefert (MAC am Ende
  angehängt) — dadurch landete die MAC-Adresse an $switch_pass
  angehängt. `mac` als zusätzliche (ungenutzte) read-Variable ergänzt.
- PoE-Neustart wurde bei nicht erreichbaren Geräten ausgelöst, sobald ein
  `port`-Wert gesetzt war — unabhängig davon, ob dem Gerät überhaupt ein
  Switch zugeordnet ist. Das führte zu sinnlosen SSH-Versuchen mit leeren
  Zugangsdaten (ssh @) und irreführenden "PoE deaktiviert/aktiviert"
  Log-Einträgen für Geräte ohne Switch. Prüft jetzt zusätzlich, dass
  switch_ip nicht leer ist, bevor ein Neustart versucht wird (gilt für
  den regulären Check-Loop und den manuellen Neustart).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 14:56:53 +02:00
alientimandClaude Sonnet 5 37dac64abc Live-Log-Fix, Sidebar-Untermenüs für Geräte/Einstellungen, eigenes Konto
- Live-Log-Bug behoben: _latest_log_file() sortierte nach Datei-ctime statt
  nach Dateiname — auf manchen Dateisystemen (u.a. unter WSL2 auf einem
  gemounteten Windows-Laufwerk) unzuverlässig und lieferte nicht immer das
  tatsächlich neueste Logfile. Sortiert jetzt wie der Rest des Codes über
  den chronologisch sortierbaren Dateinamen (rpi-YYYYMMDDHHMMSS.log).
- Navbar umstrukturiert in aufklappbare Gruppen mit Unterpunkten:
  - "Geräte": Clients (bisherige Devices-Seite), Switche, Zugangsdaten
  - "Einstellungen": Benutzer, Gruppen, Systemeinstellungen (Prüfintervall),
    Im-/Export
  - "Logs": Live, Änderungen (vormals Live-Log/Änderungslog)
  Sichtbarkeit gilt jetzt auch pro Unterpunkt: eine Gruppe erscheint nur,
  wenn mindestens ein Unterpunkt für den Benutzer sichtbar ist, und zeigt
  dann auch nur die sichtbaren Unterpunkte.
- Im-/Export als eigene Unterseite mit Export/Import nebeneinander
  (.settings-grid).
- Neue Seite "Mein Konto" (/account, erreichbar über ein Zahnrad-Symbol
  neben dem eigenen Namen in der Sidebar) ersetzt das bisherige Profil-Modal:
  Profil/Passwort/Profilbild als volle Seite, dazu für Admins die
  Navbar-Reihenfolge (aus den Systemeinstellungen hierher verschoben).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 14:44:02 +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 08d8d1f738 Dashboard-Kacheln, Ansichtsrechte, Standardgruppe, Countdown-Fix, Deploy-Pfad
- Dashboard zeigt jetzt in beiden Zustaenden (mit/ohne Login) Kacheln statt
  Tabelle; ohne Login nur aktive Geraete + Online/Offline/Gesamt, eingeloggt
  alle Geraete + zusaetzliche Deaktiviert-Kachel
- Sortierung ueberall: erst alle Nicht-Online-Geraete, dann Online, jeweils
  alphabetisch
- Neue Rechte devices.view / switches.view; Standardgruppe 'Benutzer' wird
  automatisch angelegt (alle Ansichtsrechte) und jedem neuen Benutzer
  zugeordnet; bestehende Benutzer ohne Gruppe werden migriert
- Gruppen-Seite zeigt zusaetzlich virtuelle 'Admin'-Karte (informativ) und
  markiert die Standardgruppe (nicht loeschbar)
- 'Naechste Pruefung'-Countdown wird serverseitig aus dem tatsaechlichen
  letzten Log-Eintrag geseedet statt bei jedem Reload neu zu starten
- Deployment-Doku korrigiert: Checkout getrennt von /srv/poe_manager, damit
  kein verschachteltes srv/poe_manager/srv/poe_manager entsteht

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 12:41:21 +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