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

Comments

Wim Leers created an issue. See original summary.

wim leers’s picture

Interestingly, 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.

effulgentsia’s picture

a internal flag (name TBD)

In #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 internal flag (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.

effulgentsia’s picture

I 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.

wim leers’s picture

@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.

wim leers’s picture

#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.

wim leers’s picture

Issue tags: +Security improvements
gabesullice’s picture

It appears quite a lot of decoupled sites are reading display configuration stored in EntityViewDisplay

Really? 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:

links: {
  displays:full: {
    href: https://example.jsonapi.dev/jsonapi/node/article/display/full.json
  },
  displays:teaser: {
    href: https://example.jsonapi.dev/jsonapi/node/article/display/teaser.json
  }
}

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.

wim leers’s picture

Personally, I consider what you're describing to be a complicated anti-pattern.

Why 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.

My hope is that […]

[…] 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. […]

I agree that all of that would be nice.

But I really just provided EntityViewDisplay as 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?

gabesullice’s picture

Why 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.

Allowing site builders to have some over the front end 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.

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?

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.

effulgentsia’s picture

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....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.

You 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.

gabesullice’s picture

@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 leave it on this list of issues, but at the lowest of priorities.

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?

wim leers’s picture

Allowing site builders to have some over the front end is desirable, but deriving that display logic from disparate and complex config entities (read: implementation details) is an anti-pattern.

Agreed! Drupal's internal data model decomposition for UI purposes makes sense for Drupal's UI code architecture, not for others' UIs.

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.

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.

I think you both would agree that most sites don't need to read config entities.

Yes. But it depends on the use case. Even if 80% doesn't need it, it may be mission-critical for 20%.

Thus, internalizing sub-properties of the very few remaining accessible config entities, is not a very high priority in my mind.

I think that makes sense.

wim leers’s picture

Priority: Major » Normal

In >6 weeks no disagreements with making this a lower priority. So, making that happen now.

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.

samuel.mortenson’s picture

I started working on this, and assumed that a good approach would be to remove LayoutEntityDisplayNormalizer and add an internal flag to the layout_builder.section config 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 when LayoutEntityDisplayNormalizer is removed?

wim leers’s picture

I suspect it's because of \Drupal\layout_builder\Field\LayoutSectionItemList::defaultAccess():

  public function defaultAccess($operation = 'view', AccountInterface $account = NULL) {
    // @todo Allow access in https://www.drupal.org/node/2942975.
    return AccessResult::forbidden();
  }
samuel.mortenson’s picture

@wim-leers Thanks for digging - I'll do my testing with a test config schema instead of Layout Builder then.

samuel.mortenson’s picture

Status: Active » Needs review
StatusFileSize
new6.25 KB

Here'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.

Status: Needs review » Needs work

The last submitted patch, 21: 3043245-21.patch, failed testing. View results

samuel.mortenson’s picture

Status: Needs work » Needs review
StatusFileSize
new4.87 KB
new2.82 KB

Should fix some of the test failures.

Status: Needs review » Needs work

The last submitted patch, 23: 3043245-23.patch, failed testing. View results

samuel.mortenson’s picture

Assigned: Unassigned » samuel.mortenson

Working on fixes.

samuel.mortenson’s picture

Status: Needs work » Needs review
StatusFileSize
new10.73 KB
new7.26 KB

Adding 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.

Status: Needs review » Needs work

The last submitted patch, 26: 3043245-26.patch, failed testing. View results

samuel.mortenson’s picture

Status: Needs work » Needs review
StatusFileSize
new16.51 KB
new7.28 KB

Worked on test fixes and added unit test coverage for \Drupal\serialization\Normalizer\ConfigEntityNormalizer.

Status: Needs review » Needs work

The last submitted patch, 28: 3043245-28.patch, failed testing. View results

samuel.mortenson’s picture

Status: Needs work » Needs review
StatusFileSize
new17.23 KB
new604 bytes

Forgot to update the config normalizer service arguments.

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.

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.

bbrala’s picture

Assigned: samuel.mortenson » Unassigned

This sounds like a good idea, but needs a review from someone with a little more knowlegde of the config system than me i think.

ranjith_kumar_k_u’s picture

StatusFileSize
new16.92 KB

The last patch failed to apply on 9.4, so re-rolled it for 9.4.

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.

bbrala’s picture

Seems your reroll didn't work. Any chance you can try again?

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.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new144 bytes

The 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.

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.

borisson_’s picture

Status: Needs work » Needs review
StatusFileSize
new0 bytes

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.

borisson_’s picture

Issue tags: +ddd2023
borisson_’s picture

StatusFileSize
new12.78 KB

Actually uploading a patch that contains what I wanted it to

borisson_’s picture

StatusFileSize
new11.71 KB

rebased on 11.x

borisson_’s picture

Status: Needs review » Needs work
borisson_’s picture

Status: Needs work » Needs review
StatusFileSize
new5.97 KB
new9.21 KB
borisson_’s picture

StatusFileSize
new736 bytes
new8.99 KB

Status: Needs review » Needs work

The last submitted patch, 48: 3043245-48.patch, failed testing. View results

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.