Problem/Motivation
While working on #2737719: EntityResource: Provide comprehensive test coverage: for every entity type, every format, every method, I encountered 403 responses when I expected to get 406 responses. See #2737719-41: EntityResource: Provide comprehensive test coverage: for every entity type, every format, every method and #2737719-71: EntityResource: Provide comprehensive test coverage: for every entity type, every format, every method.
Blocks can be viewed by anonymous user by default, so when a "block" REST resource is enabled, everybody can read all block configuration. The root cause is that we ended up with a very strange interpretation of the view
operation on Block
config entities: rather than "read/view Block config entities", it has ended up meaning "view the rendered version of this Block config entity's plugin". It made sense then, but it also means it's highly inconsistent with how entity access is supposed to work.
For all other entities "view" == "read the entity". But in this case, because "blocks" are this complex hybrid of "entity + plugin", it really means "read the entity's plugin's output".
Proposed resolution
TBD
Remaining tasks
TBD
User interface changes
None.
API changes
TBD, hopefully none.
Data model changes
TBD, hopefully none.
Comments
Comment #2
dawehnerI'm wondering whether we could have different access checking depending on the format we want to render. I would argue ideally reading of block config entities via REST, would return exactly what you expect to return.
Comment #3
Wim LeersInteresting idea :) But wouldn't that quickly become too confusing?
I'm not sure what this means?
Comment #4
dawehnerOh well, basically repeating the previous sentence. Check the view condition for the config entity instead of taking into account the plugin itself.
Comment #5
Wim LeersProblems reported with the current code in another API-first situation: #2826813: Access checks failed for entity block:views_block !, in the JSON API module.
Comment #7
shadcn CreditAttribution: shadcn at Chapter Three commentedThis is happening for
BlockContent
entities as well. And rather scary. Everything is exposed: fromuuid
torevision_id
..etc.Comment #8
Wim LeersGiven #7, perhaps this makes sense.
Comment #9
Wim LeersThis came up again at #2835845-36: EntityResource: Provide comprehensive test coverage for BlockContent entity and #2835845-37: EntityResource: Provide comprehensive test coverage for BlockContent entity.
Comment #10
BerdirResponding to Wim's comment from that issue:
As we already discussed once on IRC, I disagree with this (view == "read the entity" == "render on page" (because the rendered representation is equivalent with being able to read all fields)), as did you in this issue in comment #7/#8 :)
Content entities have plenty of layers between reading raw data and rendering an actual entity, at least 4 that can control visibility and how it is displayed:
1. Field formatters/view display configuration. Allows to control how a field is displayed and it's also very easy to hide one completely by just moving it to hidden. Entities often have internal data that is not meant to be displayed and this is the easiest way for users to do so.
2. Text formats convert e.g. embedded entities and many other things.
3. The process layer also allows to dynamically hide/show fields
4. Twig also makes it trivial to do a {{ content|without('some_field') }}.
None of that is reflected in field access. And we do offer all those API's, even I who knows that API well usually only bother with field access for fields that should only show dynamically based on access checks. And many developers probably just do checks in preprocess/twig.
All those steps can expose internal/private data. Especially since the rest module provides default configuration for node, so just by enabling rest, your site exposes all the raw data for its configurable fields on nodes to anyone. The example I also mentioned in IRC is a newspaper paywall. Those usually don't use field/node access as the user can view the node, but he'll just get a short teaser. If the site has REST enabled and you know that, it's easy to build a script to steal all their content.
So IMHO, the problem of viewing raw data vs. viewing what Drupal renders as the visual representation of that entity exists for all entities, content but also something like a view for example. As comment #7 said, all the "scary" internal data is out there in the open.
There is one thing where block is different from content entities. And that's that their raw data is usually just configuration of what should be displayed, so it's usually impossible to actually get the data you want to have displayed. For nodes, while there are plenty of issues as well, you can probably usually get something working despite all the "scary" stuff. But that doesn't mean it is not a problem.
So yes, possibly block and node require different solutions for what is technically the same problem and probably multiple issues.
I'm not sure how to solve those things. I guess a menu block should return a JSON/data representation of the menu tree for example? A block_content block the block_content entity (which then has the content-entity side of this problem)? A breadcrumb block the breadcrumb data? Maybe we need block plugin normalizers?