Problem/Motivation

Drupal\jsonapi\Access\EntityAccessChecker still has a temporary workaround in it from prior to https://www.drupal.org/project/drupal/issues/3043321 (generic revision access control) landing in core.

Proposed resolution

Now that we have a generic revision access API, replace the content_moderation specific code with just a check based on the generic revision access operation.

API changes

The current code is checking the 'view all revisions' operation on the entity when it's not the default revision. This would change that to 'view revision' instead, as that's the operation we use for viewing an individual revision in RevisionHtmlRouteProvider. If other access control handlers aren't handling that at the moment then access would be denied.

Issue fork drupal-3035113

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

Dylan Donkersgoed created an issue. See original summary.

dylan donkersgoed’s picture

Status: Active » Needs review
StatusFileSize
new2.35 KB

Attached.

Note that this patch only addresses the issue with this specific method. I see that other methods use similar access check objects and theoretically could cause the same issue with similar overrides.

gabesullice’s picture

Issue tags: +API-First Initiative

Hi @Dylan Donkersgoed! Thanks for filing this issue. And for providing a patch! This is the second issue to reference this problem (I can't find the other though). Found it! #3034532: Workbench Moderation's `access_check.latest_revision` service ID conflicts with Content Moderation in core

Unfortunately, the intention really was to prevent any other access checkers from being used. Our intention wasn't to cause fatal errors, of course! However, since we don't want any other revision access checkers to be used (frankly, we don't trust them) I don't think we want to use an interface.

The problem is that these access checkers were all written on the assumption that they would be used for admin UI routes, not entity access in JSON:API. So their logic isn't always safe to use.

gabesullice’s picture

Title: Conflict with group content moderation patch » EntityAccessChecker::setLatestRevisionCheck cannot depend on a compatible service; needs alternative solution
gabesullice’s picture

More context:

Part of the problem is that the Entity API does not have any access control mechanisms that respect revisions. The only access control in Drupal core is all about access to revision pages. There's a major revision refactoring underway in #2942907: Entity system does not provide an API for retrieving an entity variant that is safe for editing and access control has been brought up several times. I've asked if there is a specific issue we can track.

In the meantime, it seems we should find a workaround that doesn't brick people's sites in this issue.

wim leers’s picture

Category: Bug report » Feature request
geek-merlin’s picture

Title: EntityAccessChecker::setLatestRevisionCheck cannot depend on a compatible service; needs alternative solution » jsonapi typehints class, leading to WSOD when decorated; Find other solution
StatusFileSize
new3.42 KB

OK, first copying over my comment and patch from [#12988384-16]. Also changing title to address the full scope.
Patch flying in that changes all class-typehinted methods to interface typehints (and removes obsolete use statements) (It is identical to #2 plus the other typehints).

Ran into the same problem with group module and #2906085: Content moderation integration: transition permissions and latest version access.

Setting to critical as WSOD. Setting to jsonapi due to the following.

Short version: By typehinting a class instead of an interface, jsonapi does not play by the rules.

Long version (or why this rule is important): If like suggested and implemented above, we subclass the content_moderation class, everything looks fine. But what should the next module do? The only correct way to enrich a service is to decorate it and implement the interface. The group patch referenced above does this well. And any component must accept decorated services as long as they implement the interface. That's the rules in DI land.

Patch flying in that fixes the typehint in jsonapi.

Thanks a lot for the above explanations why the class typehinting had been done in the first place. I'd suggest
a) Fix the typehints like in the attached patch
b) For now, add some hook_requirements implementation that checks the said class and warns the user if it differs. (it's the best we can do...)
c) Work upstream that we get a proper API for what we need here

geek-merlin’s picture

Category: Feature request » Bug report
Priority: Normal » Critical

Setting critical bug as this leads to WSOD.

geek-merlin’s picture

Looked into the upstream core issue, it looks amazing and has good progress.

wim leers’s picture

You wrote:

Fix the typehints like in the attached patch

But did you read

Unfortunately, the intention really was to prevent any other access checkers from being used. Our intention wasn't to cause fatal errors, of course! However, since we don't want any other revision access checkers to be used (frankly, we don't trust them) I don't think we want to use an interface.

?

wim leers’s picture

geek-merlin’s picture

#11: Yes i read that, and i did not want to sound like i lightheadedly disregard this, the proposal is the only solutio i can see.
Did you grok the passage above about decorating services & coding against interfaces? Do you see any other way to proceed in this light?

wim leers’s picture

Yes, of course I know about interfaces.

#3 and #6 explain why we explicitly and intentionally chose to not typehint to the interface, since it doesn't provide sufficient guarantees.

I do see another way: let #2906085: Content moderation integration: transition permissions and latest version access subclass the classes its decorating. That would signal that they provide a customized version of the same behavior and provide the same guarantees. And it'd automatically work.

wim leers’s picture

Category: Bug report » Support request
Priority: Critical » Normal
Status: Needs review » Closed (works as designed)

I turned this into a concrete proposal and change request over at #2906085-48: Content moderation integration: transition permissions and latest version access.

This was never a critical bug in the JSON:API module, but rather a consequence of a design choice in another contrib module. Changing the issue metadata accordingly.

I believe we've explained in detail the rationale behind the design choice in the JSON:API module. It's a matter of security. So, closing this.

jonathanshaw’s picture

The problem is that these access checkers were all written on the assumption that they would be used for admin UI routes, not entity access in JSON:API.

subclass the classes its decorating. That would signal that they provide a customized version of the same behavior and provide the same guarantees.

Do you see this as the correct long term solution, or is there something else long term that will address the lack of consideration for jsonapi in access checkers? Something there an alternative but empty interface that access checkers could implement in order to declare their safety for use in this context.

geek-merlin’s picture

Category: Support request » Feature request
Status: Closed (works as designed) » Active

@gabesullice explained in #6:

More context:

Part of the problem is that the Entity API does not have any access control mechanisms that respect revisions. The only access control in Drupal core is all about access to revision pages. There's a major revision refactoring underway in #2942907: Entity system does not provide an API for retrieving an entity variant that is safe for editing and access control has been brought up several times. I've asked if there is a specific issue we can track.

In the meantime, it seems we should find a workaround that doesn't brick people's sites in this issue.

If i get it right, this meantime is over, and now that #2942907: Entity system does not provide an API for retrieving an entity variant that is safe for editing is in, it sheds new light on this issue..

wim leers’s picture

#16: see #17 :)

#17: no, what Gabe said is blocked on #3043321: Use generic access API for node and media revision UI (which was only created a few days ago, as a subtask of #2350939: Implement a generic revision UI, which is very old).

geek-merlin’s picture

Project: JSON:API » Drupal core
Version: 8.x-2.x-dev » 8.7.x-dev
Component: Code » jsonapi.module
Status: Active » Postponed
Related issues: +#2942907: Entity system does not provide an API for retrieving an entity variant that is safe for editing, +#3043321: Use generic access API for node and media revision UI

OK so i leant that this module now lives in core (and understand the harsh insisting on this not be a bug ;-) - great work to have this in core!!).
So i guess we move this over to core and postpone on #3043321: Use generic access API for node and media revision UI.

wim leers’s picture

Title: jsonapi typehints class, leading to WSOD when decorated; Find other solution » [PP-1] JSON:API is typehinting LatestRevisionCheck because there is no Entity Revision Access API yet, remove that typehint once such an API exists
Version: 8.7.x-dev » 8.8.x-dev

Sure, we can do that. But that'll probably take months to complete, and will ship with Drupal 8.8 (end of 2019) at the earliest.

So if Workbench Moderation users want to move forward, the only option is to do #3034532: Workbench Moderation's `access_check.latest_revision` service ID conflicts with Content Moderation in core. And for Group users that have the #2906085: Content moderation integration: transition permissions and latest version access patch applied (it's not even committed yet!), the only option is to slightly refine the patch.

Then once #3043321: Use generic access API for node and media revision UI lands, yes, we'd love to change this typehint! 😄Believe me, we hate that we have to have it there. But it's the prudent thing to do.

shelane’s picture

Now that JSON API has been moved into core in 8.7, I have rolled this patch for core.

shelane’s picture

StatusFileSize
new3.5 KB
socialnicheguru’s picture

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

sam-elayyoub’s picture

StatusFileSize
new3.58 KB

This patch works with me perfectly, in case if this still needed

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

bbrala’s picture

Status: Postponed » Needs work
larowlan’s picture

Title: [PP-1] JSON:API is typehinting LatestRevisionCheck because there is no Entity Revision Access API yet, remove that typehint once such an API exists » JSON:API is typehinting LatestRevisionCheck because there is no Entity Revision Access API yet, remove that typehint once such an API exists

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

atul4drupal’s picture

StatusFileSize
new3.38 KB

Rerolled for 9.3.x ... just in case someone needed like we did...

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

nikhil_110’s picture

StatusFileSize
new3.38 KB

Attached patch against Drupal 10.1.x

sahil.goyal’s picture

StatusFileSize
new3.45 KB
new1.23 KB

Patch #36 is conflicting to apply to D10.1.x, so Updated the patch to make it compatible and Fix the errors to make it pass all test cases.

bbrala’s picture

Let me get a review in :)

  1. +++ b/core/modules/jsonapi/src/Access/EntityAccessChecker.php
    @@ -67,9 +67,9 @@ class EntityAccessChecker {
    +  protected $AccessInterface = NULL;
    

    This feels weird, the variable name shouldn't start with a capital letter.

  2. +++ b/core/modules/jsonapi/src/Access/EntityAccessChecker.php
    @@ -95,14 +95,14 @@ public function __construct(ResourceTypeRepositoryInterface $resource_type_repos
    +  public function setLatestRevisionCheck(AccessInterface $latest_revision_check) {
    

    Since we are broadening the hint, i think this is not bc-breaking. So this is fine.

  3. +++ b/core/modules/jsonapi/src/Access/EntityAccessChecker.php
    @@ -196,8 +196,8 @@ protected function checkRevisionViewAccess(EntityInterface $entity, AccountInter
    +    if ($entity_type->getLinkTemplate('latest-version') && $entity->isLatestRevision() && isset($this->AccessInterface)) {
    

    I wonder, if you already have access to view all revisions, do we even need to check for the specific revision? Or could you have permissions to see all revisions and then get denied for some specific revision? Although technically possible i kinda wonder why that would be the case.

Summarizing; some small changes needed, the change seems reasonable now that the blocking issue is merged.

amermod’s picture

We are still talking about revision checks while it should be the role of the EntityAccessControlHandler to do the revision access check.

And it actually does that already, so why is there still a revision access check in the jsonAPI module ? Because the EntityAccessControlHandler can not be trusted for revisions, as said in #3, four years ago ?

I just attached a patch that removes simply the revisions check, to see what will fail.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

richard.thomas made their first commit to this issue’s fork.

richard.thomas’s picture

Status: Needs work » Needs review

I've created a merge request to remove the content_moderation specific access checking logic in favour of a generic 'view revision' check.

https://git.drupalcode.org/project/drupal/-/merge_requests/15455

The code was previously checking 'view all revisions' as well as the content moderation one, but it seems like 'view revision' makes more sense as we're specifically checking access for the working copy revision. Although from what I can see nearly all the core access control handlers treat both operations the same?

Only catch was that the workspace access control didn't seem to handle 'view revision' at all. Possibly a separate issue but it seemed better to fix that here rather than try and handle that edge case inside JSON:API by checking both.

richard.thomas’s picture

Title: JSON:API is typehinting LatestRevisionCheck because there is no Entity Revision Access API yet, remove that typehint once such an API exists » Replace content moderation specific access check in JSON:API with generic revision access check
Issue summary: View changes

I've updated the issue summary to better describe the change here and hidden old patch files.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.