Problem/Motivation
While working on #2930028-50: Comprehensive JSON API integration test coverage phase 1: for every entity type, individual resources only, I noticed that I was able to POST this:
[
'data' => [
'type' => 'comment--comment',
'attributes' => [
'entity_id' => 345,
'entity_type' => 'entity_test',
'field_name' => 'comment',
'subject' => 'Dramallama',
'comment_body' => [
'value' => 'Llamas are awesome.',
'format' => 'plain_text',
],
],
],
]
But that should not have been allowed: entity_id is a relationship field and thus should have been under the relationships key! Why is evident from both the JSON API spec and the response: what you get back is of the form
[
'data' => [
'type' => 'comment--comment',
'attributes' => [
'entity_type' => 'entity_test',
'field_name' => 'comment',
'subject' => 'Dramallama',
'comment_body' => [
'value' => 'Llamas are awesome.',
'format' => 'plain_text',
],
],
'relationships' => [
'entity_id' => [
'data' => [
'type' => 'entity_test--bar',
'id' => '<some UUID>',
],
],
],
],
]
Proposed resolution
Add validation in \Drupal\jsonapi\Normalizer\JsonApiDocumentTopLevelNormalizer::denormalize().
See http://jsonapi.org/format/#crud-creating.
Remaining tasks
TBD
User interface changes
None.
API changes
None. (Well, requests getting this wrong may now get HTTP 4xx responses, but this is per the JSON API spec and per the JSON API Drupal module's documentation: we reserve the right to fix spec compliance bugs without introducing BC layers for invalid calls.)
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #16 | 2942549-16.patch | 6.93 KB | gabesullice |
| #16 | interdiff-2942549-11-16.txt | 2.09 KB | gabesullice |
| #11 | 2942549-11.patch | 5.61 KB | gabesullice |
| #11 | interdiff-2942549-9-11.txt | 2.23 KB | gabesullice |
| #9 | 2942549-9.patch | 5.94 KB | gabesullice |
Comments
Comment #2
wim leersComment #3
wim leersPer #2952293-27: Branch next major: version 2, requiring Drupal core >=8.5 and #2952293-28: Branch next major: version 2, requiring Drupal core >=8.5, moving this to v2.
Comment #4
wim leersThis still needs explicit test coverage, but if I modify
CommentTestto do what's described in the IS, I can simulate a test that should fail.This then at least has some initial patch!
An explicit test probably belongs in
\Drupal\Tests\jsonapi\Functional\JsonApiRegressionTest, because not every entity type has a relationship.Comment #5
gabesullicestill NW
Comment #6
gabesulliceI think @Wim Leers just set this to NR to get a testbot run, but maybe it was for a +1 on the approach.
In that case, +1!
Comment #7
wim leers#6: exactly :)
Comment #8
gabesulliceComment #9
gabesulliceRerolled. Added explicit tests. Moved the check to
validateRequestBodyand made that a static call, since it's a static method.Still need to handle internal vs public fields.
Comment #10
gabesullices/that/the
s/that/the
This is a copy/paste mistake.
Comment #11
gabesulliceTurns out that there is no need to deal with internal/public fields. The received values should already be internal and
array_keys($resource_type->getRelatableResourceTypes())also returns public fields.Comment #13
wim leers🤔
We're now accessing this first, then calling
::validateRequestBody(). But::validateRequestBody()is also validating the presence of this…❤️
Comment #14
gabesulliceEpically confusing typo. They both are dealing with public field names.
Yup... silly mistake. Let's just use
$context['resource_type']rather than dynamically loading the type from the document value.Comment #15
wim leers👍
Comment #16
gabesulliceDone.
Comment #17
wim leersComment #19
gabesullice🎉
Comment #20
wim leers👏