Problem/Motivation
Created as a follow-up to #2350939: Implement a generic revision UI.
There are several problems that result from the Revert and Delete actions being available for the current revision.
- The user interface break slightly, with the Revert/Delete split/drop button being directly to the right of the "Current revision" text, all under the single "Operations" column.
- Following through the Revert action technically works, in that a new "revert" revision is created, practically nothing has changed because the "current revision" is the current state of the content. In other words, reverting the current revision is illogical because there is nothing to revert to.
- Following through the Delete action results in an error and White Screen of Death, which leaves the entity in a broken and unrecoverable state.
The current solution to this is that every entity implementing the Generic Revision UI must include logic in its own access checker to ensure that the Revert and Delete actions cannot be accessed. Example from #1984588: Add Block Content revision UI:
'revert' => AccessResult::allowedIfHasPermissions($account, [
'administer blocks',
'revert any ' . $bundle . ' block content revisions',
], 'OR')->orIf(AccessResult::forbiddenIf($entity->isDefaultRevision() && $entity->isLatestRevision())),
'delete revision' => AccessResult::allowedIfHasPermissions($account, [
'administer blocks',
'delete any ' . $bundle . ' block content revisions',
], 'OR')->orIf(AccessResult::forbiddenIf($entity->isDefaultRevision() && $entity->isLatestRevision())),
In short, each implementation must include something to the effect of AccessResult::forbiddenIf($entity->isDefaultRevision() && $entity->isLatestRevision()
in the access checker, once for the revert
operation, and a second time for the delete revision
operation.
There are two issues here:
- It's reasonable to assume that some developers will forget or not realise they need to include this in their access checkers, resulting in some implementation potentially being buggy.
- The fact that every implementation needs to include what is in effect the same lines of code suggests that overall developer effort would be reduced by providing this logic in an access checker out of the box, as well as lowering the barrier to entry and reducing the likelihood of bugs in contrib/custom implementations.
Proposed resolution
Remove isDefaultRevision and isLatestRevision checks from entity type specific access control handlers (e.g BlockContentAccessControlHandler)
Add check for isDefaultRevision for revert and delete revision operations in generic EntityAccessControlHandler and return a forbidden
Improve and fix test coverage for these operations, including expanding EntityTest access tests.
Remaining tasks
Final review