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>
This commit is contained in:
2026-08-11 09:52:01 +02:00
co-authored by Claude Sonnet 5
parent 8e4a874943
commit 7d7239e1af
6 changed files with 172 additions and 91 deletions
+24 -2
View File
@@ -268,6 +268,18 @@ for _group in PERMISSIONS.values():
ALL_PERMISSION_KEYS.append(_key)
PERMISSION_PARENT_GROUP[_key] = _group["view_key"]
# Welche Spalten (R/W/E/D) für einen Bereich überhaupt vorkommen — z.B. hat
# nur "Geräte" (wegen Clients' Dashboard-Neustart) eine D-Spalte, Logs/
# Einstellungen brauchen sie gar nicht erst anzuzeigen. Auf der Gruppen-
# Seite bekommt so jeder Bereich nur die Spalten, die er tatsächlich nutzt,
# statt überall gleich viele (teils komplett ungenutzte) Spalten zu zeigen.
GROUP_ROW_TYPES = {}
for _group_key, _group in PERMISSIONS.items():
_used_row_keys = {"view"}
for _child in _group["children"].values():
_used_row_keys.update(_child["rows"].keys())
GROUP_ROW_TYPES[_group_key] = [rt for rt in PERMISSION_ROW_TYPES if rt[0] in _used_row_keys]
DEFAULT_GROUP_NAME = "Benutzer"
DEFAULT_GROUP_PERMISSIONS = [
"devices_group.view", "devices.view", "switches.view",
@@ -2738,9 +2750,18 @@ def groups():
name = request.form.get("name", "").strip()
if name:
try:
conn.execute("INSERT INTO groups (name) VALUES (?)", (name,))
cur = conn.execute("INSERT INTO groups (name) VALUES (?)", (name,))
# Rechte direkt beim Anlegen setzbar (dieselbe Tabelle wie
# beim Bearbeiten, hier ohne eigenes "_submitted"-Flag, da
# eine neue Gruppe ohnehin noch keine Rechte hat).
selected_permissions = set(request.form.getlist("permissions")) & set(ALL_PERMISSION_KEYS)
if selected_permissions:
conn.executemany(
"INSERT INTO group_permissions (group_id, permission) VALUES (?, ?)",
[(cur.lastrowid, p) for p in selected_permissions],
)
conn.commit()
log_action("group.create", name)
log_action("group.create", name, f"{len(selected_permissions)} Rechte" if selected_permissions else None)
flash(f"Gruppe '{name}' angelegt.", "success")
except sqlite3.IntegrityError:
flash("Eine Gruppe mit diesem Namen existiert bereits!", "danger")
@@ -2906,6 +2927,7 @@ def groups():
all_users_all=all_users_all,
permission_catalog=PERMISSIONS,
permission_row_types=PERMISSION_ROW_TYPES,
group_row_types=GROUP_ROW_TYPES,
permission_labels=PERMISSION_LABELS,
)