Mercurial > hg > isophonics-drupal-site
comparison core/modules/jsonapi/tests/src/Functional/UserTest.php @ 18:af1871eacc83
Update to Drupal core 8.7.1
author | Chris Cannam |
---|---|
date | Thu, 09 May 2019 15:33:08 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
17:129ea1e6d783 | 18:af1871eacc83 |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\Tests\jsonapi\Functional; | |
4 | |
5 use Drupal\Component\Serialization\Json; | |
6 use Drupal\Component\Utility\NestedArray; | |
7 use Drupal\Core\Cache\Cache; | |
8 use Drupal\Core\Url; | |
9 use Drupal\field\Entity\FieldConfig; | |
10 use Drupal\field\Entity\FieldStorageConfig; | |
11 use Drupal\node\Entity\Node; | |
12 use Drupal\user\Entity\User; | |
13 use GuzzleHttp\RequestOptions; | |
14 | |
15 /** | |
16 * JSON:API integration test for the "User" content entity type. | |
17 * | |
18 * @group jsonapi | |
19 */ | |
20 class UserTest extends ResourceTestBase { | |
21 | |
22 /** | |
23 * {@inheritdoc} | |
24 */ | |
25 public static $modules = ['user']; | |
26 | |
27 /** | |
28 * {@inheritdoc} | |
29 */ | |
30 protected static $entityTypeId = 'user'; | |
31 | |
32 /** | |
33 * {@inheritdoc} | |
34 */ | |
35 protected static $resourceTypeName = 'user--user'; | |
36 | |
37 /** | |
38 * {@inheritdoc} | |
39 */ | |
40 protected static $patchProtectedFieldNames = [ | |
41 'changed' => NULL, | |
42 ]; | |
43 | |
44 /** | |
45 * {@inheritdoc} | |
46 */ | |
47 protected static $anonymousUsersCanViewLabels = TRUE; | |
48 | |
49 /** | |
50 * {@inheritdoc} | |
51 * | |
52 * @var \Drupal\taxonomy\TermInterface | |
53 */ | |
54 protected $entity; | |
55 | |
56 /** | |
57 * {@inheritdoc} | |
58 */ | |
59 protected static $labelFieldName = 'name'; | |
60 | |
61 /** | |
62 * {@inheritdoc} | |
63 */ | |
64 protected static $firstCreatedEntityId = 4; | |
65 | |
66 /** | |
67 * {@inheritdoc} | |
68 */ | |
69 protected static $secondCreatedEntityId = 5; | |
70 | |
71 /** | |
72 * {@inheritdoc} | |
73 */ | |
74 protected function setUpAuthorization($method) { | |
75 // @todo Remove this in | |
76 $this->grantPermissionsToTestedRole(['access content']); | |
77 | |
78 switch ($method) { | |
79 case 'GET': | |
80 $this->grantPermissionsToTestedRole(['access user profiles']); | |
81 break; | |
82 | |
83 case 'POST': | |
84 case 'PATCH': | |
85 case 'DELETE': | |
86 $this->grantPermissionsToTestedRole(['administer users']); | |
87 break; | |
88 } | |
89 } | |
90 | |
91 /** | |
92 * {@inheritdoc} | |
93 */ | |
94 protected function createEntity() { | |
95 // Create a "Llama" user. | |
96 $user = User::create(['created' => 123456789]); | |
97 $user->setUsername('Llama') | |
98 ->setChangedTime(123456789) | |
99 ->activate() | |
100 ->save(); | |
101 | |
102 return $user; | |
103 } | |
104 | |
105 /** | |
106 * {@inheritdoc} | |
107 */ | |
108 protected function createAnotherEntity($key) { | |
109 /** @var \Drupal\user\UserInterface $user */ | |
110 $user = $this->getEntityDuplicate($this->entity, $key); | |
111 $user->setUsername($user->label() . '_' . $key); | |
112 $user->setEmail("$key@example.com"); | |
113 $user->save(); | |
114 return $user; | |
115 } | |
116 | |
117 /** | |
118 * {@inheritdoc} | |
119 */ | |
120 protected function getExpectedDocument() { | |
121 $self_url = Url::fromUri('base:/jsonapi/user/user/' . $this->entity->uuid())->setAbsolute()->toString(TRUE)->getGeneratedUrl(); | |
122 return [ | |
123 'jsonapi' => [ | |
124 'meta' => [ | |
125 'links' => [ | |
126 'self' => ['href' => 'http://jsonapi.org/format/1.0/'], | |
127 ], | |
128 ], | |
129 'version' => '1.0', | |
130 ], | |
131 'links' => [ | |
132 'self' => ['href' => $self_url], | |
133 ], | |
134 'data' => [ | |
135 'id' => $this->entity->uuid(), | |
136 'type' => 'user--user', | |
137 'links' => [ | |
138 'self' => ['href' => $self_url], | |
139 ], | |
140 'attributes' => [ | |
141 'created' => '1973-11-29T21:33:09+00:00', | |
142 'changed' => (new \DateTime())->setTimestamp($this->entity->getChangedTime())->setTimezone(new \DateTimeZone('UTC'))->format(\DateTime::RFC3339), | |
143 'default_langcode' => TRUE, | |
144 'langcode' => 'en', | |
145 'name' => 'Llama', | |
146 'drupal_internal__uid' => 3, | |
147 ], | |
148 ], | |
149 ]; | |
150 } | |
151 | |
152 /** | |
153 * {@inheritdoc} | |
154 */ | |
155 protected function getExpectedCacheContexts(array $sparse_fieldset = NULL) { | |
156 $cache_contexts = parent::getExpectedCacheContexts($sparse_fieldset); | |
157 if ($sparse_fieldset === NULL || in_array('mail', $sparse_fieldset)) { | |
158 $cache_contexts = Cache::mergeContexts($cache_contexts, ['user']); | |
159 } | |
160 return $cache_contexts; | |
161 } | |
162 | |
163 /** | |
164 * {@inheritdoc} | |
165 */ | |
166 protected function getPostDocument() { | |
167 return [ | |
168 'data' => [ | |
169 'type' => 'user--user', | |
170 'attributes' => [ | |
171 'name' => 'Dramallama', | |
172 ], | |
173 ], | |
174 ]; | |
175 } | |
176 | |
177 /** | |
178 * {@inheritdoc} | |
179 */ | |
180 protected function getExpectedUnauthorizedAccessMessage($method) { | |
181 switch ($method) { | |
182 case 'GET': | |
183 return "The 'access user profiles' permission is required and the user must be active."; | |
184 | |
185 case 'PATCH': | |
186 return "Users can only update their own account, unless they have the 'administer users' permission."; | |
187 | |
188 case 'DELETE': | |
189 return "The 'cancel account' permission is required."; | |
190 | |
191 default: | |
192 return parent::getExpectedUnauthorizedAccessMessage($method); | |
193 } | |
194 } | |
195 | |
196 /** | |
197 * Tests PATCHing security-sensitive base fields of the logged in account. | |
198 */ | |
199 public function testPatchDxForSecuritySensitiveBaseFields() { | |
200 // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463. | |
201 $url = Url::fromRoute(sprintf('jsonapi.user--user.individual'), ['entity' => $this->account->uuid()]); | |
202 /* $url = $this->account->toUrl('jsonapi'); */ | |
203 | |
204 $original_normalization = $this->normalize($this->account, $url); | |
205 // @todo Remove the array_diff_key() call in https://www.drupal.org/node/2821077. | |
206 $original_normalization['data']['attributes'] = array_diff_key( | |
207 $original_normalization['data']['attributes'], | |
208 ['created' => TRUE, 'changed' => TRUE, 'name' => TRUE] | |
209 ); | |
210 | |
211 // Since this test must be performed by the user that is being modified, | |
212 // we must use $this->account, not $this->entity. | |
213 $request_options = []; | |
214 $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json'; | |
215 $request_options[RequestOptions::HEADERS]['Content-Type'] = 'application/vnd.api+json'; | |
216 $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); | |
217 | |
218 // Test case 1: changing email. | |
219 $normalization = $original_normalization; | |
220 $normalization['data']['attributes']['mail'] = 'new-email@example.com'; | |
221 $request_options[RequestOptions::BODY] = Json::encode($normalization); | |
222 | |
223 // DX: 405 when read-only mode is enabled. | |
224 $response = $this->request('PATCH', $url, $request_options); | |
225 $this->assertResourceErrorResponse(405, sprintf("JSON:API is configured to accept only read operations. Site administrators can configure this at %s.", Url::fromUri('base:/admin/config/services/jsonapi')->setAbsolute()->toString(TRUE)->getGeneratedUrl()), $url, $response); | |
226 $this->assertSame(['GET'], $response->getHeader('Allow')); | |
227 | |
228 $this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE); | |
229 | |
230 // DX: 422 when changing email without providing the password. | |
231 $response = $this->request('PATCH', $url, $request_options); | |
232 $this->assertResourceErrorResponse(422, 'mail: Your current password is missing or incorrect; it\'s required to change the Email.', NULL, $response, '/data/attributes/mail'); | |
233 | |
234 $normalization['data']['attributes']['pass']['existing'] = 'wrong'; | |
235 $request_options[RequestOptions::BODY] = Json::encode($normalization); | |
236 | |
237 // DX: 422 when changing email while providing a wrong password. | |
238 $response = $this->request('PATCH', $url, $request_options); | |
239 $this->assertResourceErrorResponse(422, 'mail: Your current password is missing or incorrect; it\'s required to change the Email.', NULL, $response, '/data/attributes/mail'); | |
240 | |
241 $normalization['data']['attributes']['pass']['existing'] = $this->account->passRaw; | |
242 $request_options[RequestOptions::BODY] = Json::encode($normalization); | |
243 | |
244 // 200 for well-formed request. | |
245 $response = $this->request('PATCH', $url, $request_options); | |
246 $this->assertResourceResponse(200, FALSE, $response); | |
247 | |
248 // Test case 2: changing password. | |
249 $normalization = $original_normalization; | |
250 $normalization['data']['attributes']['mail'] = 'new-email@example.com'; | |
251 $new_password = $this->randomString(); | |
252 $normalization['data']['attributes']['pass']['value'] = $new_password; | |
253 $request_options[RequestOptions::BODY] = Json::encode($normalization); | |
254 | |
255 // DX: 422 when changing password without providing the current password. | |
256 $response = $this->request('PATCH', $url, $request_options); | |
257 $this->assertResourceErrorResponse(422, 'pass: Your current password is missing or incorrect; it\'s required to change the Password.', NULL, $response, '/data/attributes/pass'); | |
258 | |
259 $normalization['data']['attributes']['pass']['existing'] = $this->account->passRaw; | |
260 $request_options[RequestOptions::BODY] = Json::encode($normalization); | |
261 | |
262 // 200 for well-formed request. | |
263 $response = $this->request('PATCH', $url, $request_options); | |
264 $this->assertResourceResponse(200, FALSE, $response); | |
265 | |
266 // Verify that we can log in with the new password. | |
267 $this->assertRpcLogin($this->account->getAccountName(), $new_password); | |
268 | |
269 // Update password in $this->account, prepare for future requests. | |
270 $this->account->passRaw = $new_password; | |
271 $request_options = []; | |
272 $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json'; | |
273 $request_options[RequestOptions::HEADERS]['Content-Type'] = 'application/vnd.api+json'; | |
274 $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); | |
275 | |
276 // Test case 3: changing name. | |
277 $normalization = $original_normalization; | |
278 $normalization['data']['attributes']['mail'] = 'new-email@example.com'; | |
279 $normalization['data']['attributes']['pass']['existing'] = $new_password; | |
280 $normalization['data']['attributes']['name'] = 'Cooler Llama'; | |
281 $request_options[RequestOptions::BODY] = Json::encode($normalization); | |
282 | |
283 // DX: 403 when modifying username without required permission. | |
284 $response = $this->request('PATCH', $url, $request_options); | |
285 $this->assertResourceErrorResponse(403, 'The current user is not allowed to PATCH the selected field (name).', $url, $response, '/data/attributes/name'); | |
286 | |
287 $this->grantPermissionsToTestedRole(['change own username']); | |
288 | |
289 // 200 for well-formed request. | |
290 $response = $this->request('PATCH', $url, $request_options); | |
291 $this->assertResourceResponse(200, FALSE, $response); | |
292 | |
293 // Verify that we can log in with the new username. | |
294 $this->assertRpcLogin('Cooler Llama', $new_password); | |
295 } | |
296 | |
297 /** | |
298 * Verifies that logging in with the given username and password works. | |
299 * | |
300 * @param string $username | |
301 * The username to log in with. | |
302 * @param string $password | |
303 * The password to log in with. | |
304 */ | |
305 protected function assertRpcLogin($username, $password) { | |
306 $request_body = [ | |
307 'name' => $username, | |
308 'pass' => $password, | |
309 ]; | |
310 $request_options = [ | |
311 RequestOptions::HEADERS => [], | |
312 RequestOptions::BODY => Json::encode($request_body), | |
313 ]; | |
314 $response = $this->request('POST', Url::fromRoute('user.login.http')->setRouteParameter('_format', 'json'), $request_options); | |
315 $this->assertSame(200, $response->getStatusCode()); | |
316 } | |
317 | |
318 /** | |
319 * Tests PATCHing security-sensitive base fields to change other users. | |
320 */ | |
321 public function testPatchSecurityOtherUser() { | |
322 // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463. | |
323 $url = Url::fromRoute(sprintf('jsonapi.user--user.individual'), ['entity' => $this->account->uuid()]); | |
324 /* $url = $this->account->toUrl('jsonapi'); */ | |
325 | |
326 $original_normalization = $this->normalize($this->account, $url); | |
327 | |
328 // Since this test must be performed by the user that is being modified, | |
329 // we must use $this->account, not $this->entity. | |
330 $request_options = []; | |
331 $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json'; | |
332 $request_options[RequestOptions::HEADERS]['Content-Type'] = 'application/vnd.api+json'; | |
333 $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); | |
334 | |
335 $normalization = $original_normalization; | |
336 $normalization['data']['attributes']['mail'] = 'new-email@example.com'; | |
337 $request_options[RequestOptions::BODY] = Json::encode($normalization); | |
338 | |
339 // DX: 405 when read-only mode is enabled. | |
340 $response = $this->request('PATCH', $url, $request_options); | |
341 $this->assertResourceErrorResponse(405, sprintf("JSON:API is configured to accept only read operations. Site administrators can configure this at %s.", Url::fromUri('base:/admin/config/services/jsonapi')->setAbsolute()->toString(TRUE)->getGeneratedUrl()), $url, $response); | |
342 $this->assertSame(['GET'], $response->getHeader('Allow')); | |
343 | |
344 $this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE); | |
345 | |
346 // Try changing user 1's email. | |
347 $user1 = $original_normalization; | |
348 $user1['data']['attributes']['mail'] = 'another_email_address@example.com'; | |
349 $user1['data']['attributes']['uid'] = 1; | |
350 $user1['data']['attributes']['name'] = 'another_user_name'; | |
351 $user1['data']['attributes']['pass']['existing'] = $this->account->passRaw; | |
352 $request_options[RequestOptions::BODY] = Json::encode($user1); | |
353 $response = $this->request('PATCH', $url, $request_options); | |
354 // Ensure the email address has not changed. | |
355 $this->assertEquals('admin@example.com', $this->entityStorage->loadUnchanged(1)->getEmail()); | |
356 $this->assertResourceErrorResponse(403, 'The current user is not allowed to PATCH the selected field (uid). The entity ID cannot be changed.', $url, $response, '/data/attributes/uid'); | |
357 } | |
358 | |
359 /** | |
360 * Tests GETting privacy-sensitive base fields. | |
361 */ | |
362 public function testGetMailFieldOnlyVisibleToOwner() { | |
363 // Create user B, with the same roles (and hence permissions) as user A. | |
364 $user_a = $this->account; | |
365 $pass = user_password(); | |
366 $user_b = User::create([ | |
367 'name' => 'sibling-of-' . $user_a->getAccountName(), | |
368 'mail' => 'sibling-of-' . $user_a->getAccountName() . '@example.com', | |
369 'pass' => $pass, | |
370 'status' => 1, | |
371 'roles' => $user_a->getRoles(), | |
372 ]); | |
373 $user_b->save(); | |
374 $user_b->passRaw = $pass; | |
375 | |
376 // Grant permission to role that both users use. | |
377 $this->grantPermissionsToTestedRole(['access user profiles']); | |
378 | |
379 $collection_url = Url::fromRoute('jsonapi.user--user.collection', [], ['query' => ['sort' => 'drupal_internal__uid']]); | |
380 // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463. | |
381 $user_a_url = Url::fromRoute(sprintf('jsonapi.user--user.individual'), ['entity' => $user_a->uuid()]); | |
382 /* $user_a_url = $user_a->toUrl('jsonapi'); */ | |
383 $request_options = []; | |
384 $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json'; | |
385 $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); | |
386 | |
387 // Viewing user A as user A: "mail" field is accessible. | |
388 $response = $this->request('GET', $user_a_url, $request_options); | |
389 $doc = Json::decode((string) $response->getBody()); | |
390 $this->assertArrayHasKey('mail', $doc['data']['attributes']); | |
391 // Also when looking at the collection. | |
392 $response = $this->request('GET', $collection_url, $request_options); | |
393 $doc = Json::decode((string) $response->getBody()); | |
394 $this->assertSame($user_a->uuid(), $doc['data']['2']['id']); | |
395 $this->assertArrayHasKey('mail', $doc['data'][2]['attributes'], "Own user--user resource's 'mail' field is visible."); | |
396 $this->assertSame($user_b->uuid(), $doc['data'][count($doc['data']) - 1]['id']); | |
397 $this->assertArrayNotHasKey('mail', $doc['data'][count($doc['data']) - 1]['attributes']); | |
398 | |
399 // Now request the same URLs, but as user B (same roles/permissions). | |
400 $this->account = $user_b; | |
401 $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); | |
402 // Viewing user A as user B: "mail" field should be inaccessible. | |
403 $response = $this->request('GET', $user_a_url, $request_options); | |
404 $doc = Json::decode((string) $response->getBody()); | |
405 $this->assertArrayNotHasKey('mail', $doc['data']['attributes']); | |
406 // Also when looking at the collection. | |
407 $response = $this->request('GET', $collection_url, $request_options); | |
408 $doc = Json::decode((string) $response->getBody()); | |
409 $this->assertSame($user_a->uuid(), $doc['data']['2']['id']); | |
410 $this->assertArrayNotHasKey('mail', $doc['data'][2]['attributes']); | |
411 $this->assertSame($user_b->uuid(), $doc['data'][count($doc['data']) - 1]['id']); | |
412 $this->assertArrayHasKey('mail', $doc['data'][count($doc['data']) - 1]['attributes']); | |
413 } | |
414 | |
415 /** | |
416 * Test good error DX when trying to filter users by role. | |
417 */ | |
418 public function testQueryInvolvingRoles() { | |
419 $this->setUpAuthorization('GET'); | |
420 | |
421 $collection_url = Url::fromRoute('jsonapi.user--user.collection', [], ['query' => ['filter[roles.id][value]' => 'e9b1de3f-9517-4c27-bef0-0301229de792']]); | |
422 $request_options = []; | |
423 $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json'; | |
424 $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); | |
425 | |
426 // The 'administer users' permission is required to filter by role entities. | |
427 $this->grantPermissionsToTestedRole(['administer users']); | |
428 | |
429 $response = $this->request('GET', $collection_url, $request_options); | |
430 $expected_cache_contexts = ['url.path', 'url.query_args:filter', 'url.site']; | |
431 $this->assertResourceErrorResponse(400, "Filtering on config entities is not supported by Drupal's entity API. You tried to filter on a Role config entity.", $collection_url, $response, FALSE, ['4xx-response', 'http_response'], $expected_cache_contexts, FALSE, 'MISS'); | |
432 } | |
433 | |
434 /** | |
435 * Tests that the collection contains the anonymous user. | |
436 */ | |
437 public function testCollectionContainsAnonymousUser() { | |
438 $url = Url::fromRoute('jsonapi.user--user.collection', [], ['query' => ['sort' => 'drupal_internal__uid']]); | |
439 $request_options = []; | |
440 $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json'; | |
441 $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); | |
442 | |
443 $response = $this->request('GET', $url, $request_options); | |
444 $doc = Json::decode((string) $response->getBody()); | |
445 | |
446 $this->assertCount(4, $doc['data']); | |
447 $this->assertSame(User::load(0)->uuid(), $doc['data'][0]['id']); | |
448 $this->assertSame('Anonymous', $doc['data'][0]['attributes']['name']); | |
449 } | |
450 | |
451 /** | |
452 * {@inheritdoc} | |
453 */ | |
454 public function testCollectionFilterAccess() { | |
455 // Set up data model. | |
456 $this->assertTrue($this->container->get('module_installer')->install(['node'], TRUE), 'Installed modules.'); | |
457 FieldStorageConfig::create([ | |
458 'entity_type' => static::$entityTypeId, | |
459 'field_name' => 'field_favorite_animal', | |
460 'type' => 'string', | |
461 ]) | |
462 ->setCardinality(1) | |
463 ->save(); | |
464 FieldConfig::create([ | |
465 'entity_type' => static::$entityTypeId, | |
466 'field_name' => 'field_favorite_animal', | |
467 'bundle' => 'user', | |
468 ]) | |
469 ->setLabel('Test field') | |
470 ->setTranslatable(FALSE) | |
471 ->save(); | |
472 $this->drupalCreateContentType(['type' => 'x']); | |
473 $this->rebuildAll(); | |
474 $this->grantPermissionsToTestedRole(['access content']); | |
475 | |
476 // Create data. | |
477 $user_a = User::create([])->setUsername('A')->activate(); | |
478 $user_a->save(); | |
479 $user_b = User::create([])->setUsername('B')->set('field_favorite_animal', 'stegosaurus')->block(); | |
480 $user_b->save(); | |
481 $node_a = Node::create(['type' => 'x'])->setTitle('Owned by A')->setOwner($user_a); | |
482 $node_a->save(); | |
483 $node_b = Node::create(['type' => 'x'])->setTitle('Owned by B')->setOwner($user_b); | |
484 $node_b->save(); | |
485 $node_anon_1 = Node::create(['type' => 'x'])->setTitle('Owned by anon #1')->setOwnerId(0); | |
486 $node_anon_1->save(); | |
487 $node_anon_2 = Node::create(['type' => 'x'])->setTitle('Owned by anon #2')->setOwnerId(0); | |
488 $node_anon_2->save(); | |
489 $node_auth_1 = Node::create(['type' => 'x'])->setTitle('Owned by auth #1')->setOwner($this->account); | |
490 $node_auth_1->save(); | |
491 | |
492 $favorite_animal_test_url = Url::fromRoute('jsonapi.user--user.collection')->setOption('query', ['filter[field_favorite_animal]' => 'stegosaurus']); | |
493 | |
494 // Test. | |
495 $collection_url = Url::fromRoute('jsonapi.node--x.collection'); | |
496 $request_options = []; | |
497 $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json'; | |
498 $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions()); | |
499 // ?filter[uid.id]=OWN_UUID requires no permissions: 1 result. | |
500 $response = $this->request('GET', $collection_url->setOption('query', ['filter[uid.id]' => $this->account->uuid()]), $request_options); | |
501 $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'user.permissions'); | |
502 $doc = Json::decode((string) $response->getBody()); | |
503 $this->assertCount(1, $doc['data']); | |
504 $this->assertSame($node_auth_1->uuid(), $doc['data'][0]['id']); | |
505 // ?filter[uid.id]=ANONYMOUS_UUID: 0 results. | |
506 $response = $this->request('GET', $collection_url->setOption('query', ['filter[uid.id]' => User::load(0)->uuid()]), $request_options); | |
507 $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'user.permissions'); | |
508 $doc = Json::decode((string) $response->getBody()); | |
509 $this->assertCount(0, $doc['data']); | |
510 // ?filter[uid.name]=A: 0 results. | |
511 $response = $this->request('GET', $collection_url->setOption('query', ['filter[uid.name]' => 'A']), $request_options); | |
512 $doc = Json::decode((string) $response->getBody()); | |
513 $this->assertCount(0, $doc['data']); | |
514 // /jsonapi/user/user?filter[field_favorite_animal]: 0 results. | |
515 $response = $this->request('GET', $favorite_animal_test_url, $request_options); | |
516 $this->assertSame(200, $response->getStatusCode()); | |
517 $doc = Json::decode((string) $response->getBody()); | |
518 $this->assertCount(0, $doc['data']); | |
519 // Grant "view" permission. | |
520 $this->grantPermissionsToTestedRole(['access user profiles']); | |
521 // ?filter[uid.id]=ANONYMOUS_UUID: 0 results. | |
522 $response = $this->request('GET', $collection_url->setOption('query', ['filter[uid.id]' => User::load(0)->uuid()]), $request_options); | |
523 $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'user.permissions'); | |
524 $doc = Json::decode((string) $response->getBody()); | |
525 $this->assertCount(0, $doc['data']); | |
526 // ?filter[uid.name]=A: 1 result since user A is active. | |
527 $response = $this->request('GET', $collection_url->setOption('query', ['filter[uid.name]' => 'A']), $request_options); | |
528 $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'user.permissions'); | |
529 $doc = Json::decode((string) $response->getBody()); | |
530 $this->assertCount(1, $doc['data']); | |
531 $this->assertSame($node_a->uuid(), $doc['data'][0]['id']); | |
532 // ?filter[uid.name]=B: 0 results since user B is blocked. | |
533 $response = $this->request('GET', $collection_url->setOption('query', ['filter[uid.name]' => 'B']), $request_options); | |
534 $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'user.permissions'); | |
535 $doc = Json::decode((string) $response->getBody()); | |
536 $this->assertCount(0, $doc['data']); | |
537 // /jsonapi/user/user?filter[field_favorite_animal]: 0 results. | |
538 $response = $this->request('GET', $favorite_animal_test_url, $request_options); | |
539 $this->assertSame(200, $response->getStatusCode()); | |
540 $doc = Json::decode((string) $response->getBody()); | |
541 $this->assertCount(0, $doc['data']); | |
542 // Grant "admin" permission. | |
543 $this->grantPermissionsToTestedRole(['administer users']); | |
544 // ?filter[uid.name]=B: 1 result. | |
545 $response = $this->request('GET', $collection_url->setOption('query', ['filter[uid.name]' => 'B']), $request_options); | |
546 $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'user.permissions'); | |
547 $doc = Json::decode((string) $response->getBody()); | |
548 $this->assertCount(1, $doc['data']); | |
549 $this->assertSame($node_b->uuid(), $doc['data'][0]['id']); | |
550 // /jsonapi/user/user?filter[field_favorite_animal]: 1 result. | |
551 $response = $this->request('GET', $favorite_animal_test_url, $request_options); | |
552 $this->assertSame(200, $response->getStatusCode()); | |
553 $doc = Json::decode((string) $response->getBody()); | |
554 $this->assertCount(1, $doc['data']); | |
555 $this->assertSame($user_b->uuid(), $doc['data'][0]['id']); | |
556 } | |
557 | |
558 } |