feat(cabana): log successful toolbar and widget action runs with the admin id (quick-261028-rqf)

- runAction writes "cabana: admin action run" with controller, action,
  admin_id and kind (toolbar or field; field name and record id for a
  widget), never values, payload, answer or record contents
- the failure and data-rejected lines carry the same keys (admin_id, kind)
- actionAdminID helper shared with the bulk and record lines (unchanged)
- TestAdminActionRunLog pins the line on the acme.demo fixture (Postgres)
- README and the permissions docs describe the run log
This commit is contained in:
Jakub Zych
2026-10-28 21:05:55 +01:00
parent 202d38ba3c
commit 61d10436c7
4 changed files with 161 additions and 20 deletions

View File

@@ -72,7 +72,7 @@ The admin registers two permissions of its own on the System tab of the permissi
An administrator's grants are the role's `permissions` merged with the administrator's own `backend_users.permissions`, the way WinterCMS merges them: the administrator's value for a code replaces the role's, and only `1` grants. A `-1` (or `0`) on the administrator therefore removes a permission the role grants, so rows copied from a WinterCMS database keep their denies. As in WinterCMS the merge compares codes exactly, so denying `acme.blog.access_posts` does not take it back from a role that grants `acme.blog.*`.
Actions registered through `pact.HasAdminActions`, bulk actions (`pact.HasAdminBulkActions`) and record actions (`pact.HasAdminRecordActions`) may each name extra permissions, checked on top of the controller's. An administrator who lacks them does not get the action in the list schema or in a record's `meta.actions`, and posting it answers 403 and is written to the authentication log. A bulk or record action that ran is logged with the controller, the action, the administrator and the affected count or record id, without record contents.
Actions registered through `pact.HasAdminActions`, bulk actions (`pact.HasAdminBulkActions`) and record actions (`pact.HasAdminRecordActions`) may each name extra permissions, checked on top of the controller's. An administrator who lacks them does not get the action in the list schema or in a record's `meta.actions`, and posting it answers 403 and is written to the authentication log. A bulk, record, toolbar or widget action that ran is logged with the controller, the action and the administrator, plus the affected count for a bulk action, the record id for a record action (and for a widget action posted from a saved record), and the kind `toolbar` or `field` for the other two, without record contents, posted values or payload.
A permission denial and a refusal are different answers with the same status. A denial comes from the framework: the administrator lacks a permission code, and the 403 carries the framework's fixed text. A refusal comes from controller code that returns a `cabana.ForbiddenError`: the administrator may run the route, but this change is not allowed for this record, and the 403 carries the plugin's translated message and, optionally, messages per field. See [Refusing a write](admin-controllers.md#refusing-a-write).