You are here

public function UserResourceTestBase::testPatchDxForSecuritySensitiveBaseFields in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/user/tests/src/Functional/Rest/UserResourceTestBase.php \Drupal\Tests\user\Functional\Rest\UserResourceTestBase::testPatchDxForSecuritySensitiveBaseFields()

Tests PATCHing security-sensitive base fields of the logged in account.

3 methods override UserResourceTestBase::testPatchDxForSecuritySensitiveBaseFields()
UserXmlAnonTest::testPatchDxForSecuritySensitiveBaseFields in core/modules/user/tests/src/Functional/Rest/UserXmlAnonTest.php
Tests PATCHing security-sensitive base fields of the logged in account.
UserXmlBasicAuthTest::testPatchDxForSecuritySensitiveBaseFields in core/modules/user/tests/src/Functional/Rest/UserXmlBasicAuthTest.php
Tests PATCHing security-sensitive base fields of the logged in account.
UserXmlCookieTest::testPatchDxForSecuritySensitiveBaseFields in core/modules/user/tests/src/Functional/Rest/UserXmlCookieTest.php
Tests PATCHing security-sensitive base fields of the logged in account.

File

core/modules/user/tests/src/Functional/Rest/UserResourceTestBase.php, line 148

Class

UserResourceTestBase

Namespace

Drupal\Tests\user\Functional\Rest

Code

public function testPatchDxForSecuritySensitiveBaseFields() {

  // The anonymous user is never allowed to modify itself.
  if (!static::$auth) {
    $this
      ->markTestSkipped();
  }
  $this
    ->initAuthentication();
  $this
    ->provisionEntityResource();

  /** @var \Drupal\user\UserInterface $user */
  $user = static::$auth ? $this->account : User::load(0);

  // @todo Remove the array_diff_key() call in https://www.drupal.org/node/2821077.
  $original_normalization = array_diff_key($this->serializer
    ->normalize($user, static::$format), [
    'created' => TRUE,
    'changed' => TRUE,
    'name' => 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'));

  // Test case 1: changing email.
  $normalization = $original_normalization;
  $normalization['mail'] = [
    [
      'value' => 'new-email@example.com',
    ],
  ];
  $request_options[RequestOptions::BODY] = $this->serializer
    ->encode($normalization, static::$format);

  // 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, 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, FALSE, FALSE, FALSE, FALSE);
  $normalization['pass'] = [
    [
      'existing' => $this->account->passRaw,
    ],
  ];
  $request_options[RequestOptions::BODY] = $this->serializer
    ->encode($normalization, static::$format);

  // 200 for well-formed request.
  $response = $this
    ->request('PATCH', $url, $request_options);
  $this
    ->assertResourceResponse(200, FALSE, $response);

  // Test case 2: changing password.
  $normalization = $original_normalization;
  $new_password = $this
    ->randomString();
  $normalization['pass'] = [
    [
      'value' => $new_password,
    ],
  ];
  $request_options[RequestOptions::BODY] = $this->serializer
    ->encode($normalization, static::$format);

  // 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, FALSE, FALSE, FALSE, FALSE);
  $normalization['pass'][0]['existing'] = $this->account->pass_raw;
  $request_options[RequestOptions::BODY] = $this->serializer
    ->encode($normalization, static::$format);

  // 200 for well-formed request.
  $response = $this
    ->request('PATCH', $url, $request_options);
  $this
    ->assertResourceResponse(200, FALSE, $response);

  // Verify that we can log in with the new password.
  $this
    ->assertRpcLogin($user
    ->getAccountName(), $new_password);

  // Update password in $this->account, prepare for future requests.
  $this->account->passRaw = $new_password;
  $this
    ->initAuthentication();
  $request_options = [
    RequestOptions::HEADERS => [
      'Content-Type' => static::$mimeType,
    ],
  ];
  $request_options = array_merge_recursive($request_options, $this
    ->getAuthenticationRequestOptions('PATCH'));

  // Test case 3: changing name.
  $normalization = $original_normalization;
  $normalization['name'] = [
    [
      'value' => 'Cooler Llama',
    ],
  ];
  $request_options[RequestOptions::BODY] = $this->serializer
    ->encode($normalization, static::$format);

  // DX: 403 when modifying username without required permission.
  $response = $this
    ->request('PATCH', $url, $request_options);
  $this
    ->assertResourceErrorResponse(403, "Access denied on updating field 'name'.", $response);
  $this
    ->grantPermissionsToTestedRole([
    'change own username',
  ]);

  // 200 for well-formed request.
  $response = $this
    ->request('PATCH', $url, $request_options);
  $this
    ->assertResourceResponse(200, FALSE, $response);

  // Verify that we can log in with the new username.
  $this
    ->assertRpcLogin('Cooler Llama', $new_password);
}