3195df0fd320bbba2c38903b5bc6b724e51d78db
26
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3195df0fd3 |
Fix: nginx blockierte SSH-Terminal-WebSocket + DHCP-Stop bei Netzwerkaenderung
Auf der frisch installierten Test-VM zeigten sich zwei weitere reale Probleme: 1. "Verbindung testen" im Switch-Modal blieb dauerhaft auf "Getrennt" haengen, sobald ueber nginx (Port 80) statt direkt gegen Flask (Port 5000) zugegriffen wurde. Ursache: etc/nginx/sites-available/poe_manager reichte den "Upgrade"/"Connection"-Header fuer /ws/ssh_terminal nicht durch -- Flask/Werkzeug lehnte den WebSocket-Handshake dadurch mit 400 Bad Request ab, statt mit 101 Switching Protocols zu antworten. Live reproduziert und verifiziert (curl-Handshake direkt vs. durch nginx). Alle bisherigen Terminal-Tests dieser Session liefen ausschliesslich direkt gegen Flask, nie durch nginx, daher bis jetzt unentdeckt. Fix: eigener location /ws/ Block mit Upgrade-Map (Standard-nginx-Pattern) und grosszuegigen Timeouts fuer die lang offene Terminal-Verbindung. 2. Der Kea-DHCP-Server lief nach einer Aenderung der Host-Netzwerkkonfiguration unveraendert weiter, obwohl die konfigurierte Range nach einem IP-/Subnetzwechsel nicht mehr zum neuen Netz passen muss. Neue Funktion _stop_dhcp_service_if_active() stoppt Kea jetzt sowohl beim Anwenden als auch beim Auto-Rollback einer Netzwerkaenderung -- bewusst nur stoppen statt automatisch neu zu starten, die Range muss der Admin aktiv auf der DHCP-Seite pruefen und den Dienst dort bewusst wieder starten (gleiche Philosophie wie beim Rest der DHCP-Dienststeuerung). Beide Fixes live auf der Test-VM verifiziert (WebSocket-Handshake per curl, Netzwerk-Reapply ohne Fehler im journalctl-Log trotz nicht installiertem Kea). |
||
|
|
2b5d9d1b48 |
Netzwerkeinstellungen: netplan/systemd-networkd als drittes Backend + DHCP-Interface-Default-Fix
Auf einer echten, frisch installierten Ubuntu-24.04-VM (192.168.80.114, Standard-Setup, Netz per DHCP) zeigten sich zwei reale Bugs: 1. Systemeinstellungen > Netzwerkeinstellungen: 'Kein unterstütztes Backend erkannt' trotz laufendem Netz -- _detect_network_backend() kannte nur NetworkManager und dhcpcd, nicht netplan/systemd-networkd, den mit Abstand haeufigsten Fall auf einem normalen Ubuntu-Host. Neues drittes Backend 'netplan' ergaenzt: Erkennung ueber systemd-networkd + vorhandenes netplan-Binary, Moduserkennung ueber das 'dynamic'-Flag des Kernels auf der aktuellen Adresse, Anwenden ueber eine eigene Override-Datei (/etc/netplan/90-poe-manager.yaml, gewinnt alphabetisch gegen z.B. cloud-inits 50-*.yaml) plus Aufruf von netplan apply, Backup/Auto-Rollback wie bei den anderen Backends. Live verifiziert: Anwenden loeste echten DHCP-Lease-Renew aus, nach Ablauf der 45s-Bestaetigungsfrist wurde die Override-Datei automatisch wieder entfernt (Rollback funktioniert). 2. DHCP-Konfiguration: 'Keine IPv4-Adresse auf eth0 gefunden', obwohl das Interface-Dropdown korrekt 'enp1s0' zeigte -- DHCP_DEFAULTS hatte 'eth0' hart kodiert (Annahme aus einer aelteren Testumgebung), was auf Systemen mit Predictable Network Interface Names schlicht nicht existiert. _load_dhcp_settings() korrigiert das jetzt: liegt der gespeicherte/Default-Wert nicht unter den tatsaechlich vorhandenen Schnittstellen, wird automatisch die erste echte vorgeschlagen. Neue Abhaengigkeit PyYAML fuer das Schreiben der netplan-Override-Datei. |
||
|
|
9e23243872 |
Fix: rsync fehlte in install.sh-Paketliste (Deploy-Schritt braucht es)
Live auf frischem Testsystem (Ubuntu 24.04, 192.168.80.114) verifiziert: Skript brach beim Kopieren nach /srv/poe_manager mit 'rsync: command not found' ab, weil rsync nirgends in der apt-get-install-Zeile stand. |
||
|
|
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>
|
||
|
|
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> |
||
|
|
82edf7628b |
Neu: Netzwerkeinstellungen des Hosts unter Systemeinstellungen (IP/DNS/DHCP)
Bisher enthielt "Systemeinstellungen" nur das Pruefintervall. Jetzt zusaetzlich Verwaltung der Netzwerkkonfiguration DIESES Hosts (getrennt vom Kea-DHCP-*Server* fuer Clients): - Backend-Erkennung (NetworkManager vs. dhcpcd via systemctl is-active). Kein erkanntes Backend -> Seite bleibt rein lesend statt zu raten. - Status-Anzeige: Interface, IP/Prefix, Gateway, DNS, Modus (DHCP/Statisch). - Aenderung: Interface, Modus, bei Statisch IP/Prefix/Gateway, DNS unabhaengig von Modus setzbar (IP per DHCP + feste DNS moeglich). - Sicherheitsnetz analog "netplan try": Backup vor jeder Aenderung, automatisches Rollback nach 45s ohne explizite Bestaetigung (nur moeglich, wenn die Seite ueber die neue Config noch erreichbar ist) -- verhindert Aussperren durch einen Tippfehler bei IP/Gateway. - Bugfix waehrend der Implementierung gefunden: der Auto-Revert-Timer laeuft in einem Hintergrund-Thread ohne Request-Kontext: log_action() griff auf current_user zu und warf dort einen AttributeError (die Config wurde trotzdem korrekt zurueckgerollt, nur der Audit-Log-Eintrag fehlte und ein Fehler landete im Server-Log). Fix: log_action_system() ohne current_user-Abhaengigkeit fuer Code ausserhalb des Request- Kontexts. - Getestet: Backend-Erkennung + rein lesender Fallback live (WSL hat weder NetworkManager noch dhcpcd aktiv, korrekt erkannt), Rechte-Gating, Anwenden-/Rollback-Logik fuer beide Backends per gemocktem subprocess.run verifiziert (inkl. echtem dhcpcd.conf-Rewrite und vollständigem Anwenden-dann-Auto-Rollback-Durchlauf mit Audit-Log- Eintrag). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
197af26d72 |
Navbar-Reihenfolge: Unterpunkte je Gruppe editierbar, Karte unter Profil/Passwort verschoben
- Neuer Settings-Schluessel nav_child_order (JSON dict group_key -> geordnete Liste der Kind-Keys), analog zu nav_order fuer die Top-Level- Reihenfolge. _ordered_nav_items() liefert die komplette, ungefilterte Navbar-Struktur inkl. angewandter Kind-Reihenfolge; inject_nav() filtert das anschliessend weiterhin nach Berechtigung wie bisher. - save_nav_order() verarbeitet zusaetzlich ein Feld nav_child_order_<group_key> pro Gruppe mit Kindern. - account.html: Navbar-Reihenfolge-Karte jetzt UNTER Profil/Passwort aendern (vorher darueber), zeigt die komplette Navbar inkl. eingerueckter, separat sortierbarer Unterpunkte pro Gruppe (verschachtelte <ul>, moveNavItem() bewegt automatisch nur innerhalb der eigenen Gruppe dank DOM-Nesting). - Live per Playwright verifiziert: Zugangsdaten innerhalb Geraete nach oben verschoben, gespeichert, Sidebar zeigt danach tatsaechlich die neue Reihenfolge (Zugangsdaten vor Clients/Switche). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
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> |
||
|
|
bb3a6ab3a5 |
Gruppen-Rechtetabelle: Einrückung der Unterpunkte auf 48px erhöht
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |