Problem/Motivation
Discovered in #2938035-6: When PATCHing a field is disallowed, no reason is given for *why* this happens. This blocks that issue.
#2808233: REST 403 responses don't tell the user *why* access is not granted: requires deep Drupal understanding to figure out introduced \Drupal\Core\Access\AccessResultReasonInterface
. It also introduced the inheriting of a the reason through ->orIf()
and ->andIf()
combinations.
I just noticed that if you do
$a = AccessResult::neutral('You do not have the FOO permission.');
$b = AccessResult::neutral();
$reason = $a->orIf($b)->getReason();
Then $reason === NULL
… which means you've just lost the reason. This occurs in real-world circumstances. Which means, for example, on any site with hook_entity_field_access()
, the reason for some field access operation being denied … will be erased. Resulting in a bad DX.
Proposed resolution
- Add tests.
- Fix.
Remaining tasks
None.
User interface changes
None.
API changes
None.
Data model changes
None.
Comment | File | Size | Author |
---|---|---|---|
#13 | 2938053-13.patch | 5.68 KB | Wim Leers |
Comments
Comment #2
Wim LeersExpanding test coverage. This fails.
(Lifted from #2938035-6: When PATCHing a field is disallowed, no reason is given for *why* this happens.)
Comment #3
Wim LeersAnd this fixes it.
(Lifted from #2938035-7: When PATCHing a field is disallowed, no reason is given for *why* this happens.)
Comment #5
effulgentsia CreditAttribution: effulgentsia at Acquia commentedIf this is indirectly blocking #2930028: Comprehensive JSON API integration test coverage phase 1: for every entity type, individual resources only, which in turn blocks JsonApi from being added to core, then raising this to Major. If it ends up not needing to block any of that, then we can re-evaluate priority.
Comment #6
Wim Leers#5: correct, this is indirectly blocking #2930028: Comprehensive JSON API integration test coverage phase 1: for every entity type, individual resources only, and will soon be directly blocking it.
Comment #7
e0ipsoThis looks good to me. I'm hesitant to RTBC because I'd like to add an extra assertion
$this->assertNull($neutral_reasonless->orIf($neutral_reasonless)->getReason());
. But that's a very minor observation.Comment #8
Wim LeersGood call, done.
Comment #9
e0ipsoThis is RTBC for me.
Comment #10
alexpottI wanted to make sure we had test coverage for both
$forbidden->orIf($neutral)
and$neutral->orIf($forbidden);
and it turns out we have an important typo in the test. We need to make the following change:Another thing I pondered was if we should test for reason precedence. Ie.
We don't have any other tests for this for the FORBIDDEN && FORBIDDEN where the same situation comes up. I also wonder if we should care about the information loss.
Comment #11
Wim Leers+1. Done! I should've done that in the original issue.
Comment #12
Wim Leers… and there was one more, even!
Fixed both.
Comment #13
Wim LeersAnd #10 made me realize that the problem this issue describes occurs not only for
NEUTRAL || NEUTRAL
, but also forFORBIDDEN || FORBIDDEN
. A similar bug existed there (the reason could get lost). The fix was similar. In fact, now the::orIf()
logic has identical code for handling reason inheritance in both the "merge NEUTRAL || NEUTRAL" and the "merge FORBIDDEN || FORBIDDEN" cases, and both have complete test coverage now.Comment #14
alexpottUpdating title accordingly.
Comment #15
Wim LeersOops, I wanted to do that, but obviously forgot!
Comment #16
Wim LeersThe JSON API module just ran into this same core bug in its test coverage, as predicted. See #2930028-61: Comprehensive JSON API integration test coverage phase 1: for every entity type, individual resources only.
Comment #17
borisson_This all looks very solid. @alexpott made some remarks in #10 and as far as I can tell, those have all been resolved.
Comment #18
alexpottCommitted and pushed b6242dab05 to 8.6.x and f1d3e4a07c to 8.5.x. Thanks!
Crediting myself for a review that affected the shape of the patch.
Comment #21
Wim LeersThis unblocked #2938035 — rebased patches at #2938035-28: When PATCHing a field is disallowed, no reason is given for *why* this happens ready!
It also unblocked #2954847, a similar issue for the contrib JSON API module!