8577cd24cdbdc3a646a7e0da387424e6a6f381ab
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1b7fe81507 |
Fileshare: Baum-Navigation, Datei-Vorschau, 15MB-Uploads (v1.1.1)
- Freigaben-Auswahl von einem Dropdown auf eine Baum-Navigation (links) umgestellt: alle gemounteten Freigaben als Wurzelknoten, Ordner beliebig aufklappbar. Der Pfad von der Wurzel bis zur aktuellen Position wird serverseitig schon aufgeklappt gerendert (_fileshare_tree_ancestors), alles andere laedt der Client per Klick lazy nach (neue Route /fileshare/subfolders) -- kein Durchlaufen der kompletten Freigabe auf einmal noetig. Dateien stehen bewusst nicht im Baum, nur in der bestehenden Tabelle rechts. - Inline-Vorschau fuer PDF (iframe), Bilder, TXT/CSV/LOG/MD/JSON (per Range- Request in Haeppchen bis 512KB, mit Hinweis bei Abschneiden -- Erkennung ueber den Content-Range-Header, nicht nur den 206-Status, der bei JEDEM Range-Request auftritt) sowie Word/Excel rein clientseitig per mammoth.js bzw. SheetJS (beide lokal vendored, kein Cloud-Viewer -- interne Dokumente verlassen das Netz nicht). Excel-Zellen werden bewusst per textContent statt ueber SheetJS' eigene HTML-Ausgabe gesetzt, um unabhaengig von deren Escaping-Verhalten sicher zu sein. Neue Route /fileshare/view mit fester Endungs-Positivliste, nosniff + restriktiver CSP. - Uploads bis 15MB erlaubt (MAX_CONTENT_LENGTH in app.py) -- dafuer musste auch nginx' client_max_body_size (Standard 1MB) auf 16MB angehoben werden, sowohl im Vorlagen-Code (_NGINX_PROXY_LOCATIONS/_render_nginx_config, fuer die naechste Anwendung ueber Einstellungen->NGINX) als auch in der Fresh-Install-Vorlage. Neuer 413-Errorhandler zeigt eine Flash-Meldung statt Werkzeugs nackter Fehlerseite. - install.sh: known_hosts (liegt unter /srv/tesm) von rsync --delete ausgenommen -- fehlte bisher in der Exclude-Liste (anders als sqlite.db/ fernet.key/secret.key) und waere bei jedem Update verlorengegangen. Live auf POETEST getestet: Baum-Vorbefuellung, Lazy-Load von Geschwisterordnern, alle 5 Vorschautypen (PDF-Route direkt verifiziert, Bild/Text/Word/Excel zusaetzlich visuell), Abschneide-Erkennung sowohl bei kleiner als auch bei >512KB-Datei. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
09b222615a |
Fileshare-Feature: LDAP-gruppengesteuerte Netzlaufwerke im Browser (v1.1.0)
- Neue ldap_fileshare_mappings-Tabelle (AD-Gruppe -> Freigabe-UNC+Label), verwaltet in Einstellungen -> LDAP wie die bestehende App-Gruppenzuordnung (inkl. AD-Gruppen-Dropdown per "Gruppen laden", UNC-Backslash/Slash- Normalisierung). - Login-Gate: optionale "Erforderliche AD-Gruppe fuer Login" (Dropdown, gleiches Lade-Muster) -- ohne Mitgliedschaft scheitert der Login wie bei falschen Zugangsdaten, ohne Hinweis auf den eigentlichen Grund. - Sessionabhaengiges Mounten: beim LDAP-Login werden alle per AD-Gruppe zugeordneten Freigaben mit den eigenen (nie gespeicherten) Zugangsdaten per mount.cifs unter /mnt/tesm-shares/<session-token>/ gemountet, beim Logout wieder ausgehaengt. Passwort läuft ausschliesslich ueber die PASSWD-Umgebungsvariable von mount.cifs. Aufraeum-Sweep (30 Min-Takt, 12h-Schwelle) und Cleanup-on-Startup als Sicherheitsnetz. - Zwei unabhaengige Gates: TESM-Rechtesystem (fileshare.view/.create/.edit, neue PERMISSIONS-Gruppe fileshare_group) UND AD-Gruppenmitgliedschaft muessen beide zutreffen, sonst wird nicht gemountet und der Menuepunkt "Dateifreigaben" bleibt verborgen. - Neuer Dateibrowser (/fileshare, .../download, .../upload, .../mkdir, .../delete, .../rename) mit Breadcrumbs, Upload/Download, Anlegen/ Umbenennen/Loeschen -- Pfadaufloesung ausschliesslich ueber os.path.realpath-Vergleich gegen die eigene Mount-Root (Path-Traversal- Schutz), zusaetzlich secure_filename() fuer Datei-/Ordnernamen. - KRITISCHER Bugfix waehrend Live-Test gefunden: generate_ips.py importiert app.py als Hilfsmodul (u.a. aus poe.sh/tesm-check.service heraus, alle paar Sekunden) -- das fuehrte Modul-Level-Code erneut aus und hat aktive Fileshare-Mounts anderer Sitzungen sofort wieder ausgehaengt. Neues TESM_WEB_PROCESS-Env-Flag (nur in tesm.service gesetzt) schuetzt Cleanup-on-Startup und den Sweep-Thread davor, bei einem reinen Modul-Import erneut zu laufen. - install.sh: cifs-utils ergaenzt (liefert mount.cifs). - SCHEMA_VERSION 1 -> 2, VERSION 1.0.10 -> 1.1.0. Live auf Testbox (192.168.82.51) und POETEST (192.168.80.202) getestet: Login-Gate (erlauben/verbieten/reset), Rechte-Gate (Mount+Menuepunkt nur mit fileshare.view), vollstaendiger Datei-Workflow (Upload/Download/ Umbenennen/Anlegen/Loeschen) gegen eine echte SMB-Freigabe, Path-Traversal gegen alle 5 Routen (serverseitig verifiziert, kein Escape), sauberes Unmount bei /logout. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
4de5828573 |
NGINX-Seite ausgebaut: Domain/Ports, RAW-Config, Let's Encrypt mit Auto-Verlaengerung; Flask nur noch lokal erreichbar
Umbenennung: Einstellungen -> SSL/TLS heisst jetzt Einstellungen -> NGINX (Route /settings/ssl -> /settings/nginx, Recht settings_ssl.* -> settings_nginx.*, Icon "server" statt "shield") -- die Seite verwaltet den kompletten Reverse-Proxy, nicht mehr nur SSL. Neu: - Domain (server_name) und HTTP-/HTTPS-Port sind jetzt einstellbar, nicht mehr hart "_" bzw. 80/443. Aendert man den HTTP-Port weg von 80, wird automatisch zusaetzlich ein minimaler Nur-ACME-Block auf Port 80 mitgeschrieben, da Let's Encrypt (HTTP-01) protokollbedingt immer Port 80 braucht, unabhaengig vom konfigurierten HTTP-Port. - "RAW-Konfiguration"-Button zeigt die komplette aktuelle nginx-Config im selben Popup-Stil wie das Live-Log (Wiederverwendung von window.openRawLogModal, kein neuer Code dafuer noetig). - Let's Encrypt: Zertifikat per certbot anfordern (certonly --webroot, bewusst NICHT das certbot-nginx-Plugin -- das wuerde die App-eigene, komplett selbstgeschriebene Config direkt editieren und bei der naechsten Aenderung ueber diese Seite wieder verlieren). Automatische Verlaengerung laeuft ueber certbots eigenen systemd-Timer/Cron (Standard-Paketverhalten), ein Deploy-Hook (/etc/letsencrypt/renewal-hooks/deploy/tesm-reload-nginx.sh, wird wie die logrotate-Config bei jedem App-Start neu geschrieben) laedt nginx nach jeder Verlaengerung neu. Fehlgeschlagene Anforderung (kein oeffentlicher DNS-Eintrag o.ae.) wird sauber abgefangen und als Fehlermeldung angezeigt, ohne etwas zu veraendern -- live mit einer ungueltigen Test-Domain verifiziert. - Zertifikatsquelle (Upload vs. Let's Encrypt) wird als eigenes Setting (ssl_source) verfolgt, das Anwenden/Anzeigen/Entfernen beruecksichtigt beide Quellen jeweils passend (Entfernen einer LE-verwalteten Installation laeuft ueber "certbot delete", nicht ueber rohes Datei-Loeschen, damit certbots eigene Renewal-Konfiguration nicht verwaist). - certbot zu install.sh's Paketliste hinzugefuegt. Flask/gunicorn bindet jetzt an 127.0.0.1 statt 0.0.0.0 (tesm.service) -- direkter Zugriff auf Port 5000 aus dem Netz ist damit nicht mehr moeglich, nur noch ueber den nginx-Reverse-Proxy (der ohnehin nur ueber 127.0.0.1 zugreift). Beantwortet die Nachfrage, ob Flask unerreichbar gemacht werden kann. Live auf Testsystem-Update-Restart verifiziert: Domain/Port-Aenderung (HTTP-Port 8080 inkl. automatischem Zusatz-Block auf Port 80), RAW-Config-Anzeige, Zertifikat-Upload, Let's-Encrypt-Fehlschlag sauber abgefangen, Rueckbau auf Standardwerte (_, 80, 443, kein SSL) ueber denselben Anwenden/Bestaetigen-Sicherheitsnetz-Pfad wie zuvor. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
bc360a0b7f |
Produktiver WSGI-Server (Gunicorn) statt Flasks Entwicklungsserver
tesm.service startete die App bisher direkt per 'python3 app.py', was Flasks eingebauten Werkzeug-Entwicklungsserver nutzt -- der meldet bei jedem Start 'WARNING: This is a development server. Do not use it in a production deployment.' und ist bewusst nicht für Dauerbetrieb gebaut. Umgestellt auf Gunicorn, mit zwei bewusst gesetzten Einschraenkungen: - '--workers 1': die App haelt laufende Wartungs-Jobs/Import-Vorschauen nur im Arbeitsspeicher DES EINEN Prozesses (_maintenance_jobs, _pending_imports, ...) -- mehrere Worker-Prozesse wuerden diesen Zustand auf mehrere, sich nicht kennende Prozesse verteilen. - '--worker-class gthread --threads 16' statt eines async-Workers: das Browser-SSH-Terminal (flask-sock) belegt pro offener WebSocket- Verbindung einen blockierenden Thread. - '--timeout 0': deaktiviert Gunicorns eigenen 30s-Worker-Timeout, der sonst auch eine offene, aber gerade inaktive SSH-Terminal-Verbindung killen wuerde. Live auf POETEST verifiziert: keine WARNING-Zeile mehr, genau 1 Master- + 1 Worker-Prozess, alle Kernseiten weiterhin 200, und als kritischer Regressionstest das WebSocket-SSH-Terminal Ende-zu-Ende gegen einen echten Host erfolgreich getestet (Host-Key/Passwort-Prompt/Login/Shell). Dabei einen unabhaengigen Altlast-Fehler in POETESTs venv gefunden und allgemein in install.sh gefixt: './venv/bin/pip' hat eine zur Venv-Erstellung fest einprogrammierte Shebang-Zeile -- nach der historischen Umbenennung 'poe_manager' -> 'tesm' zeigte sie auf einen nicht mehr existierenden Pfad und schlug mit 'cannot execute: required file not found' fehl. 'python3 -m pip' umgeht das, da nur der (korrekt referenzierte) venv-Python-Interpreter selbst gebraucht wird -- betrifft sonst auch jedes kuenftige In-Place-Update auf einem aehnlich gewachsenen Host. |
||
|
|
3ab3407a18 |
Login-Seite überarbeitet, TESM-Logo als echter Hintergrund; SSH-MOTD-Banner mit Live-Daten
- Login-Seite: WiS-/TESM-Logo und "Melde dich an, um fortzufahren" aus der Box entfernt; die TESM-Wortmarke mit Funktionszeile ist jetzt der tatsächliche Seitenhintergrund (absolut positioniert, hinter allem), die Box liegt zentriert davor. Nebenbei zwei echte Bugs gefunden und behoben: fehlendes Cache-Busting auf login.html (asset_url() wie in base.html, sonst hält nginx' 7-Tage-Cache eine alte style.css/app.js fest) und ein durch den fehlenden align-items-Wert auf die volle Höhe gestrecktes Login-Formular. - Neuer SSH-Login-Banner (dynamisches MOTD) mit Live-Flottenstatus statt der Standard-Ubuntu-Willkommensmeldung: srv/tesm/motd_banner.py liest Online/Offline- und DHCP-Status aus denselben Quellen wie das Web-Dashboard (get_device_status()/_dhcp_read_leases()), eingebunden über etc/update-motd.d/50-tesm. install.sh deaktiviert dabei die Standard- Ubuntu-MOTD-Skripte (chmod -x, reversibel) und installiert den neuen Hook. |
||
|
|
d1b10bd970 |
Rebrand to TESM: infra rename, LDAP/AD login, selective import/export, Papierkorb
- Vollständiges Rebranding "PoE Manager" -> TESM (TimEShepManager): neue Logos/Favicon (theme-aware), Sidebar/Login-Branding, Copyright-Zeile. - Infrastruktur-Umbenennung: srv/poe_manager -> srv/tesm, alle POE_*-Env-Vars -> TESM_* (POE_SCRIPT bewusst unverändert, echtes PoE-Skript), systemd Units poe_web/rpi-check* -> tesm/tesm-check*, nginx-Site, netplan/logrotate Configs, Gitea-Repo alientim/Aruba-PoE-Modern -> alientim/tesm. - LDAP/Active-Directory Same-Sign-On: Search+Bind, AD-Gruppen->App-Gruppen- Zuordnung (additiv), Konto-Sperren, AD-Vorab-Suche/-Anlage, eigene Einstellungsseite. - Selektives Import/Export (8 Kategorien, Zwei-Schritt-Vorschau) mit eigenem R/E/X-Rechtemodell (X = Export, getrennt von E = Import). - Papierkorb: Soft-Delete statt Hard-Delete für Geräte/Switche/Zugangsdaten/ Benutzer/Gruppen (AD-Nutzer ausgenommen), eigene Seite unterhalb Wartung, konfigurierbare Aufbewahrungsfrist. - rpi_ip -> ip Spalten-/Code-Umbenennung (Geräte sind längst nicht mehr auf Raspberry Pis beschränkt). - README auf aktuellen Stand gebracht. |
||
|
|
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). |
||
|
|
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> |