Hintergrund-Wissen für Mods, die verstehen wollen, wie Rechte vergeben sind und wo die App technisch aufsetzt.
Architektur in einem Bild
Browser
│
│ HTTP/JSON
▼
FastAPI Backend
│
├─ SQLite (App-Cache)
│ - idea, topic, taxonomy_event, taxonomy_phase
│ - activity_log, idea_report, idea_interaction
│ - ranking_snapshot, user_feed_seen
│
└─ HTTP Basic Auth (User-Auth wird durchgereicht)
│
▼
edu-sharing REST (Source of Truth)
- ccm:io, ccm:map, ccm:io_reference
- Permissions / Memberships / Groups
- Ratings, Comments, Anhänge
Wichtigste Regel: edu-sharing ist die einzige verbindliche Datenquelle. Die App-DB ist nur ein Performance-Cache + Speicher für app-spezifische Zusätze (Mitmachen, Folgen, Reports, Versteckt-Flag, Aktivitäts-Log).
Wie wird Mod-Status erkannt?
Im Backend prüft _is_moderator() pro Request:
-
Bootstrap-Whitelist — Usernames aus der
MODERATION_BOOTSTRAP_USERS- Env-Variable. Default leer. Sinnvoll als Notfall-Liste, damit du dich nie aussperrst. -
Group-Mitgliedschaft — User wird in edu-sharing als Mitglied einer der
MODERATION_FALLBACK_GROUPSgeführt. DefaultGROUP_ALFRESCO_ADMINISTRATORS.
Wenn eine der beiden Bedingungen zutrifft → Mod.
Gruppen-Mitgliedschaft prüfen
API-Endpoint:
GET /api/v1/me/memberships
Authorization: Basic …
Antwort zeigt deine ES-Gruppen + welche davon als Mod-Gruppe konfiguriert sind.
Mod-Konfiguration ändern
Im .env:
# Beide Beispiele zusammen — User darf in jeder der Gruppen sein
MODERATION_FALLBACK_GROUPS=GROUP_xxx_ORG_ADMINISTRATORS,GROUP_ALFRESCO_ADMINISTRATORS
# Bootstrap-User: Komma-Liste von Login-Usernames
MODERATION_BOOTSTRAP_USERS=
Nach Änderung Container/Backend-Prozess neu starten (Env wird nur beim Start gelesen).
Mod werden / aussteigen
Mod-Verwaltung läuft direkt in edu-sharing, nicht über die App. Im Mod-Tab „Moderatoren" siehst du nur lesend die Mitglieder, kannst keine hinzufügen oder entfernen — das wäre eine globale ACL-Änderung in einer Admin-Gruppe und ist bewusst nicht in der App exponiert.
Wenn jemand Mod werden soll:
-
ES-Admin öffnet
https://redaktion.openeduhub.net/edu-sharing/ -
Navigiert zur konfigurierten Mod-Gruppe (z.B.
GROUP_xxx_ORG_ADMINISTRATORS) -
User als Mitglied hinzufügen
Beim nächsten Login des Users greift die App-Mod-Erkennung sofort.
ACLs am Knoten
Jeder ES-Knoten (ccm:io, ccm:map) hat eine ACL mit:
|
Permission |
Bedeutung |
|---|---|
|
Consumer |
Lesen, Vorschau, Download |
|
Editor |
Metadaten ändern |
|
Collaborator |
Editor + Kinder anlegen |
|
Coordinator |
Voll-Admin auf diesem Knoten (ACL ändern, löschen) |
ACLs werden vererbt, können aber per-Knoten überschrieben werden.
Wer hat Mod-Rechte auf den Mod-Aktionen?
Die App-Endpoints, die Mod-Rechte verlangen (@_require_moderator), prüfen nur den App-Mod-Status. Aber dahinter ruft die App edu-sharing-APIs auf (z.B. addReference, delete_node). Wenn der Caller im ES keine ACL-Write am Ziel-Knoten hat → 403 von ES, App reicht den Fehler weiter.
Vereinfacht:
-
App-Mod-Status = darfst die UI-Aktion auslösen
-
ES-ACL = darfst die ES-Aktion tatsächlich ausführen
Für die HackathOERn-Sammlungen sind beide Permissions an den Mod-Gruppen gehängt — solange du in der konfigurierten Gruppe bist, klappt beides.
Tool-Permissions (Repository-Konfig)
Eine dritte Schicht auf Repository-Niveau: bestimmte API-Calls brauchen zusätzliche Tool-Permissions, die der Repo-Admin in der ES-Admin-Konsole freischaltet.
Wichtigste für unsere App:
|
Tool-Permission |
wofür |
|---|---|
|
|
|
|
|
Schreibzugriff aufs Home-Verzeichnis |
|
|
Andere User einladen / Gruppen-Mitglieder hinzufügen |
Symptome wenn Tool-Permission fehlt:
-
403
DAOToolPermissionException(für Mods) -
403
DAOSecurityException(für Guests / Standard-User)
→ Lösung: ES-Admin muss die Tool-Permission für die HackathOERn-Mod-Gruppe in der Admin-Konsole aktivieren. Kann nicht via App-UI gefixt werden.
Submit-Mechanismus
|
Fall |
Pfad |
|---|---|
|
Anonymer Submit |
App → Backend → mit Guest-Account ( |
|
Authentifizierter Submit |
App → Backend → mit User-Auth in die Inbox schreiben → User wird Owner |
In beiden Fällen entsteht ein neuer ccm:io direkt unter der konfigurierten Inbox-Sammlung (EDU_GUEST_INBOX_ID).
Reference-Pattern (Kern-Architektur)
Beim Einsortieren ins Sammlungs-Tree:
1. Original liegt in Inbox ─────► 98fcbe56...
│
│ addReference
▼
2. Reference-Knoten in Sammlung X ──► d671abfc... (Challenge)
mit originalId = <Inbox-Knoten>
Vorteile des Pattern:
-
Inhalt nur an EINER Stelle (Inbox)
-
Mehrere Sammlungen können denselben Inhalt referenzieren
-
Edits am Original sind sofort überall sichtbar
-
ACLs bleiben stabil (keine Move-Inheritance-Drift)
Die App nutzt Reference-only — kein _move-Fallback. Wenn addReference mit 403 abgelehnt wird, geht's nicht weiter. Dafür ist die Tool-Permission auf Repo-Niveau die Ursache.
Inbox-Owner-Tracking
ccm:creator ist immer der Account, der den POST gemacht hat — also bei anonymen Submits der Guest-Account.
Für die App-Sicht „wer ist Owner dieser Idee, darf bearbeiten" gibt's einen Zusatz-Mechanismus:
-
Bei eingeloggten Submits wird
submitter:<username>-Keyword als Schlagwort anscclom:general_keywordangehängt -
Die App liest beim Owner-Check zuerst
submitter:-Marker, danncm:creator -
Owner-Edit-Gating prüft:
_is_owner_or_mod(idea_id, auth)→ owner = match von User mit Submitter ODER Creator
Geisterzeilen-Cleanup im Sync
Wenn ein Inbox-Original irgendwo referenziert wird (= original_id einer Reference-Row), gehört es nicht mehr in den Public-Cache. Beim Sync-Lauf:
DELETE FROM idea WHERE id IN (
SELECT original_id FROM idea WHERE original_id IS NOT NULL
);
Räumt die Inbox-Originale automatisch aus der Listen-Sicht.
Auth-Failed-Audit
Jeder fehlgeschlagene Mod-Endpoint-Aufruf wird im Activity-Log als auth_failed notiert. Mods können im Aktivitäts-Tab nach Spitzen schauen (Brute-Force-Versuche).
Datenflüsse im Überblick
Aktion Wo geschrieben Wo geslesen
────── ───────────── ───────────
Idee einreichen ES (Inbox) Backend-Sync → App-Cache
Idee bearbeiten ES (Original) refresh_idea → App-Cache
Sammlung erstellen ES Sync → App-Cache
Reference setzen ES Sync + refresh
Idee verstecken App-DB (hidden=1) App-DB
Idee löschen ES (delete) Sync entfernt aus Cache
Kommentar ES (/comment/v1) get_idea-Antwort
Rating ES (/rating/v1) get_idea-Antwort
Mitmachen/Folgen App-DB App-DB
Meldung App-DB App-DB
Activity-Log App-DB App-DB
Backup ZIP in /data/backups App-UI
edu-sharing-Begriffsmodell
Für tiefere Recherche / Repo-Inspektion:
|
ES-Typ |
Bedeutung |
App-Entsprechung |
|---|---|---|
|
|
Inhalts-Knoten (Lerninhalt) |
„Idee" |
|
|
Referenz auf einen ccm:io |
„Idee in Sammlung" |
|
|
Container (Sammlung/Ordner) |
„Topic" / „Herausforderung" |
|
|
User-Knoten |
App-User |
|
|
Gruppe oder User |
für ACLs |
→ Zurück zur Mod-Übersicht · → Benutzerhandbuch