Rollen und Rechte
Kurzantwort: Rechte greifen auf drei Ebenen: Modell (welche Rolle für
welche Operation), Feld (Feldrollen) und Zeile (Owner-Filter und
Attributfilter). Die Modellrollen kommen aus @AccessByRole und werden gegen
die Client-Rollen des Tokens geprüft. Ist keine Rolle gesetzt, ist die Operation
frei.
Die drei Ebenen
Abschnitt betitelt „Die drei Ebenen“flowchart TB
R["Request"] --> M{"Modellrolle vorhanden<br/>und im Token?"}
M -->|nein und Strict| E403["403 missing-permission"]
M -->|nein und tolerant| SKIP["Operation liefert nichts / false"]
M -->|ja| F["Feldrollen: welche Felder<br/>lesbar/schreibbar sind"]
F --> Z["Zeilenfilter:<br/>_userId (Owner)<br/>+ Attributfilter"]
Z --> DB[(Daten)]
Ebene 1 – Modellrollen
Abschnitt betitelt „Ebene 1 – Modellrollen“@AccessByRole(onCreate = "crm/customer-create", onRead = "crm/customer", onUpdate = "crm/customer-update", onDelete = "crm/customer-delete", onDownload = "", onHistory = "", onRollback = "")Geprüft wird in AbstractAuthorizationLayer gegen
RequestContext.getEffectiveUserRoles() – das sind die Client-Rollen aus
resource_access.<cias_client>.roles.
| Prüfmethode | Operation | Fehler bei fehlender Rolle |
|---|---|---|
createAccessAllowedByClass | Create | missing-create-role bzw. missing-permission|<rolle> |
readAccessAllowedByClass | Read/Query | missing-permission|<rolle> |
updateAccessAllowedByClass | Update/Patch | missing-update-role |
deleteAccessAllowedByClass | Delete | missing-permission|<rolle> |
downloadAccessAllowedByClass | Dateidownload | missing-permission|<rolle> |
historyAccessAllowedByClass | Historie lesen | missing-permission|<rolle> |
rollbackAccessAllowedByClass | Rollback | missing-rollback-role |
Ist keine Rolle konfiguriert (null), ist die Operation erlaubt. Rechte sind
also opt-in pro Modell.
Das Verhalten bei fehlender Rolle hängt am Strict Mode:
strikt → MissingPermissionException (403), tolerant → die Prüfung liefert
false und der Aufrufer liefert nichts zurück.
Rollennamen
Abschnitt betitelt „Rollennamen“Format (Vorschau im Frontend, verbindlich ist das Backend):
%ordnerpfad%/%modellname%{-aktion}| Situation | Rollenname |
|---|---|
Modell Question in audits/checklisten, keine Einschränkung | audits/checklisten/question |
| dasselbe, READ eingeschränkt | audits/checklisten/question-read |
Modell Tenant ohne Ordner | tenant |
| dasselbe, DELETE eingeschränkt | tenant-delete |
- Die Standardrolle (ohne Aktionssuffix) erlaubt alle Aktionen.
- Wird eine Aktion aktiv eingeschränkt, ist zusätzlich die Aktionsrolle erforderlich.
- Bestandteile werden normalisiert: Kleinschreibung, Leerzeichen zu
-.
Alle Rollen eines Systems sammelt der Generator in RoleRegistryService.
Realm-Rollen vs. Client-Rollen
Abschnitt betitelt „Realm-Rollen vs. Client-Rollen“| Art | Quelle im Token | wofür |
|---|---|---|
| Realm-Rollen | realm_access.roles | administrative Rechte der Plattform: allowed-tenant-context-switch, allowed-user-context-switch, Mandantenverwaltung |
| Client-Rollen | resource_access.<cias_client>.roles | fachliche Rechte auf Modellen und Feldern |
Die Modellprüfung benutzt Client-Rollen, der Kontextwechsel Realm-Rollen.
Ebene 2 – Feldrollen
Abschnitt betitelt „Ebene 2 – Feldrollen“@AccessFieldByRole(onCreate = "", onRead = "…", onUpdate = "…", onDelete = "")Die Feldrollen stehen in MetaFieldInfo (createRole, readRole,
updateRole, deleteRole) und werden vom generierten
{Model}AttributeFilter bzw. beim Aufbau der Antwort ausgewertet. Ein Feld ohne
Leserecht erscheint nicht in der Antwort; im Strict Mode führt die ausdrückliche
Anforderung eines solchen Feldes zum Fehler.
Ebene 3 – Zeilenrechte
Abschnitt betitelt „Ebene 3 – Zeilenrechte“Owner-Filter
Abschnitt betitelt „Owner-Filter“Erbt ein Modell von AbstractUserModel, ergänzt der System-Layer bei jeder
Abfrage:
_userId EQ <RequestContext.userId>Dieser Filter ist als mandatory markiert: Lässt er sich nicht in ein Datenbank-Prädikat übersetzen, scheitert die Anfrage – er wird nie stillschweigend weggelassen.
Attributfilter
Abschnitt betitelt „Attributfilter“Siehe Attributbasierte Filter.
Schreibschutz für unsichtbare Zeilen
Abschnitt betitelt „Schreibschutz für unsichtbare Zeilen“Update, Patch, Delete und Rollback laden ihr Ziel über einen ungefilterten
find. Damit die bloße Kenntnis einer ID nicht genügt, prüft der System-Layer
vorher assertVisibleForWrite(id): dieselben Filter wie beim Lesen. Eine nicht
sichtbare Zeile wird als 404 gemeldet, nicht als 403 – „existiert, gehört
dir aber nicht” würde die Existenz fremder Daten verraten.
Mandantenrechte
Abschnitt betitelt „Mandantenrechte“Der Mandant ist kein Filter, sondern die Wahl der Datenbank – siehe Mandantentrennung.
Wichtige Regel
Abschnitt betitelt „Wichtige Regel“Rechteprüfung findet im System-Layer und in cdms-authorization statt, nicht
in der Persistenz. Wer die Persistenz direkt aufruft, umgeht Owner- und
Attributfilter. Das ist beabsichtigt (Infrastruktur ohne Fachautorisierung),
muss bei neuen Aufrufern aber bewusst berücksichtigt werden.