2026-03-04 15:56:58 +01:00
|
|
|
# RBAC Permission Playbook
|
|
|
|
|
|
2026-03-06 12:25:18 +01:00
|
|
|
Letzte Aktualisierung: 2026-03-06
|
2026-03-04 15:56:58 +01:00
|
|
|
|
|
|
|
|
Ziel: Neue Rechte konsistent und ohne Legacy-Pfade ergänzen.
|
|
|
|
|
|
|
|
|
|
## Entscheidungshilfe
|
|
|
|
|
|
|
|
|
|
1. Nur UI an bestehende Ability hängen: 3 Schritte.
|
|
|
|
|
2. Neue Ability auf bestehende Permission: 4 Schritte.
|
|
|
|
|
3. Ganz neue Permission (inkl. DB): 7 Schritte.
|
|
|
|
|
|
|
|
|
|
## Fall A: Ganz neue Permission
|
|
|
|
|
|
|
|
|
|
1. Permission-Key in `PermissionService` ergänzen.
|
2026-04-13 23:20:05 +02:00
|
|
|
Datei: `core/Service/Access/PermissionService.php`
|
2026-03-04 15:56:58 +01:00
|
|
|
2. DB-Update für Bestandsinstanzen anlegen (idempotent).
|
|
|
|
|
Datei: `db/updates/YYYY-MM-DD-*.sql`
|
|
|
|
|
3. `db/init/init.sql` für Neuinstallationen synchron ergänzen.
|
|
|
|
|
4. Ability in passender Policy ergänzen:
|
|
|
|
|
`ABILITY_*`, `supports()`, Mapping in `authorize()`.
|
|
|
|
|
5. Action/API auf Ability umstellen:
|
|
|
|
|
Web: `Guard::requireAbility(...)` oder `AuthorizationService`.
|
|
|
|
|
API: `ApiResponse::requireAbility(...)`.
|
|
|
|
|
6. Falls UI betroffen: `UiCapabilityMap` ergänzen und in Action nach `$viewAuth` auflösen.
|
|
|
|
|
7. Tests + Doku aktualisieren.
|
|
|
|
|
|
|
|
|
|
Beispiel (Core): `system_audit.view` + `system_audit.purge` mit Abilities
|
|
|
|
|
`ops.admin.system_audit.view` und `ops.admin.system_audit.purge`.
|
|
|
|
|
|
|
|
|
|
## Fall B: Neue Ability auf bestehende Permission
|
|
|
|
|
|
|
|
|
|
1. Ability in passender Policy ergänzen und auf vorhandenen Permission-Key mappen.
|
|
|
|
|
2. Action/API auf neue Ability ziehen.
|
|
|
|
|
3. Optional UI-Mapping in `UiCapabilityMap` + `$viewAuth`.
|
|
|
|
|
4. Tests/Doku nachziehen.
|
|
|
|
|
|
|
|
|
|
## Fall C: Nur UI-Freigabe erweitern (ohne neue Permission)
|
|
|
|
|
|
|
|
|
|
1. Capability-Key in `UiCapabilityMap` ergänzen.
|
|
|
|
|
2. In Action mit `UiAccessService::pageCapabilities(...)` oder `layoutCapabilities()` auflösen.
|
|
|
|
|
3. Template nur über `$viewAuth['page']` bzw. `$viewAuth['layout']` steuern.
|
|
|
|
|
|
|
|
|
|
## Fall D: API-only Endpoint
|
|
|
|
|
|
|
|
|
|
1. Ability festlegen (Policy/OperationsPolicy).
|
|
|
|
|
2. Endpoint mit `ApiResponse::requireAbility(...)` schützen.
|
|
|
|
|
3. OpenAPI aktualisieren.
|
|
|
|
|
4. API-Tests ergänzen.
|
|
|
|
|
|
|
|
|
|
## Fall E: Scope-sensitive Ability (Ressourcenbezug)
|
|
|
|
|
|
|
|
|
|
1. Immer Kontext übergeben, z. B.:
|
|
|
|
|
`actor_user_id`, `target_user_id`, `target_tenant_id`, `input`.
|
|
|
|
|
2. Wenn Capabilities benötigt werden:
|
|
|
|
|
`AuthorizationDecision::attribute('capabilities', [])` nutzen.
|
|
|
|
|
3. Für reine Bool-Checks `AuthorizationService::allow(...)` verwenden.
|
|
|
|
|
|
|
|
|
|
## Verbindliche Regeln
|
|
|
|
|
|
|
|
|
|
1. Keine Permission-Checks in Templates (`can(...)` verboten).
|
|
|
|
|
2. Keine alten Wrapper (`Guard::requirePermission*`, `ApiResponse::requirePermission`).
|
|
|
|
|
3. UI nur über `$viewAuth`.
|
|
|
|
|
4. Policy-/Ability-Namen sind der technische Vertrag, nicht der Permission-Key im Template.
|
|
|
|
|
|
|
|
|
|
## Minimal-Checkliste vor Merge
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
rg -n "(?<!::)\\bcan\\(" templates pages -g '*.phtml' -P
|
|
|
|
|
rg -n "Guard::requirePermission\\(|Guard::requirePermissionOrForbidden\\(|ApiResponse::requirePermission\\(" pages lib tests web templates -g '*.php'
|
|
|
|
|
docker compose exec php vendor/bin/phpunit
|
|
|
|
|
docker compose exec php vendor/bin/phpstan analyse -c phpstan.neon --no-progress
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Erwartung:
|
|
|
|
|
|
|
|
|
|
1. Die beiden `rg`-Checks liefern `0` Treffer.
|
|
|
|
|
2. `phpunit` und `phpstan` sind grün.
|