function UserResourceTestBase::testPatchDxForSecuritySensitiveBaseFields

Same name in other branches
  1. 9 core/modules/user/tests/src/Functional/Rest/UserResourceTestBase.php \Drupal\Tests\user\Functional\Rest\UserResourceTestBase::testPatchDxForSecuritySensitiveBaseFields()
  2. 8.9.x core/modules/user/tests/src/Functional/Rest/UserResourceTestBase.php \Drupal\Tests\user\Functional\Rest\UserResourceTestBase::testPatchDxForSecuritySensitiveBaseFields()
  3. 11.x 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.

File

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

Class

UserResourceTestBase

Namespace

Drupal\Tests\user\Functional\Rest

Code

public function testPatchDxForSecuritySensitiveBaseFields() : void {
    $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);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.