Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / core / modules / rest / tests / src / Functional / EntityResource / User / UserResourceTestBase.php
index d758cf660869a9647241cca2d026964585c01a55..7974cba7306ec32634618a86246b8b3cba58b936 100644 (file)
@@ -79,6 +79,17 @@ abstract class UserResourceTestBase extends EntityResourceTestBase {
     return $user;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function createAnotherEntity() {
+    /** @var \Drupal\user\UserInterface $user */
+    $user = $this->entity->createDuplicate();
+    $user->setUsername($user->label() . '_dupe');
+    $user->save();
+    return $user;
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -159,14 +170,14 @@ abstract class UserResourceTestBase extends EntityResourceTestBase {
 
     // DX: 422 when changing email without providing the password.
     $response = $this->request('PATCH', $url, $request_options);
-    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response);
+    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response, FALSE, FALSE, FALSE, FALSE);
 
     $normalization['pass'] = [['existing' => 'wrong']];
     $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
 
     // DX: 422 when changing email while providing a wrong password.
     $response = $this->request('PATCH', $url, $request_options);
-    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response);
+    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response, FALSE, FALSE, FALSE, FALSE);
 
     $normalization['pass'] = [['existing' => $this->account->passRaw]];
     $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
@@ -183,7 +194,7 @@ abstract class UserResourceTestBase extends EntityResourceTestBase {
 
     // DX: 422 when changing password without providing the current password.
     $response = $this->request('PATCH', $url, $request_options);
-    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\npass: Your current password is missing or incorrect; it's required to change the Password.\n", $response);
+    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\npass: Your current password is missing or incorrect; it's required to change the Password.\n", $response, FALSE, FALSE, FALSE, FALSE);
 
     $normalization['pass'][0]['existing'] = $this->account->pass_raw;
     $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
@@ -243,6 +254,49 @@ abstract class UserResourceTestBase extends EntityResourceTestBase {
     $this->assertSame(200, $response->getStatusCode());
   }
 
+  /**
+   * Tests PATCHing security-sensitive base fields to change other users.
+   */
+  public function testPatchSecurityOtherUser() {
+    // The anonymous user is never allowed to modify other users.
+    if (!static::$auth) {
+      $this->markTestSkipped();
+    }
+
+    $this->initAuthentication();
+    $this->provisionEntityResource();
+
+    /** @var \Drupal\user\UserInterface $user */
+    $user = $this->account;
+    $original_normalization = array_diff_key($this->serializer->normalize($user, static::$format), ['changed' => TRUE]);
+
+    // Since this test must be performed by the user that is being modified,
+    // we cannot use $this->getUrl().
+    $url = $user->toUrl()->setOption('query', ['_format' => static::$format]);
+    $request_options = [
+      RequestOptions::HEADERS => ['Content-Type' => static::$mimeType],
+    ];
+    $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH'));
+
+    $normalization = $original_normalization;
+    $normalization['mail'] = [['value' => 'new-email@example.com']];
+    $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
+
+    // Try changing user 1's email.
+    $user1 = [
+      'mail' => [['value' => 'another_email_address@example.com']],
+      'uid' => [['value' => 1]],
+      'name' => [['value' => 'another_user_name']],
+      'pass' => [['existing' => $this->account->passRaw]],
+      'uuid' => [['value' => '2e9403a4-d8af-4096-a116-624710140be0']],
+    ] + $original_normalization;
+    $request_options[RequestOptions::BODY] = $this->serializer->encode($user1, static::$format);
+    $response = $this->request('PATCH', $url, $request_options);
+    // Ensure the email address has not changed.
+    $this->assertEquals('admin@example.com', $this->entityStorage->loadUnchanged(1)->getEmail());
+    $this->assertResourceErrorResponse(403, "Access denied on updating field 'uid'.", $response);
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -263,4 +317,13 @@ abstract class UserResourceTestBase extends EntityResourceTestBase {
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function getExpectedUnauthorizedAccessCacheability() {
+    // @see \Drupal\user\UserAccessControlHandler::checkAccess()
+    return parent::getExpectedUnauthorizedAccessCacheability()
+      ->addCacheTags(['user:3']);
+  }
+
 }