Issue #3228000 by bbrala, larowlan, GuyPaddock, Wim Leers, bradjones1, alexpott, catch, e0ipso: Users deleted via JSON:API DELETE don't follow the site-wide cancel_method in the user settings
(cherry picked from commit 9d8e7da4fc
)
merge-requests/561/head
parent
cccb885429
commit
7c0c951f76
|
@ -369,7 +369,25 @@ class EntityResource {
|
|||
* The response.
|
||||
*/
|
||||
public function deleteIndividual(EntityInterface $entity) {
|
||||
$entity->delete();
|
||||
// @todo Replace with entity handlers in: https://www.drupal.org/project/drupal/issues/3230434
|
||||
if ($entity->getEntityTypeId() === 'user') {
|
||||
$cancel_method = \Drupal::service('config.factory')->get('user.settings')->get('cancel_method');
|
||||
|
||||
// Allow other modules to act.
|
||||
|
||||
user_cancel([], $entity->id(), $cancel_method);
|
||||
// Since user_cancel() is not invoked via Form API, batch processing
|
||||
// needs to be invoked manually.
|
||||
$batch =& batch_get();
|
||||
// Mark this batch as non-progressive to bypass the progress bar and
|
||||
// redirect.
|
||||
$batch['progressive'] = FALSE;
|
||||
batch_process();
|
||||
}
|
||||
else {
|
||||
$entity->delete();
|
||||
}
|
||||
|
||||
return new ResourceResponse(NULL, 204);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ use Drupal\field\Entity\FieldConfig;
|
|||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\user\UserInterface;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
|
||||
/**
|
||||
|
@ -19,10 +20,12 @@ use GuzzleHttp\RequestOptions;
|
|||
*/
|
||||
class UserTest extends ResourceTestBase {
|
||||
|
||||
const BATCH_TEST_NODE_COUNT = 15;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['user', 'jsonapi_test_user'];
|
||||
protected static $modules = ['user', 'jsonapi_test_user', 'node'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -119,6 +122,15 @@ class UserTest extends ResourceTestBase {
|
|||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testDeleteIndividual() {
|
||||
$this->config('user.settings')->set('cancel_method', 'user_cancel_delete')->save(TRUE);
|
||||
|
||||
parent::testDeleteIndividual();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -597,6 +609,175 @@ class UserTest extends ResourceTestBase {
|
|||
$this->assertEquals($original_name, $updated_user->get('name')->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if JSON:API respects user.settings.cancel_method: user_cancel_block.
|
||||
*/
|
||||
public function testDeleteRespectsUserCancelBlock() {
|
||||
$cancel_method = 'user_cancel_block';
|
||||
$this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE);
|
||||
$this->config('user.settings')->set('cancel_method', $cancel_method)->save(TRUE);
|
||||
|
||||
$account = $this->createAnotherEntity($cancel_method);
|
||||
$node = $this->drupalCreateNode(['uid' => $account->id()]);
|
||||
|
||||
$this->sendDeleteRequestForUser($account, $cancel_method);
|
||||
|
||||
$user_storage = $this->container->get('entity_type.manager')
|
||||
->getStorage('user');
|
||||
$user_storage->resetCache([$account->id()]);
|
||||
$account = $user_storage->load($account->id());
|
||||
|
||||
$this->assertNotNull($account, 'User is not deleted after JSON:API DELETE operation with user.settings.cancel_method: ' . $cancel_method);
|
||||
$this->assertTrue($account->isBlocked(), 'User is blocked after JSON:API DELETE operation with user.settings.cancel_method: ' . $cancel_method);
|
||||
|
||||
$node_storage = $this->container->get('entity_type.manager')->getStorage('node');
|
||||
$node_storage->resetCache([$node->id()]);
|
||||
$test_node = $node_storage->load($node->id());
|
||||
$this->assertNotNull($test_node, 'Node of the user is not deleted.');
|
||||
$this->assertTrue($test_node->isPublished(), 'Node of the user is published.');
|
||||
$test_node = node_revision_load($node->getRevisionId());
|
||||
$this->assertTrue($test_node->isPublished(), 'Node revision of the user is published.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if JSON:API respects user.settings.cancel_method: user_cancel_block_unpublish.
|
||||
*/
|
||||
public function testDeleteRespectsUserCancelBlockUnpublish() {
|
||||
$cancel_method = 'user_cancel_block_unpublish';
|
||||
$this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE);
|
||||
$this->config('user.settings')->set('cancel_method', $cancel_method)->save(TRUE);
|
||||
|
||||
$account = $this->createAnotherEntity($cancel_method);
|
||||
$node = $this->drupalCreateNode(['uid' => $account->id()]);
|
||||
|
||||
$this->sendDeleteRequestForUser($account, $cancel_method);
|
||||
|
||||
$user_storage = $this->container->get('entity_type.manager')
|
||||
->getStorage('user');
|
||||
$user_storage->resetCache([$account->id()]);
|
||||
$account = $user_storage->load($account->id());
|
||||
|
||||
$this->assertNotNull($account, 'User is not deleted after JSON:API DELETE operation with user.settings.cancel_method: ' . $cancel_method);
|
||||
$this->assertTrue($account->isBlocked(), 'User is blocked after JSON:API DELETE operation with user.settings.cancel_method: ' . $cancel_method);
|
||||
|
||||
$node_storage = $this->container->get('entity_type.manager')->getStorage('node');
|
||||
$node_storage->resetCache([$node->id()]);
|
||||
$test_node = $node_storage->load($node->id());
|
||||
$this->assertNotNull($test_node, 'Node of the user is not deleted.');
|
||||
$this->assertFalse($test_node->isPublished(), 'Node of the user is no longer published.');
|
||||
$test_node = node_revision_load($node->getRevisionId());
|
||||
$this->assertFalse($test_node->isPublished(), 'Node revision of the user is no longer published.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if JSON:API respects user.settings.cancel_method: user_cancel_block_unpublish.
|
||||
* @group jsonapi
|
||||
*/
|
||||
public function testDeleteRespectsUserCancelBlockUnpublishAndProcessesBatches() {
|
||||
$cancel_method = 'user_cancel_block_unpublish';
|
||||
$this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE);
|
||||
$this->config('user.settings')->set('cancel_method', $cancel_method)->save(TRUE);
|
||||
|
||||
$account = $this->createAnotherEntity($cancel_method);
|
||||
|
||||
$nodeCount = self::BATCH_TEST_NODE_COUNT;
|
||||
$node_ids = [];
|
||||
$nodes = [];
|
||||
while ($nodeCount-- > 0) {
|
||||
$node = $this->drupalCreateNode(['uid' => $account->id()]);
|
||||
$nodes[] = $node;
|
||||
$node_ids[] = $node->id();
|
||||
}
|
||||
|
||||
$this->sendDeleteRequestForUser($account, $cancel_method);
|
||||
|
||||
$user_storage = $this->container->get('entity_type.manager')
|
||||
->getStorage('user');
|
||||
$user_storage->resetCache([$account->id()]);
|
||||
$account = $user_storage->load($account->id());
|
||||
|
||||
$this->assertNotNull($account, 'User is not deleted after JSON:API DELETE operation with user.settings.cancel_method: ' . $cancel_method);
|
||||
$this->assertTrue($account->isBlocked(), 'User is blocked after JSON:API DELETE operation with user.settings.cancel_method: ' . $cancel_method);
|
||||
|
||||
$node_storage = $this->container->get('entity_type.manager')->getStorage('node');
|
||||
$node_storage->resetCache($node_ids);
|
||||
|
||||
$test_nodes = $node_storage->loadMultiple($node_ids);
|
||||
|
||||
$this->assertCount(self::BATCH_TEST_NODE_COUNT, $test_nodes, 'Nodes of the user are not deleted.');
|
||||
|
||||
foreach ($test_nodes as $test_node) {
|
||||
$this->assertFalse($test_node->isPublished(), 'Node of the user is no longer published.');
|
||||
}
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
$test_node = node_revision_load($node->getRevisionId());
|
||||
$this->assertFalse($test_node->isPublished(), 'Node revision of the user is no longer published.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if JSON:API respects user.settings.cancel_method: user_cancel_reassign.
|
||||
*/
|
||||
public function testDeleteRespectsUserCancelReassign() {
|
||||
$cancel_method = 'user_cancel_reassign';
|
||||
$this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE);
|
||||
$this->config('user.settings')->set('cancel_method', $cancel_method)->save(TRUE);
|
||||
|
||||
$account = $this->createAnotherEntity($cancel_method);
|
||||
$node = $this->drupalCreateNode(['uid' => $account->id()]);
|
||||
|
||||
$this->sendDeleteRequestForUser($account, $cancel_method);
|
||||
|
||||
$user_storage = $this->container->get('entity_type.manager')
|
||||
->getStorage('user');
|
||||
$user_storage->resetCache([$account->id()]);
|
||||
$account = $user_storage->load($account->id());
|
||||
|
||||
$this->assertNull($account, 'User is deleted after JSON:API DELETE operation with user.settings.cancel_method: ' . $cancel_method);
|
||||
|
||||
$node_storage = $this->container->get('entity_type.manager')->getStorage('node');
|
||||
$node_storage->resetCache([$node->id()]);
|
||||
$test_node = $node_storage->load($node->id());
|
||||
$this->assertNotNull($test_node, 'Node of the user is not deleted.');
|
||||
$this->assertTrue($test_node->isPublished(), 'Node of the user is still published.');
|
||||
$this->assertEquals(0, $test_node->getOwnerId(), 'Node of the user has been attributed to anonymous user.');
|
||||
$test_node = node_revision_load($node->getRevisionId());
|
||||
$this->assertTrue($test_node->isPublished(), 'Node revision of the user is still published.');
|
||||
$this->assertEquals(0, $test_node->getRevisionUser()->id(), 'Node revision of the user has been attributed to anonymous user.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if JSON:API respects user.settings.cancel_method: user_cancel_delete.
|
||||
*/
|
||||
public function testDeleteRespectsUserCancelDelete() {
|
||||
$cancel_method = 'user_cancel_delete';
|
||||
$this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE);
|
||||
$this->config('user.settings')->set('cancel_method', $cancel_method)->save(TRUE);
|
||||
|
||||
$account = $this->createAnotherEntity($cancel_method);
|
||||
$node = $this->drupalCreateNode(['uid' => $account->id()]);
|
||||
|
||||
$url = Url::fromRoute(sprintf('jsonapi.%s.individual', static::$resourceTypeName), ['entity' => $account->uuid()]);
|
||||
$request_options = [];
|
||||
$request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
|
||||
$request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions());
|
||||
$this->setUpAuthorization('DELETE');
|
||||
$response = $this->request('DELETE', $url, $request_options);
|
||||
$this->assertResourceResponse(204, NULL, $response);
|
||||
|
||||
$node_storage = $this->container->get('entity_type.manager')->getStorage('node');
|
||||
$user_storage = $this->container->get('entity_type.manager')->getStorage('user');
|
||||
|
||||
$user_storage->resetCache([$account->id()]);
|
||||
$account = $user_storage->load($account->id());
|
||||
$this->assertNull($account, 'User is deleted after JSON:API DELETE operation with user.settings.cancel_method: ' . $cancel_method);
|
||||
|
||||
$node_storage->resetCache([$node->id()]);
|
||||
$test_node = $node_storage->load($node->id());
|
||||
$this->assertNull($test_node, 'Node of the user is deleted.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -620,4 +801,18 @@ class UserTest extends ResourceTestBase {
|
|||
return parent::makeNormalizationInvalid($document, $entity_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Drupal\user\UserInterface $account
|
||||
* @param string $cancel_method
|
||||
*/
|
||||
private function sendDeleteRequestForUser(UserInterface $account, string $cancel_method) {
|
||||
$url = Url::fromRoute(sprintf('jsonapi.%s.individual', static::$resourceTypeName), ['entity' => $account->uuid()]);
|
||||
$request_options = [];
|
||||
$request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
|
||||
$request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions());
|
||||
$this->setUpAuthorization('DELETE');
|
||||
$response = $this->request('DELETE', $url, $request_options);
|
||||
$this->assertResourceResponse(204, NULL, $response);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue