Problem/Motivation

When trying to update a comment via REST using:

  • method: PATCH
  • URL: /comment/1
  • Content-Type: application/json
{
  "langcode":[{"value":"en"}],
  "subject":[{"value":"New Subject"}],
  "uid":[{"target_id":"1","url":"/discasaurus.com/user/1"}],
  "status":[{"value":"1"}],
  "comment_type":[{"target_id":"comment"}],
  "default_langcode":[{"value":"1"}],
  "comment_body":[{"value":"<p>New body...</p>","format":"basic_html"}]
}

A 403 response is sent, with the following body:

{"error":"Access denied on updating field 'comment_type'."}

Removing the comment_type from the request body results in a 400 response with the following body:

{"error":"A string must be provided as a bundle value."}

Proposed resolution

In \Drupal\rest\Plugin\rest\resource\EntityResource::patch() (for updating entities via REST), retrieve an entity type's bundle key, and ignore any fields that set it.

Once that is done, you'll get an exception like this though:
LogicException: The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\rest\ResourceResponse. in Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext() (line 159 of /var/www/discasaurus.com/drupal/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php).

This is due to rdf_comment_storage_load() generating a URL that causes cacheability metadata to be bubbled. So a minor change/fix to rdf_comment_storage_load() is also necessary.

Remaining tasks

TBD

User interface changes

None.

API changes

TBD

Data model changes

TBD

CommentFileSizeAuthor
#53 interdiff-2631774-47-53.txt1.29 KBtedbow
#53 2631774-53.patch10.5 KBtedbow
#47 interdiff.txt2.52 KBdawehner
#47 2631774-47.patch10.51 KBdawehner
#40 2631774-40.png47.06 KBmarthinal
#40 interdiff-2631774-34-40.txt891 bytesmarthinal
#40 2631774-40.patch10.38 KBmarthinal
#34 interdiff.txt1.2 KBWim Leers
#34 rest_cannot_PATCH_comment-2631774-34.patch10.7 KBWim Leers
#32 interdiff.txt2.32 KBWim Leers
#32 rest_cannot_PATCH_comment-2631774-32.patch10.45 KBWim Leers
#28 interdiff.txt921 bytesWim Leers
#28 rest_cannot_PATCH_comment-2631774-28.patch10.4 KBWim Leers
#27 interdiff.txt2.62 KBWim Leers
#27 rest_cannot_PATCH_comment-2631774-27.patch10.47 KBWim Leers
#25 rest_cannot_PATCH_comment-2631774-25-test-only-FAIL.patch7.92 KBWim Leers
#21 rest_cannot_PATCH_comment-2631774-21.patch2.43 KBWim Leers
#18 interdiff.txt929 bytesWim Leers
#18 rest_cannot_PATCH_comment-2631774-18.patch3.93 KBWim Leers
#16 interdiff.txt2.02 KBWim Leers
#16 rest_cannot_PATCH_comment-2631774-16.patch2.58 KBWim Leers
#11 interdiff.txt1 KBWim Leers
#11 rest_cannot_PATCH_comment-2631774-11.patch2.11 KBWim Leers
#9 interdiff.txt938 bytesWim Leers
#9 rest_cannot_PATCH_comment-2631774-9.patch2.05 KBWim Leers
#8 rest_cannot_PATCH_comment-2631774-8.patch1.13 KBWim Leers
#2 comment-update-via-rest-2631774-1.patch933 bytestyler.frankenstein
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tyler.frankenstein created an issue. See original summary.

tyler.frankenstein’s picture

Issue summary: View changes
Status: Active » Needs review
FileSize
933 bytes

Status: Needs review » Needs work

The last submitted patch, 2: comment-update-via-rest-2631774-1.patch, failed testing.

Wim Leers’s picture

Priority: Normal » Major

Confirmed.

Wim Leers’s picture

Title: Comment Update with REST - Access denied on updating field 'comment_type' » Impossible to update Comment entity with REST (HTTP PATCH): bundle field not allowed to be updated, but EntityNormalizer::denormalize() requires it
Issue tags: +DX (Developer Experience), +REST
Wim Leers’s picture

Issue summary: View changes

This is what I wrote on IRC, shortly after I discovered this issue:

 <WimLeers> klausi: neclimdul Crell Is there anybody who has *ever* successfully PATCHed a Comment entity? \Drupal\comment\CommentAccessControlHandler::checkFieldAccess() *forbids* 'update' access to 'comment_type' (the bundle field), yet \Drupal\serialization\Normalizer\EntityNormalizer::denormalize() *requires* the bundle field to be specified. These are opposite
18:01:19 <WimLeers> requirements, and so it's AFAICT impossible to update a Comment entity via REST :(

Had a first stab at updating the issue summary. Will try to push forward @tyler.frankenstein's proposed solution.

Wim Leers’s picture

Option 0: the patch in #2

The patch doesn't work (tests fail), and only fixes the problem in the particular case of the author because the access restrictions are simply removed. That's not a proper solution.

Option 1: naïve

I would say we do something like this:

diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
index 4b4d027..856af6e 100644
--- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -144,7 +144,9 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
     }
 
     // Overwrite the received properties.
+    $entity_keys = array_values($entity->getEntityType()->getKeys());
     $langcode_key = $entity->getEntityType()->getKey('langcode');
+
     foreach ($entity->_restSubmittedFields as $field_name) {
       $field = $entity->get($field_name);
       // It is not possible to set the language to NULL as it is automatically
@@ -153,7 +155,7 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
         continue;
       }
 
-      if (!$original_entity->get($field_name)->access('edit')) {
+      if (in_array($field_name, $entity_keys) || !$original_entity->get($field_name)->access('edit')) {
         throw new AccessDeniedHttpException("Access denied on updating field '$field_name'.");
       }
       $original_entity->set($field_name, $field->getValue());

… but that means we also won't get errors anymore when trying to change the UUID, i.e. no more errors like:

{"error":"Access denied on updating field 'uuid'."}

… even though you actually are changing the UUID field.

Option 2: generalize

But, really, we do something similar for the langcode field already. So why not simply generalize it? That would look like this:

diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
index 4b4d027..a13f469 100644
--- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -144,12 +144,12 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
     }
 
     // Overwrite the received properties.
-    $langcode_key = $entity->getEntityType()->getKey('langcode');
+    $entity_keys = array_values($entity->getEntityType()->getKeys());
+
     foreach ($entity->_restSubmittedFields as $field_name) {
       $field = $entity->get($field_name);
-      // It is not possible to set the language to NULL as it is automatically
-      // re-initialized. As it must not be empty, skip it if it is.
-      if ($field_name == $langcode_key && $field->isEmpty()) {
+      // None of an entity's keys can be changed when updating an entity.
+      if (in_array($field_name, $entity_keys)) {
         continue;
       }
 

But, the same problem: no complains when trying to change the UUID field. This time around, we are not actually changing the UUID field anymore though: any entity field that is also an entity key is simply ignored. This is also in compliance with the general rule Be liberal in what you accept: https://en.wikipedia.org/wiki/Robustness_principle.

Option 3: special case the bundle field just like we special case the langcode field

 core/modules/rest/src/Plugin/rest/resource/EntityResource.php | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
index 4b4d027..6e2ca6a 100644
--- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -145,6 +145,8 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
 
     // Overwrite the received properties.
     $langcode_key = $entity->getEntityType()->getKey('langcode');
+    $bundle_key = $entity->getEntityType()->getKey('langcode');
+
     foreach ($entity->_restSubmittedFields as $field_name) {
       $field = $entity->get($field_name);
       // It is not possible to set the language to NULL as it is automatically
@@ -152,6 +154,9 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
       if ($field_name == $langcode_key && $field->isEmpty()) {
         continue;
       }
+      if ($field_name == $bundle_key) {
+        continue;
+      }
 
       if (!$original_entity->get($field_name)->access('edit')) {
         throw new AccessDeniedHttpException("Access denied on updating field '$field_name'.");

Option 4: ?

I don't think there's a significantly different option? We can't modify \Drupal\serialization\Normalizer\EntityNormalizer::denormalize() to not need the bundle in any case.

Wim Leers’s picture

Component: comment.module » rest.module
Status: Needs work » Needs review
Issue tags: +Needs tests
FileSize
1.13 KB

Option 2 actually doesn't make sense, because e.g. entity label can definitely be updated for most entities, yet option 2 would no longer allow for that.

Given all that, I think something like option 3 makes most sense: it fulfills the requirements for the EntityNormalizer to work correctly, and gets in the way as little as possible! (It only gets in the way in that you won't be getting a {"error":"Access denied on updating field 'comment_type'."} error anymore, but that was a directly conflicting requirement anyway.)

Wim Leers’s picture

So #8 allows you to update a comment (or any entity with a bundle field that you're not allowed to change). But I can confirm the problem that the original poster mentioned:

This allows the comment to be successfully updated via REST (including sending along the content_type value), but it throws a 500 error:

LogicException: The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\rest\ResourceResponse. in Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext() (line 159 of /var/www/discasaurus.com/drupal/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php).

This fixes that.

Wim Leers’s picture

Issue summary: View changes

IS updated with the proposed solution.

Wim Leers’s picture

Not every entity type has bundles.

Wim Leers’s picture

Issue tags: -REST +API-First Initiative
Wim Leers’s picture

#2405091: Cannot create user entities - {"error":"Access denied on creating field pass"} solved similar problems for creating entities. It also vastly expanded \Drupal\rest\Tests\CreateTest(), just like we should expand \Drupal\rest\Tests\UpdateTest here.

neclimdul’s picture

Re: Option 1
This was the approach I expected. But this code:

      if (in_array($field_name, $entity_keys) || !$original_entity->get($field_name)->access('edit')) {
         throw new AccessDeniedHttpException("Access denied on updating field '$field_name'.");
       }

I assumed this would look like:

      if ((in_array($field_name, $entity_keys) && $original_entity->get($field_name) == $entity->get($field_name))
        || !$original_entity->get($field_name)->access('edit')) {
        
        throw new AccessDeniedHttpException("Access denied on updating field '$field_name'.");
      }

This would still give us that error because if the values aren't the same we fall back on the access check.

Wim Leers’s picture

Status: Needs review » Needs work

That indeed makes sense. Let's do that.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
2.58 KB
2.02 KB

There, did that. And since the special handling for the langcode field is just another special case of the more general entity key field special handling we're introducing here, we can (and should) refactor that while doing this, to keep the code understandable.

Status: Needs review » Needs work

The last submitted patch, 16: rest_cannot_PATCH_comment-2631774-16.patch, failed testing.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
3.93 KB
929 bytes

Status: Needs review » Needs work

The last submitted patch, 18: rest_cannot_PATCH_comment-2631774-18.patch, failed testing.

Wim Leers’s picture

+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
--- a/core/modules/rest/src/Tests/ResourceTest.php
+++ b/core/modules/rest/src/Tests/ResourceTest.php

Oops.

This snuck in from another issue. And it also caused the sole failure.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
2.43 KB

Manually edited patch.

neclimdul’s picture

Status: Needs review » Reviewed & tested by the community

Works for me. Preemptive RTBC assuming this would should actually come back green.

larowlan’s picture

Status: Reviewed & tested by the community » Needs work

else if (isset($entity_keys['langcode']) && $field_name === $entity_keys['langcode'] && $field->isEmpty()) { + continue;
This will never evaluate TRUE because you now call array values on the keys

Also, why the rdf changes? I think they might break unsaved entity preview, there is a similar issue for users and terms #2314509: RDF module prevents viewing of unsaved users - might need a try/catch?

Wim Leers’s picture

Why RDF changes: see IS, explained there. Does not break anything, we merely prevent URL generation from bubbling metadata.

Wim Leers’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
7.92 KB

#23: nice catch! Will fix that.


Finally wrote the test coverage I said we'd need in #8. We don't ever want to find out this PITA again!

In doing so, I also noticed that this problem only occurs for the JSON normalization/serialization, not for HAL+JSON! The fact that pretty much all our test coverage for REST is only testing HAL+JSON therefore does not help inspire confidence… Even worse: the $entity->set($field_name, NULL)-style removal of values that are read-only that the existing UpdateTest does only work for HAL+JSON! For JSON, we have to resort to array_diff_key(), because it's not actually possible to unset cid, for example. So, great, we'd standardize on array_diff_key(), right? Nope! Wrong again! Doesn't work because then we'll still end up with children of _links in HAL+JSON referring to fields we're not allowed to update. These differences are because HAL uses its own normalizer.
I've now got less faith in REST test coverage than I already had.

So, I present to you, a piece of very solid test coverage, that exposes this problem in the first place, but that also shows the crazy normalizer-dependent omissions you have to do when building PATCH requests. See \Drupal\rest\Tests\UpdateTest::assertPatchEntity().


No interdiff, because this is pure test coverage to prove that HEAD is broken. In the next reroll, I will add #21.

Wim Leers’s picture

Also, please note the difference in read-only fields when comparing HAL+JSON and JSON:

HAL+JSON (read-only fields depend on hal module's normalizer)
+++ b/core/modules/rest/src/Tests/UpdateTest.php
@@ -223,7 +238,135 @@ public function testUpdateUser() {
+    $this->pass('Test case 1: PATCH comment using HAL+JSON.');
+    $comment->setSubject('Initial subject')->save();
+    $read_only_fields = [
+      'uuid',
+      'name',
+      'created',
+      'changed',
+      'status',
+      'thread',
+      'entity_type',
+      'field_name',
+      'entity_id',
+      'uid',
+    ];
JSON (read-only fields depend on serialization module's normalizer)
+++ b/core/modules/rest/src/Tests/UpdateTest.php
@@ -223,7 +238,135 @@ public function testUpdateUser() {
+    $this->pass('Test case 1: PATCH comment using JSON.');
+    $comment->setSubject('Initial subject')->save();
+    $read_only_fields = [
+      'cid', // Extra compared to HAL+JSON.
+      'uuid',
+      'pid', // Extra compared to HAL+JSON.
+      'entity_id',
+      'uid',
+      'name',
+      'homepage', // Extra compared to HAL+JSON.
+      'created',
+      'changed',
+      'status',
+      'thread',
+      'entity_type',
+      'field_name',
+    ];
Wim Leers’s picture

So, here's the fix merged in again (i.e. #21 === interdiff.txt).

Note that because the test coverage is so comprehensive, this will fail!

The test coverage starts with the given entity, tries to PATCH it, but gets a 403 because it's trying to modify read-only fields. Then it removes the first item in the list of read-only fields, tries again. Now it gets a 403 for the next read-only field. And so on. So, we comprehensively test which fields you're allowed to modify. Should this list change, then that will be a significant difference for REST API users, so it's important that we do exercise that.

Now, the patch (#21) actually makes it so that any entity key can be sent without complaints. So we won't get an error anymore for the UUID and CID fields either.

Wim Leers’s picture

This patch will be green.

It no longer removes entity key fields, because those are now safe to send (see the explanation in #27).

dawehner’s picture

Just a quick driveby review.

  1. +++ b/core/modules/rdf/rdf.module
    @@ -233,8 +233,9 @@ function rdf_comment_storage_load($comments) {
         $comment->rdf_data['date'] = rdf_rdfa_attributes($created_mapping, $comment->get('created')->first()->toArray());
    +    /** @var \Drupal\Core\Entity\EntityInterface $entity */
    

    Ideally we should typehint $comment, because then we don't have to typehint $entity, as its type follows automatically.

  2. +++ b/core/modules/rest/src/Tests/UpdateTest.php
    @@ -223,7 +238,132 @@ public function testUpdateUser() {
    +    // Create & save an entity to comment on, plus a comment.
    +    $node = Node::create([
    +      'type' => 'resttest',
    +      'title' => 'some node',
    +    ]);
    

    If possible it always seems better to test with the entity_test entity type and not a special snowflake like node.

The last submitted patch, 25: rest_cannot_PATCH_comment-2631774-25-test-only-FAIL.patch, failed testing.

The last submitted patch, 27: rest_cannot_PATCH_comment-2631774-27.patch, failed testing.

Wim Leers’s picture

  1. Well-spotted! I didn't even realize that. :) Done.
  2. This is what \Drupal\rest\Tests\RESTTestBase::setUp() and \Drupal\rest\Tests\CreateTest already do. But I think you're right of course. Fixed.
dawehner’s picture

+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -145,13 +145,21 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
+      // Entity key fields need special treatment.
+      if (in_array($field_name, $entity_keys)) {

Let's explain why. The code explains that they need special treatments already.

This is what \Drupal\rest\Tests\RESTTestBase::setUp() and \Drupal\rest\Tests\CreateTest already do. But I think you're right of course. Fixed.

No worries. I just try to push for not using node all the time, just because it seems to be more convenient.

Wim Leers’s picture

Let's explain why. The code explains that they need special treatments already.

Done.

No worries. I just try to push for not using node all the time, just because it seems to be more convenient.

+1. Thanks for pushing for that :)

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

gabesullice’s picture

Issue tags: +neworleans2016

Triaging with valthebald.

gabesullice’s picture

Version: 8.1.x-dev » 8.2.x-dev
Status: Needs review » Reviewed & tested by the community
Issue tags: -neworleans2016 +Triaged for D8 major current state

Confirmed #34 applies and resolves the issue.

larowlan’s picture

rtbc +1 - thanks all

catch’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/rdf/rdf.module
    @@ -233,9 +233,10 @@ function rdf_comment_storage_load($comments) {
    -    $comment->rdf_data['entity_uri'] = $entity->url();
    +    $comment->rdf_data['entity_uri'] = $entity->toUrl()->toString(TRUE)->getGeneratedUrl();
    

    Why's this necessary? And what's the difference? Could use a comment to explain if it really is.

  2. +++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
    @@ -151,13 +151,24 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
    +    $entity_keys = array_values($entity->getEntityType()->getKeys());
    

    Why is the array_values() necessary?

  3. +++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
    @@ -151,13 +151,24 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
    +        // Unchanged Values for entity keys same don't need access checking.
    

    Should this be:

    'Unchanged values for entity keys don't need access checking'?

marthinal’s picture

Status: Needs work » Needs review
Issue tags: +neworleans2016
FileSize
10.38 KB
891 bytes
47.06 KB

1) IMHO we need to fix #2626298: REST module must cache only responses to GET requests and then we don't need this change. In this hook (rdf_comment_storage_load()) we only need to obtain the url... and well, a patch request should not be cached anyway. I've tested manually applying that patch and the Exception disappears.

2) There's an empty value (see the attached image) and we only avoid to check some values. To be honest I'm not sure 100% if makes sense this option or maybe simply verify langcode + bundle_key.

3) Done.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

1) IMHO we need to fix #2626298: REST module must cache only GET requests. and then we don't need this change. In this hook (rdf_comment_storage_load()) we only need to obtain the url... and well, a patch request should not be cached anyway. I've tested manually applying that patch and the Exception disappears.

Conceptually it would be still nice to do that. Giving good examples to people is the right thing to do. On the other hand your are right about that. The other patch fixes most proabably the problem.

For me this is ready for it.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/rdf/rdf.module
@@ -233,9 +233,10 @@ function rdf_comment_storage_load($comments) {
-    $comment->rdf_data['entity_uri'] = $entity->url();
+    $comment->rdf_data['entity_uri'] = $entity->toUrl()->toString(TRUE)->getGeneratedUrl();

So given @catch's comment and the responses don't we need an @todo here?

dawehner’s picture

What about adding something like
// We are in a storage load hook, which is outside of a render context, so we should avoid to bubble metadata up, which <code>$entity->url() would.
?

xjm’s picture

(Updating issue credit for the major triage sprint. Thanks @gabesullice for helping triage this!)

valthebald’s picture

Was triaging the issue during DrupalCon NOLA Friday sprint with @gabesullice

xjm’s picture

(Added credit.)

dawehner’s picture

Status: Needs work » Needs review
FileSize
10.51 KB
2.52 KB

Let's just fix that. I also changed the "assert" function to use a normal function. There is no clear abstraction happening in this function but rather a set of operations and some assertions in there.

effulgentsia’s picture

Issue tags: +Triaged core major

Discussed with @alexpott, @catch, @xjm, @webchick, and @Cottser, and we agreed this is Major priority, so tagging. As per the recently updated bullet points in https://www.drupal.org/core/issue-priority#major-bug, this is a "feature unusable with no workaround".

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

I think all feedback has been addressed.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -146,13 +146,24 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
+    $entity_keys = array_values($entity->getEntityType()->getKeys());
...
+      if (in_array($field_name, $entity_keys)) {

I still don't get the need for array_values() here. Since using it does not remove the empty value. If we want to do that we should use array_filter. Not sure it is worth it. Plus I'd change the in_array to use the strict comparison option just to be type safe.

alexpott’s picture

+++ b/core/modules/rest/src/Tests/RESTTestBase.php
@@ -261,10 +261,15 @@ protected function enableService($resource_type, $method = 'GET', $format = NULL
+      if (is_array($format)) {
+        $settings[$resource_type][$method]['supported_formats'] = $format;
+      }

Do we need to protect against empty arrays here? And fallback to the default format if so?

Wim Leers’s picture

#50: oops, sorry, I thought that was addressed. I looked at the various patches here. Turns out I proposed this in #7. AFAICT I did it originally just to stress we only want the entity keys for a particular entity type. But keeping the keys would be totally harmless:

$keys = ['id' => 'nid' , …];
array_values($keys) === ['nid', …];

So, +1 to remove array_values().


#51: the reason is that we want to keep BC for enableService() for custom/contrib tests. It used to only allow a single format to be passed in, and otherwise default to "the default format" (for a particular test). This patch is making it possible to specify multiple formats.
We don't need to protect against empty arrays: if somebody specifies that, then it's intentional (and probably wrong).
IOW: we don't need to babybsit crappy/broken tests, but we need to make sure we retain BC.

tedbow’s picture

Status: Needs work » Needs review
FileSize
10.5 KB
1.29 KB

Fixed #50

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Nice, better code!

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

I think this fix is BC compatible and therefore should be committed to 8.1.x as well since this is a major bug fix. Committed 829fe8a and pushed to 8.1.x and 8.2.x. Thanks!

diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
index d6fdcd1..63857e4 100644
--- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -161,7 +161,7 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
         }
         // It is not possible to set the language to NULL as it is automatically
         // re-initialized. As it must not be empty, skip it if it is.
-        else if (isset($entity_keys['langcode']) && $field_name === $entity_keys['langcode'] && $field->isEmpty()) {
+        elseif (isset($entity_keys['langcode']) && $field_name === $entity_keys['langcode'] && $field->isEmpty()) {
           continue;
         }
       }

Coding standards fix on commit.

  • alexpott committed 6749853 on 8.2.x
    Issue #2631774 by Wim Leers, marthinal, dawehner, tedbow, tyler....

  • alexpott committed 829fe8a on 8.1.x
    Issue #2631774 by Wim Leers, marthinal, dawehner, tedbow, tyler....
Wim Leers’s picture

YAY! Took almost 4 months, but so happy to finally see this in. This was a huge, show-stopping REST bug, IMO bordering on critical.

Thanks for also committing it to Drupal 8.1!

Wim Leers’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

webchick’s picture

Issue tags: +8.2.0 release notes

This sounds like it allows developers to use comments as first-class citizens, so worthy of release note mention.

kalinchernev’s picture

Draft change record created.
Edit: I was following the guide and I'm unsure whether draft is correct when the patch is already merged.

pranilkochar’s picture

Drupal 8 supports OAuth 2.0 as na authentication mechanism?

Wim Leers’s picture

I just noticed the CR was never published. Just did that: https://www.drupal.org/node/2778563.

jhonatanfdez’s picture

Proposed resolution

method: PATCH
URL: drupal8/comment/1
Content-Type: application/json

{ 
"comment_type":[{"target_id":"comment"}],
"uid":[{"target_id":7}], 
  "subject":[{"value":"Editado Comentario"}],
  "comment_body":[
    {"value":"<p>Comentario</p>","format":"basic_html"}
  ]
}

note: the user must have the administrator role