Problem/Motivation
As of #3028301: Do not expose to Layout Builder's sections either in defaults or overrides to REST and other external APIs, Layout Builder is not yet ready to expose its "layout description data structure" as an API — that's what #2942975: [PP-1] Expose Layout Builder data to REST and JSON:API aims to fix. As a work-around, we created \Drupal\layout_builder\Normalizer\LayoutEntityDisplayNormalizer to ensure this is not exposed via rest.module.
However, this then had to be repeated for jsonapi.module in #3042198: Add JSON:API integration test for LayoutBuilderEntityViewDisplay. But JSON:API module doesn't allow for such arbitrary
alterations, because it makes schema support impossible (see https://www.drupal.org/project/openapi) and endangers JSON:API spec compliance.
Proposed resolution
Bring the internal flag from Typed Data definitions over to config schema as well, then we could just mark third_party_settings.layout_builder.sections as internal and the JSON:API module would respect that. We can make the RESTful Web Services module respect it too, and remove \Drupal\layout_builder\Normalizer\LayoutEntityDisplayNormalizer.
Remaining tasks
TBD
User interface changes
None.
API changes
Ability to mark
Data model changes
No changes, only an addition: a internal flag (name TBD) on config schemas would allow a certain subtree from the config schema to be marked as an internal implementation detail, that should not be exposed via HTTP APIs.
Release notes snippet
TBD
| Comment | File | Size | Author |
|---|---|---|---|
| #48 | 3043245-48.patch | 8.99 KB | borisson_ |
| #36 | 3043245-36.patch | 16.92 KB | ranjith_kumar_k_u |
| #30 | interdiff-3043245-28-30.txt | 604 bytes | samuel.mortenson |
| #30 | 3043245-30.patch | 17.23 KB | samuel.mortenson |
Comments
Comment #2
wim leersInterestingly, this is actually quite closely related to #2869792: [meta] Add constraints to all config entity types and #2300677: JSON:API POST/PATCH support for fully validatable config entities which are about adding support to create, update and delete config entities. They too require additions to config schema types.
Comment #3
wim leersThis can also be viewed to be part of #3040025: [meta] Decide on and implement additional security hardenings for JSON:API and other HTTP APIs.
Comment #4
effulgentsia commentedIn #3037039-17: Create a public API for indicating resource types should not be exposed, @gabesullice proposes distinguishing the semantics of "makes sense to be consumed via an API" vs. "is (un)prepared to be consumed via an API". I don't know if there's agreement about that but #3040354: Introduce entity type annotation key for indicating that an entity type is *safe* for HTTP API usage is also exploring the possibility of adding a different annotation for the latter.
However, we don't currently distinguish those two meanings, so as long as that's the case, a single
internalflag (to match TypedData's isInternal()) might be the best way to proceed. And if we eventually agree on adding a different flag to TypedData, then we can add it to config schemas as well.Comment #5
effulgentsia commentedI think a proof of concept patch would be a good next step. I'm curious if it would make config normalization much slower, since we'd need to walk the entire tree and load and process config schema along the way.
Comment #7
wim leers@gabesullice in #3040025-8: [meta] Decide on and implement additional security hardenings for JSON:API and other HTTP APIs
I tentatively disagree here. It appears quite a lot of decoupled sites are reading display configuration stored in
EntityViewDisplay. Regardless of #3040372 therefore being harmful for those sites since it would make it much harder for them to read this information. It seems many sites want to go even further and want to use server-side stored layout information managed by Layout Builder. That Layout Builder's data structure has not yet been finalized (see #3028301: Do not expose to Layout Builder's sections either in defaults or overrides to REST and other external APIs), nor has the way that data structure is exposed via HTTP APIs. It'd be helpful to be able to expose only those parts of config entities that have been finalized. Layout Builder is only the first example.If we some day want to expose all configuration managed by Drupal via HTTP APIs, this seems to be a necessary stepping stone.
Comment #8
wim leers#5: That would certainly be the case. But normalizations of config entities can be cached efficiently; they're the same for all users. Plus, there's no need to do field-level access checking, which is pretty expensive for content entities. So overall, I don't see performance concerns becoming a blocker here.
Comment #9
wim leersComment #10
gabesulliceReally? Where have you noticed that?
Personally, I consider what you're describing to be a complicated anti-pattern. It's unfortunate people feel forced into it.
My hope is that with JSON:API Hypermedia stabilized, some enterprising individual will write a "JSON:API Displays" module which adds a custom link to resources in much the same was that JSON:API Schema does, like so:
These endpoints would aggregate information across entity view displays and field configs into a single, logical JSON object. There's no good reason to expose the Drupal implementation detail that is config entities and view displays other than the fact that it's expedient. This module could also incorporate the Layout Builder information you're talking about without exposing its storage format.
Comment #11
wim leersWhy do you consider it an anti-pattern? It enables site builders to have some control over the front end just like they are able to do in fully coupled Drupal, specifically to control the order in which fields are rendered.
I agree that all of that would be nice.
But I really just provided
EntityViewDisplayas an example here. This issue's title, intent and scope are generic. If it's possible to mark subtrees of information as internal for content entities (by marking fields or field properties as internal), then the same should also be possible for config entities. Do you disagree with that?Comment #12
gabesulliceAllowing is desirable, but deriving that display logic from disparate and complex config entities (read: implementation details) is an anti-pattern. Consider this: Twig templates do not load and parse config entities, they receive render arrays which encode display logic through structure and semantics.
I've really struggled to come up with a case where direct access to config entities is really the best pattern for a decoupled applications. Perhaps you can help me there.
Whether I agree with that totally depends on the conclusion to the above. If we really think config entities represent valuable content to a decoupled consumer, then yes. I think there should be a facility to mark some things internal. OTOH, if we can't come up with any practical use cases for exposing config entities that shouldn't be done in another, more elegant way then I think the point is moot. Config entities are by nature completely internal.
Comment #13
effulgentsia commentedYou might be correct that decoupled applications accessing config entity resources directly is always a case of expediency rather than ideal architecture, but let's not underestimate the value of expediency here. In a lot of cases, teams who are building decoupled applications might consist entirely of front-end developers and no back-end developers. Let's say that such an application wants to present a UI that lets you select from an image style, or a date format, or a Vocabulary, or any number of contrib config entities, such as a commerce currency, or shipping option, or ...
It might be that in each such case, there ought to be a JSON:API resource with a well-thought-out API that presents these things in a way that is abstracted from the underlying config entities, but let's face it: most contrib modules won't ship with such resources. A team with a back-end developer could build these resources, but what about a team consisting of just JS developers? Maybe config entity resources aren't the best representation that's theoretically possible, but they're already there, for free, for every contrib module's config entity type, and that counts for a lot.
Comment #14
gabesullice@effulgentsia, good points. I think the selection UI you mention in your first paragraph could already work by utilizing JSON:API Schema and reading the allowed enum values. The rest could be automatically derived from field and display config entities if someone wrote a module for that generically. So it wouldn't have to be custom to every module or project (read, it wouldn't need a BE dev).
I do hear your point about the here and now though. What I'm describing is a long way off.
FWIW, my proposal isn't (and wasn't) to close this issue. I said we should
I think you both would agree that most sites don't need to read config entities. Once we complete #3040372: Allow for API-First content without requiring all configuration to also be API-first and #3040354: Introduce entity type annotation key for indicating that an entity type is *safe* for HTTP API usage, which I believe @Wim Leers agreed were higher priorities, most config entities won't be accessible by default. Thus, internalizing sub-properties of the very few remaining accessible config entities, is not a very high priority in my mind.
@Wim Leers or @effulgentsia, do you think this issue should be prioritized above anything else?
Comment #15
wim leersAgreed! Drupal's internal data model decomposition for UI purposes makes sense for Drupal's UI code architecture, not for others' UIs.
Not every config entity is for presentation purposes.
Workflow,PathautoPattern,ContentLanguageSettings,Role,TaxType(Drupal Commerce), and so on. I think you're implying that most config entities relate to presentation. Looking at the config entity types in core, I think you're right that they are in the majority. But that doesn't mean there isn't a need to access some config entities even if you have a completely custom decoupled UI.Yes. But it depends on the use case. Even if 80% doesn't need it, it may be mission-critical for 20%.
I think that makes sense.
Comment #16
wim leersIn >6 weeks no disagreements with making this a lower priority. So, making that happen now.
Comment #18
samuel.mortensonI started working on this, and assumed that a good approach would be to remove
LayoutEntityDisplayNormalizerand add an internal flag to thelayout_builder.sectionconfig schema, then add support for checking the internal flag to\Drupal\serialization\Normalizer\ConfigEntityNormalizer::getDataWithoutInternals.After removing
LayoutEntityDisplayNormalizer, I still couldn't see "sections" when viewing a entity view display that used Layout Builder. This is making manual testing difficult - what's the expected behavior whenLayoutEntityDisplayNormalizeris removed?Comment #19
wim leersI suspect it's because of
\Drupal\layout_builder\Field\LayoutSectionItemList::defaultAccess():Comment #20
samuel.mortenson@wim-leers Thanks for digging - I'll do my testing with a test config schema instead of Layout Builder then.
Comment #21
samuel.mortensonHere's what I have so far - test coverage is implicit based on the changes to the config_test entity type. Since config entities can't be edited via HTTP APIs yet, POST/PATCH haven't been tested.
Comment #23
samuel.mortensonShould fix some of the test failures.
Comment #25
samuel.mortensonWorking on fixes.
Comment #26
samuel.mortensonAdding onto config_test, even when I tried adding a new entity type within config_test, led to too much complication. I ended up splitting test coverage into a completely separate test submodule which should avoid those complications.
Comment #28
samuel.mortensonWorked on test fixes and added unit test coverage for
\Drupal\serialization\Normalizer\ConfigEntityNormalizer.Comment #30
samuel.mortensonForgot to update the config normalizer service arguments.
Comment #35
bbralaThis sounds like a good idea, but needs a review from someone with a little more knowlegde of the config system than me i think.
Comment #36
ranjith_kumar_k_u commentedThe last patch failed to apply on 9.4, so re-rolled it for 9.4.
Comment #38
bbralaSeems your reroll didn't work. Any chance you can try again?
Comment #40
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #42
borisson_I couldn't figure out a good way to reroll this, so I copied all the code from the patch to a new install and tried to get that to work, attached are the results.
Comment #43
borisson_Comment #44
borisson_Actually uploading a patch that contains what I wanted it to
Comment #45
borisson_rebased on 11.x
Comment #46
borisson_Comment #47
borisson_Comment #48
borisson_