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>
This commit is contained in:
@@ -101,66 +101,84 @@ Die App ermöglicht:
|
||||
|
||||
## Rechtesystem (Gruppen & Berechtigungen)
|
||||
|
||||
Admins dürfen wie bisher alles, inklusive Benutzer-/Gruppen-/
|
||||
Settingsverwaltung — das bleibt exklusiv Admins vorbehalten. Zusätzlich gibt
|
||||
es **Gruppen**: eine Gruppe bündelt einzelne Verwaltungsrechte, die dann
|
||||
normalen Benutzern zugewiesen werden können, ohne sie zu Admins zu machen.
|
||||
Ein Benutzer kann nur einer Gruppe/Rolle gleichzeitig zugeordnet sein
|
||||
(über den Button „Gruppe zuweisen“, analog zur Switch-Zuordnung bei
|
||||
Devices) — technisch sind mehrere Gruppen pro Benutzer möglich (Rechte
|
||||
würden sich addieren), die UI bildet aber bewusst nur eine 1:1-Zuordnung ab.
|
||||
Admins dürfen immer alles. Zusätzlich gibt es **Gruppen** mit einem
|
||||
**vollständig granularen, an der Navbar gespiegelten Rechtebaum** — jeder
|
||||
Bereich der App (nicht nur Devices/Switches) lässt sich einzeln freischalten.
|
||||
Ein Benutzer kann mehreren Gruppen angehören, die Rechte addieren sich
|
||||
(Vereinigung, nicht Schnittmenge).
|
||||
|
||||
Auf der **Gruppen**-Seite (nur für Admins) werden zur Übersicht immer auch
|
||||
die beiden Systemrollen mit aufgeführt:
|
||||
- **Admin** — eine feste, nicht editierbare Zeile mit allen Rechten;
|
||||
Mitgliedschaft wird direkt hier verwaltet (Button „Mitglieder verwalten“),
|
||||
intern über den `is_admin`-Schalter der Benutzer. Mindestens ein Admin
|
||||
muss immer bestehen bleiben (serverseitig erzwungen).
|
||||
- **Benutzer** — die **Standardgruppe**, mit der alle Ansichtsrechte
|
||||
(`devices.view`, `switches.view`) vorbelegt sind. Jeder neu angelegte,
|
||||
nicht-admin Benutzer wird ihr automatisch zugeordnet; sie kann nicht
|
||||
gelöscht werden.
|
||||
### Zweistufiger Rechtebaum
|
||||
|
||||
Jede Gruppe lässt sich über „Rechte anzeigen/bearbeiten“ aufklappen (wie ein
|
||||
Akkordeon) und zeigt dort die volle Checkbox-Liste; Mitglieder werden über
|
||||
einen eigenen Button/Modal verwaltet (nur die Anzahl steht in der Tabelle).
|
||||
Der Baum hat genau zwei Ebenen, exakt gespiegelt an den drei Sidebar-Gruppen:
|
||||
|
||||
Verfügbare Rechte:
|
||||
```
|
||||
Geräte (devices_group.view — Bereich an/aus)
|
||||
├─ Clients Lesen · Schreiben (Anlegen) · Ändern (inkl. Akt./Deakt.) · Löschen · PoE-Neustart
|
||||
├─ Switche Lesen · Schreiben · Ändern · Löschen
|
||||
└─ Zugangsdaten Lesen · Schreiben · Ändern · Löschen
|
||||
Logs (logs_group.view — Bereich an/aus)
|
||||
├─ Live Lesen
|
||||
└─ Änderungen Lesen
|
||||
Einstellungen (settings_group.view — Bereich an/aus)
|
||||
├─ Benutzer Lesen · Schreiben · Ändern · Löschen
|
||||
├─ Gruppen Lesen · Schreiben · Ändern · Löschen
|
||||
├─ Systemeinstellungen Lesen · Ändern
|
||||
└─ Im-/Export Lesen (Export) · Ändern (Import)
|
||||
```
|
||||
|
||||
| Bereich | Recht | Bedeutung |
|
||||
|----------|---------------------|-----------------------------------------------|
|
||||
| Devices | `devices.view` | Devices-Seite ansehen |
|
||||
| Devices | `devices.toggle` | Geräte aktivieren/deaktivieren |
|
||||
| Devices | `devices.create` | Geräte anlegen |
|
||||
| Devices | `devices.edit` | Geräte bearbeiten (inkl. Switch-Zuordnung) |
|
||||
| Devices | `devices.delete` | Geräte löschen |
|
||||
| Devices | `devices.restart` | PoE-Neustart/Aktivieren über das Dashboard |
|
||||
| Switches | `switches.view` | Switches- und Zugangsdaten-Seite ansehen |
|
||||
| Switches | `switches.create` | Switche und Zugangsdaten anlegen |
|
||||
| Switches | `switches.edit` | Switche und Zugangsdaten bearbeiten |
|
||||
| Switches | `switches.delete` | Switche und Zugangsdaten löschen |
|
||||
Das jeweilige „Bereich an/aus“-Recht (`devices_group.view` /
|
||||
`logs_group.view` / `settings_group.view`) wirkt als **Kill-Switch**: ist es
|
||||
für eine Gruppe nicht gesetzt, greift kein einziges Recht darunter mehr —
|
||||
selbst wenn z.B. `devices.view` einzeln noch angehakt ist. So lässt sich ein
|
||||
ganzer Bereich mit einem Klick sperren, ohne jedes Unterrecht einzeln
|
||||
zurücknehmen zu müssen (`User.has_permission()` in `app.py`).
|
||||
|
||||
Sowohl das Anzeigen der Devices-/Switches-Seiten als auch jede einzelne
|
||||
Aktion (Buttons, Toggle-Switches, Formulare) ist an das jeweilige Recht
|
||||
gekoppelt — im Frontend ausgeblendet **und** im Backend serverseitig
|
||||
durchgesetzt, unabhängig vom Frontend.
|
||||
Auf der **Gruppen**-Seite wird der Baum als Akkordeon pro Gruppe angezeigt:
|
||||
eine Zeile pro Top-Level-Bereich mit eigenem Kästchen, darunter eingerückt
|
||||
die Unterpunkte mit ihren Einzelrechten — ohne den Bereichsnamen in jedem
|
||||
Unterpunkt zu wiederholen.
|
||||
|
||||
**Bewusst ohne granulare Rechte, exklusiv Admins vorbehalten:** Benutzer,
|
||||
Gruppen, Systemeinstellungen (Prüfintervall), Im-/Export, Änderungslog,
|
||||
Live-Log und der manuelle „Jetzt prüfen“-Trigger. Für diese Bereiche gibt es
|
||||
keine sinnvolle Teilmenge unterhalb von „Admin“ — Gruppenverwaltung steuert
|
||||
direkt das Rechtesystem selbst (Delegation wäre eine Privilegien-Eskalation),
|
||||
Systemeinstellungen/Import-Export/manuelle Prüfung wirken sich global aus,
|
||||
und das Änderungslog protokolliert alle Benutzer systemweit. Live-Log und
|
||||
`/get_log` waren zwischenzeitlich nur über `@login_required` statt echter
|
||||
Admin-Prüfung abgesichert (die Sidebar blendete den Punkt zwar korrekt aus,
|
||||
die Route selbst nicht) — inzwischen serverseitig nachgezogen.
|
||||
### Systemgruppen
|
||||
|
||||
Datenmodell: `groups` (inkl. `is_default`-Flag), `group_permissions`
|
||||
(Gruppe → Recht), `user_groups` (Benutzer → Gruppe). Bestehende Datenbanken
|
||||
werden beim App-Start automatisch migriert (`_ensure_schema()` in `app.py`,
|
||||
inkl. Nachrüsten der Standardgruppe und Zuordnung bestehender Benutzer ohne
|
||||
Gruppe) — kein manuelles Migrations-Skript nötig.
|
||||
Zwei Gruppen sind fest und **weder umbenennbar noch in ihren Rechten
|
||||
änderbar** (auch nicht durch Admins über die UI) — Mitgliedschaft bleibt bei
|
||||
beiden frei verwaltbar:
|
||||
- **Admin** — virtuell (kein echter `groups`-Datensatz), intern über den
|
||||
`is_admin`-Schalter der Benutzer gesteuert, immer alle Rechte. Mindestens
|
||||
ein Admin muss bestehen bleiben (serverseitig erzwungen).
|
||||
- **Benutzer** — die Standardgruppe (`is_system`-Flag), der jeder neu
|
||||
angelegte Nicht-Admin automatisch zugeordnet wird. Fester Rechtesatz:
|
||||
Geräte-Bereich + Clients/Switche lesen, Logs-Bereich + Live-Log lesen.
|
||||
|
||||
Alle anderen Gruppen sind vom jeweiligen Rechteinhaber (`groups.edit` bzw.
|
||||
`groups.create`/`groups.delete`) frei konfigurierbar.
|
||||
|
||||
### Eskalationsschutz
|
||||
|
||||
Da jetzt auch **Benutzer-** und **Gruppenverwaltung** delegierbar sind (z.B.
|
||||
eine Gruppe mit nur `users.edit`, ohne Admin zu sein), gelten zusätzlich zu
|
||||
den granularen Rechten diese fest einprogrammierten Schranken, unabhängig
|
||||
davon, was eine Gruppe an Rechten hat:
|
||||
- Ein Benutzer als Admin anlegen/dazu machen (`group_id=admin` bei
|
||||
Anlegen/Zuweisen) bleibt echten Admins vorbehalten.
|
||||
- Ein bestehendes Admin-Konto bearbeiten, löschen oder ihm die Gruppe ändern
|
||||
bleibt echten Admins vorbehalten.
|
||||
- Wer Admin ist, wird ausschließlich über „Admin-Mitglieder verwalten“ auf
|
||||
der Gruppen-Seite gesteuert — bleibt admin-exklusiv, unabhängig von
|
||||
`groups.edit`.
|
||||
|
||||
Sowohl das Anzeigen jeder Seite als auch jede einzelne Aktion (Buttons,
|
||||
Formulare) ist an das jeweilige Recht gekoppelt — im Frontend ausgeblendet
|
||||
**und** im Backend serverseitig durchgesetzt, unabhängig vom Frontend.
|
||||
|
||||
Datenmodell: `groups` (inkl. `is_default`- und `is_system`-Flag),
|
||||
`group_permissions` (Gruppe → Recht), `user_groups` (Benutzer → Gruppe).
|
||||
Bestehende Datenbanken werden beim App-Start automatisch migriert
|
||||
(`_ensure_schema()` in `app.py`, u.a. `devices.toggle` → `devices.edit`,
|
||||
`switches.*` → gespiegelte `credentials.*`, nachträgliches Setzen der neuen
|
||||
Bereichs-Rechte für bereits vergebene Unterrechte) — läuft **nur einmalig**
|
||||
über einen Guard in der `settings`-Tabelle, damit ein bewusst deaktiviertes
|
||||
Bereichs-Recht nicht bei jedem Neustart automatisch wieder gesetzt wird.
|
||||
|
||||
## Zugangsdaten (wiederverwendbare SSH-Logins)
|
||||
|
||||
@@ -179,7 +197,7 @@ am Switch) werden beim ersten Start automatisch migriert.
|
||||
Jede Anlage, Bearbeitung, Löschung sowie jedes Aktivieren/Deaktivieren von
|
||||
Geräten, Switchen, Zugangsdaten, Benutzern und Gruppen wird in der Tabelle
|
||||
`audit_log` protokolliert (Zeitpunkt, Benutzer, Aktion, Ziel, Details) —
|
||||
einsehbar unter **Logs → Änderungslog** (nur für Admins). Zusätzlich merken
|
||||
einsehbar unter **Logs → Änderungen** (Recht `logs_activity.view`). Zusätzlich merken
|
||||
sich Geräte und Switche direkt am Datensatz (`last_modified_by`,
|
||||
`last_modified_at`), wer sie zuletzt geändert hat, damit man das nicht erst
|
||||
im Log nachschlagen muss.
|
||||
|
||||
Reference in New Issue
Block a user