Files
breadcrumb-the-shire/docs/howto-rbac-permissions-playbook.md

2.9 KiB

RBAC Permission Playbook

Letzte Aktualisierung: 2026-03-06

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. Datei: lib/Service/Access/PermissionService.php
  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

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.