Menü Projekt-Berechtigungen, Übersichtssichten und AppAdmin-Erkennung

- Menü: Dropdown "Projekt-Berechtigungen" unter Optionen mit
  Unterpunkten "Projekt-Zugriffe" und "Nutzer-Zugriffe" (nur SysAdmin/AppAdmin)
- AppAdmin-Erkennung: Server liefert isAppAdmin-Flag im Login- und
  getusers-Response (applikationsspezifisch via has_permission)
- Login: CurrentUserIsAppAdmin in sessionStorage speichern/entfernen
- Projekt-Zugriffe: geschachtelter Treetable (Projekt → Nutzer) als
  reine Anzeige, Detail-Sicht aus Projekt-Maske mit Bearbeitung
- Nutzer-Zugriffe: neue Komponente user_projektliste.ts, geschachtelter
  Treetable (Nutzer → Projekte), reine Anzeige
- Server: neuer Endpunkt GET /xhr/projektuser/listall (nur AppAdmin/SysAdmin)
- Server: get_all_projekt_users() mit Batch-Query für Projekte und User
- Treetable-Widget: Platzhalter-Pfeil bei kinderlosen Nodes nur wenn
  Geschwister mit Kindern existieren (hasSiblingsWithChildren)
- Datei projekt_user.ts umbenannt in projekt_userliste.ts (konsistent
  mit user_projektliste.ts)

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
gg committed 2026-09-07 16:04:06 +02:00
1 parent 505177b5e2
commit 9ed5e88e01
10 files changed
+693 -82

No files matched your search

+42
View File
@@ -165,3 +165,45 @@ def is_user_assigned(projekt_id: int, user_id: int) -> bool:
ProjektUser.user_id == user_id,
).first()
return zuordnung is not None
def get_all_projekt_users():
"""
Liefert alle Projekt-User-Zuordnungen, angereichert mit projektname
(aus Projekt-Relationship) sowie userid, username und email (aus
Auth-DB via Batch-Query).
Wird für die Übersichtssicht "Nutzer-Zugriffe" verwendet, in der alle
Zuordnungen in einem Aufruf geladen werden.
"""
zuordnungen = ProjektUser.query.all()
if not zuordnungen:
return []
# Projekte und Nutzer in jeweils einer Batch-Query auflösen.
projekt_ids = list({z.projekt_id for z in zuordnungen})
user_ids = list({z.user_id for z in zuordnungen})
projekte = Projekt.query.filter(Projekt.id.in_(projekt_ids)).all()
projekt_map = {p.id: p for p in projekte}
users = User.query.filter(User.id.in_(user_ids)).all()
user_map = {u.id: u for u in users}
result = []
for z in zuordnungen:
eintrag = z.to_dict()
projekt = projekt_map.get(z.projekt_id)
eintrag['projektname'] = projekt.projektname if projekt else ""
user = user_map.get(z.user_id)
if user is not None:
eintrag['userid'] = user.userid
eintrag['username'] = user.username
eintrag['email'] = user.email or ""
else:
eintrag['userid'] = ""
eintrag['username'] = ""
eintrag['email'] = ""
result.append(eintrag)
return result