> [← open.SERVICE v2](<Überblick.md>) # Berechtigungen ## Drei Ebenen **1 · Mandantentrennung.** Je `OD3_Service_*`-Klasse ein Server-Hook, der `tenant` setzt, den Ersteller einträgt und die Rollen-ACL schreibt. Für **Wartungspläne und Vorlagen** bekommt die allgemeine Mandanten-Rolle dabei kein Leserecht: ein Plan ist nicht mandantenweit sichtbar, sondern nur für die, die an ihm hängen. Es gibt kein `beforeFind` — Sichtbarkeit hängt vollständig an der ACL des jeweiligen Objekts. **2 · Capabilities** (`OD3_Permission`). Sie beantworten „darf jemand *so etwas*" und werden beim Serverstart je Mandant registriert. `usePermission` ist strikt: ist ein Key nicht registriert **und** einer Rolle zugewiesen, blendet sich die Aktion aus. **3 · ACL je Datensatz.** Sie beantwortet „darf jemand *diesen* Plan" und wird bei jedem Speichern aus Ersteller und Zuweisungen neu abgeleitet. Eine entzogene Zuweisung wirkt damit sofort. ## Der Katalog | Key | Zweck | | --------------------------------------------------- | ----------------------------------------------------- | | `openservice-schedule:can-access-schedule-plugin` | Zugang zum Wartungsmodul (Routen und Menü) | | `openservice-schedule:can-create-schedule` | Plan anlegen | | `openservice-schedule:can-delete-schedule` | Plan archivieren | | `openservice-schedule:can-perform-execution` | Durchführung | | `openservice-schedule:can-manage-template` | Vorlagenkatalog | | `service:can-read-ticket` | Tickets sehen | | `service:can-create-ticket` | Tickets anlegen | | `service:can-edit-ticket` | Tickets bearbeiten | | `service:can-delete-ticket` | Tickets löschen | | `service:can-assign-ticket` | Tickets zuweisen | | `service:can-manage-masterdata` | Stammdaten | | `service:can-manage-formconfig` | Ticketformulare | | `service:can-create-tag` | Tag aus einem Tag-Feld heraus anlegen | | `service:can-view-analytics` | Auswertungen | **Zwei Namensräume.** Die Wartungs-Keys tragen den Präfix `openservice-schedule:`, alles modulübergreifend Geteilte bleibt bei `service:`. Der Präfix ist zugleich der i18n-Namespace, unter dem die Rechteverwaltung Label und Beschreibung eines Keys sucht. Wer einen Key hinzufügt oder umbenennt, fasst Server-Enum, Frontend-Katalog und die Übersetzungsdateien gemeinsam an. **Jede Route und jeder Menüeintrag des Wartungsmoduls hängt an `can-access-schedule-plugin`.** Fehlt der Key, existiert das Modul für diesen Benutzer nicht. > [!info] Es gibt kein `can-read-schedule` und kein `can-edit-schedule` > Beide würden eine Frage beantworten, die schon die ACL beantwortet — und zwar > **pro Datensatz**, während eine Capability nur global antworten kann. Sie > widersprächen sich in dem Moment, in dem jemand einem Plan zugewiesen wird, ohne > die Capability zu halten: das UI würde sperren, was der Server erlaubt. > > `create` bleibt eine Capability, weil es beim Anlegen noch keinen Datensatz > gibt, dessen ACL man fragen könnte. ## Wer einen Plan sieht Die ACL, die der Server schreibt: | Wer | Woher | Recht | | -------------------------------------- | --------------------------------------- | ----- | | Ersteller | `user` (server-gesetzt, unveränderlich) | r + w | | `od-admin`, `od-tenant-admin-<tenant>` | immer | r + w | | `assignedRoles`, `escalationRoles` | Rollen-Relation am Plan | r | | `assignedUsers` | User-Relation am Plan | r | Gebaut wird sie serverseitig im `afterSave` — Relationen sind erst nach dem Speichern lesbar. Sie wird bei jedem Lauf **neu gebaut, nicht ergänzt**: eine ACL merkt sich nicht, *warum* ein Grant besteht, und Ergänzen wäre eine Einbahnstraße — eine vom Plan entfernte Rolle würde ihn für immer weiterlesen. Administratoren kommen in jedem Fall wieder dazu; aussperren lassen sie sich nicht. **Bearbeiten fragt die ACL, nicht die Capability.** Im Frontend ist `schedule.readonly` die Bedingung für Bearbeiten, Verschieben und Archivieren; nur das Archivieren prüft zusätzlich `can-delete-schedule`. Der Dialog **„Sichtbarkeit prüfen"** im Aktionsmenü liest die ACL und nicht die Zuweisungen: gezeigt wird, was der Server durchsetzt. Administrator-Grants sind ausgeblendet, weil sie auf jedem Datensatz stehen. > [!note] Eine Zuweisung gibt Leserecht, kein Schreibrecht > Wer einem Plan zugewiesen ist, kann ihn ansehen und abarbeiten, aber nicht > ändern. Schreiben darf der Ersteller — und Administratoren. ## Löschen Das Löschen eines Plans prüft serverseitig `can-delete-schedule`. Das ist nötig, weil ein ACL-`write` in Parse Ändern **und** Löschen abdeckt — ein ausgeblendeter Knopf allein genügt dafür nicht. Derselbe Hook verweigert das Löschen eines Plans, zu dem Durchführungen existieren, damit kein Protokoll ins Leere zeigt. Dafür gibt es das Archivieren über `deletedAt`.