Release v1.1.6 #20

Merged
AxonByteDev merged 13 commits from beta into main 2026-09-26 11:09:40 +00:00
Owner
  • docs: Installationsanleitung korrigiert — git, Bare-Metal-Weg, Version
  • fix: Update-Prüfung versteht "git describe"-Versionen
  • feat: Scripts-Suche findet auch Zielserver
  • docs: Benutzer und Rollen dokumentieren
  • feat: Benutzerverwaltung unter Einstellungen → Sicherheit, Oberfläche nach Rolle
  • feat: Benutzerverwaltung für Admins (/api/users)
  • feat: Benutzer mit Rollen (Admin, Operator, Nur-Lesen) und zentrale Rechteprüfung
  • feat: Logo und Icons für PatchPilot
  • feat: Suche in Server und Updates, alphabetische Sortierung, sortierbare Dashboard-Tabelle
  • feat: Suche auf der Snapshots-Seite findet auch Servernamen
  • feat: Einstellungen als Aufklapp-Menü in der Seitenleiste statt zweitem Menü
  • feat: E-Mail-Benachrichtigungen in den Einstellungen, Doku (#18)
  • feat: E-Mail-Benachrichtigungen über SMTP im Backend (#18)
- docs: Installationsanleitung korrigiert — git, Bare-Metal-Weg, Version - fix: Update-Prüfung versteht "git describe"-Versionen - feat: Scripts-Suche findet auch Zielserver - docs: Benutzer und Rollen dokumentieren - feat: Benutzerverwaltung unter Einstellungen → Sicherheit, Oberfläche nach Rolle - feat: Benutzerverwaltung für Admins (/api/users) - feat: Benutzer mit Rollen (Admin, Operator, Nur-Lesen) und zentrale Rechteprüfung - feat: Logo und Icons für PatchPilot - feat: Suche in Server und Updates, alphabetische Sortierung, sortierbare Dashboard-Tabelle - feat: Suche auf der Snapshots-Seite findet auch Servernamen - feat: Einstellungen als Aufklapp-Menü in der Seitenleiste statt zweitem Menü - feat: E-Mail-Benachrichtigungen in den Einstellungen, Doku (#18) - feat: E-Mail-Benachrichtigungen über SMTP im Backend (#18)
Reiner Ausgangskanal zusätzlich zu Matrix — es wird kein Postfach abgerufen und keine Antwort
ausgewertet; Befehle gibt es weiterhin nur über den Matrix-Bot.

- notifications.send() verteilt an Matrix und E-Mail; jeder Kanal ist einzeln abgesichert, ein
  Fehler wird nur geloggt und blockiert weder den anderen Kanal noch den auslösenden Job
- die bestehenden Ereignis-Schalter (send_if) gelten für beide Kanäle
- Versand mit smtplib (keine neue Abhängigkeit): STARTTLS, SSL/TLS oder unverschlüsselt,
  Anmeldung nur mit Benutzername, Timeout 10 s, mehrere Empfänger (Komma oder Semikolon)
- Betreff aus der Nachricht, z.B. "[PatchPilot] Update auf web erfolgreich abgeschlossen.",
  Text als Klartext ohne Matrix-Fettschrift
- Einstellungen email_enabled (Standard aus), smtp_host/port/security/user/password/from/to;
  smtp_password wird wie matrix_password maskiert und nie ans Frontend geliefert
- POST /api/settings/email/test — funktioniert auch vor dem Einschalten des Kanals, meldet
  fehlende Angaben, Anmelde- und Verbindungsfehler verständlich

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Einstellungen → Benachrichtigungen jetzt in drei Bereichen:
- Matrix (unverändert)
- E-Mail: aktivieren, SMTP-Server, Port, Verschlüsselung (STARTTLS/SSL/TLS/keine, passender
  Standard-Port wird vorgeschlagen), Benutzername/Passwort optional (Passwort nur maskiert),
  Absender, Empfänger (kommagetrennt). "Test-E-Mail senden" speichert vorher und geht auch
  vor dem Aktivieren
- Ereignisse: die Schalter gelten für Matrix und E-Mail und stehen deshalb für sich

Doku: neue Seite docs/E-Mail-Benachrichtigungen.md (Einrichtung, App-Passwörter,
Fehlersuche); Verweise und "Matrix-Nachricht"-Stellen in README, Installation, Selbst-Update,
Neustart, Backup, Matrix und Entwicklung auf beide Kanäle angepasst.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
"Einstellungen" in der Seitenleiste klappt jetzt seine Kategorien direkt darunter auf
(Allgemein, Proxmox, Benachrichtigungen, Sicherheit, PatchPilot-Update, Backup &
Wiederherstellung). Auf einer Einstellungsseite ist die Gruppe offen und die aktive Kategorie
markiert, sonst per Klick auf- und zuklappbar. Das eigene Untermenü auf der Einstellungsseite
entfällt; die Überschrift zeigt die aktuelle Kategorie ("Einstellungen · Sicherheit").

- Kategorien an einer Stelle: pages/settings/categories.ts
- lange Namen brechen in der Seitenleiste um statt abgeschnitten zu werden oder zu scrollen
- die Seitenleiste scrollt nur auf sehr niedrigen Fenstern, wenn alles aufgeklappt ist
- Adressen /settings/<kategorie> bleiben unverändert

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Passt der Suchbegriff zu einem Servernamen, erscheinen alle Snapshots dieses Servers —
bequemer als der Server-Filter daneben. Snapshot-Namen und Beschreibungen werden weiterhin
durchsucht, Groß-/Kleinschreibung spielt keine Rolle.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Server und Updates: Suchfeld (Name, Adresse, Typ, Betriebssystem; mehrere Wörter müssen
  alle vorkommen) mit Anzeige "x von y" und Hinweis, wenn nichts passt. Auf der Server-Seite
  bleibt der gerade bearbeitete Server sichtbar, auch wenn er nicht zur Suche passt
- Sortierung überall alphabetisch nach Name statt in Anlage-Reihenfolge — deutsch und
  "natürlich": Groß-/Kleinschreibung egal, "web2" vor "web10"
- Dashboard: jede Spaltenüberschrift sortiert per Klick, ein zweiter Klick dreht die Richtung
  um; Standard Name A–Z. Leere Werte stehen immer unten, bei Gleichstand entscheidet der Name.
  Status aufsteigend = Wichtigstes zuerst (Fehler, Updates verfügbar, Aktuell, Unbekannt,
  Inaktiv). Für "Snapshots" werden die Abfragen des Snapshot-Badges mitgenutzt (geteilter
  Cache, keine zusätzliche Last)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Bisher zeigte der Browser kein Icon (index.html verwies auf ein nicht vorhandenes /vite.svg).

- Logo in den Projektfarben: blaues abgerundetes Quadrat, weißes Schild (Sicherheit) mit
  Pfeil nach oben (Update) und Haken (erledigt). Bewusst schlicht und kräftig, damit es auch
  als 16-px-Tab-Symbol erkennbar bleibt
- frontend/public/favicon.svg als Quelle, daraus favicon-32.png, apple-touch-icon.png (randlos,
  iOS rundet selbst ab), icon-192/512.png und site.webmanifest für "Zum Home-Bildschirm"
- Logo in der Seitenleiste neben dem Namen und auf der Anmeldeseite (statt des
  Platzhalter-Symbols), oben rechts in der README
- Doku: wie man das Logo ändert und die PNGs neu erzeugt

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Grundlage für die Benutzerverwaltung:
- neue Tabelle appuser (Benutzername, Passwort-Hash, Rolle, aktiv, token_version, letzter Login)
- Beim Start wird der bisherige Einzel-Login (auth_username/auth_password_hash) zum ersten
  Admin — bestehende Installationen behalten ihre Zugangsdaten, frische bekommen
  admin / PatchPilot. Das greift auch nach der Wiederherstellung eines älteren Backups
- Die Middleware lädt bei jeder Anfrage den Benutzer: Deaktivieren, Löschen, Rollen- und
  Passwortänderung wirken sofort (token_version im Token). Alte Tokens ohne Benutzer-ID bleiben
  gültig, bis sich am Benutzer etwas ändert — niemand wird durch das Update abgemeldet
- backend/permissions.py: die einzige Stelle mit den Rechten. Lesen darf jeder außer
  Einstellungen/Benutzer/Backup/Proxmox; Operator darf scannen, Updates starten, neu starten,
  Scripts ausführen, Snapshots löschen, Doku bearbeiten; alles andere — auch jeder neue
  Endpunkt — ist nur für Admins. Scripts anlegen/bearbeiten bleibt admin-only (root auf allen
  Servern)
- Login ohne Rücksicht auf Groß-/Kleinschreibung, /api/auth/me mit Rolle, eigene Zugangsdaten
  ändern für jede Rolle (mind. 8 Zeichen, andere Sitzungen werden abgemeldet, die aktuelle
  bekommt ein neues Token)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Benutzer auflisten (alphabetisch), anlegen (Name, Passwort mind. 8 Zeichen, Rolle),
  umbenennen, Rolle ändern, deaktivieren/aktivieren, Passwort zurücksetzen, löschen
- Benutzernamen eindeutig ohne Rücksicht auf Groß-/Kleinschreibung
- Rolle, Aktivierung oder Passwort geändert -> offene Sitzungen des Benutzers enden sofort
- Schutz vor dem Aussperren: der letzte aktive Admin lässt sich weder löschen noch
  deaktivieren noch herabstufen; das eigene Konto lässt sich nicht löschen und die eigene
  Rolle/Aktivierung nicht ändern
- Passwort-Hashes verlassen nie das Backend

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Einstellungen → Sicherheit:
- "Eigenes Konto": Name/Passwort ändern für jede Rolle; das neue Token aus der Antwort wird
  übernommen (das alte ist nach einer Passwortänderung ungültig), Mindestlänge 8
- "Benutzer" (nur Admins): Liste mit Rolle, Status und letztem Login, Rolle und Aktivierung
  direkt änderbar, Passwort zurücksetzen, löschen, neuen Benutzer anlegen, kurze Erklärung
  der Rollen. Beim eigenen Konto sind Rolle/Aktivierung/Löschen gesperrt

Oberfläche nach Rolle (entschieden wird weiterhin im Backend, hier werden nur Schaltflächen
ausgeblendet):
- Nur-Lesen: alles ansehen; in den Einstellungen nur "Sicherheit"
- Operator: zusätzlich scannen, Updates/Neustarts starten, Scripts ausführen, SSH testen,
  Snapshots löschen, Doku bearbeiten
- Admin: zusätzlich Server/Scripts/Zeitpläne anlegen und ändern, alle Einstellungen, Hinweis
  "Update verfügbar"
- Seitenleiste zeigt die Rolle; beim An- und Abmelden wird der Zwischenspeicher geleert, damit
  niemand kurz Rolle/Daten des vorigen Benutzers sieht
- Einstellungen rendern erst, wenn die Rolle bekannt ist; Admin-Kategorien leiten
  Nicht-Admins zu "Sicherheit" um

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Neue Seite docs/Benutzer-und-Rollen.md: die drei Rollen und was sie dürfen, Benutzer verwalten,
Schutz vor dem Aussperren, eigenes Konto, Umstieg vom Einzel-Login, Passwort vergessen (auch
als einziger Admin). Verweise aus README, docs/README.md, Installation und Backup; in der
Entwicklerdoku permissions.py (jeder neue Endpunkt ist automatisch admin-only), AppUser,
users-Router und Endpunkte.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Die Suche auf der Scripts-Seite durchsucht jetzt neben Name und Beschreibung auch die Namen
der Zielserver. Scripts mit Ziel "alle Server" passen zu jedem Servernamen (wie der
Server-Filter daneben) und zu "alle"; mehrere Wörter müssen alle vorkommen, Groß-/
Kleinschreibung spielt keine Rolle.

parseTargetServers() liegt dafür mit der Suche in lib/scriptSearch.ts (Test umgezogen) —
nebenbei verschwindet eine react-refresh-Warnung in Scripts.tsx.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Liegt eine Installation ein paar Commits nach einem Release-Tag (z.B. frisch vom Branch
geklont), lautet ihre Version etwa "1.1.5-beta.6-3-g1a2b3c4". Das verstand die Update-Prüfung
nicht — solche Installationen zeigten nie "Update verfügbar" an. Der Anhang "-N-g<hash>"
(und "-dirty") zählt jetzt wie der Tag davor, im Backend und bei der Downgrade-Anzeige im
Frontend.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Docker-Weg (Debian und Ubuntu):
- git wird in Schritt 1 mitinstalliert — Schritt 3 klont das Repository, auf frischen
  Debian-Systemen und LXC-Vorlagen fehlte git und die Installation brach ab
- Ubuntu Schritt 6: derselbe Hinweis auf "Benutzer und Rollen" wie bei Debian

Weg ohne Docker, komplett neu und auf frischem Debian 13 durchgespielt:
- Voraussetzung Debian 13 oder Ubuntu 24.04 (Python 3.12+), Hinweis für Debian 12
- Pakete inklusive python3-venv, Node.js 22 aus NodeSource (die Distributionen liefern ältere)
- eigener Dienstbenutzer patchpilot, dem /opt/patchpilot gehört — vorher lief der Dienst als
  www-data ohne Schreibrechte und konnte weder die Datenbank anlegen noch sich aktualisieren
- VERSION wird geschrieben — ohne sie meldete PatchPilot 0.0.0-dev und erkannte nie ein Update
- für Debian und Ubuntu identisch dank runuser, Installation als eine Zeile
- systemd-Unit mit User/Group patchpilot, Restart=always
- Umstellung älterer Installationen mit User=www-data

Selbst-Update.md: Voraussetzungen für Bare-Metal an den Dienstbenutzer angepasst.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
AxonByteDev/PatchPilot!20
No description provided.