Issue #3201714 by jonathanshaw, ravi.shankar, longwave, catch, alexpott: EntityQuery accessCheck: data cleanup should never care about the current user
parent
c97c52b7ff
commit
37a5b1a70f
|
@ -171,7 +171,7 @@ function comment_field_storage_config_insert(FieldStorageConfigInterface $field_
|
|||
function comment_field_config_delete(FieldConfigInterface $field) {
|
||||
if ($field->getType() == 'comment') {
|
||||
// Delete all comments that used by the entity bundle.
|
||||
$entity_query = \Drupal::entityQuery('comment');
|
||||
$entity_query = \Drupal::entityQuery('comment')->accessCheck(FALSE);
|
||||
$entity_query->condition('entity_type', $field->getEntityTypeId());
|
||||
$entity_query->condition('field_name', $field->getName());
|
||||
$cids = $entity_query->execute();
|
||||
|
@ -318,7 +318,7 @@ function comment_entity_predelete(EntityInterface $entity) {
|
|||
// entity type that has an integer ID, $entity->id() might be a string
|
||||
// containing a number), and then cast it to an integer when querying.
|
||||
if ($entity instanceof FieldableEntityInterface && is_numeric($entity->id())) {
|
||||
$entity_query = \Drupal::entityQuery('comment');
|
||||
$entity_query = \Drupal::entityQuery('comment')->accessCheck(FALSE);
|
||||
$entity_query->condition('entity_id', (int) $entity->id());
|
||||
$entity_query->condition('entity_type', $entity->getEntityTypeId());
|
||||
$cids = $entity_query->execute();
|
||||
|
|
|
@ -615,6 +615,7 @@ function node_user_cancel($edit, UserInterface $account, $method) {
|
|||
case 'user_cancel_block_unpublish':
|
||||
// Unpublish nodes (current revisions).
|
||||
$nids = \Drupal::entityQuery('node')
|
||||
->accessCheck(FALSE)
|
||||
->condition('uid', $account->id())
|
||||
->execute();
|
||||
module_load_include('inc', 'node', 'node.admin');
|
||||
|
|
|
@ -79,7 +79,7 @@ function node_access_test_node_grants($account, $op) {
|
|||
function node_access_test_node_access_records(NodeInterface $node) {
|
||||
$grants = [];
|
||||
// For NodeAccessBaseTableTestCase, only set records for private nodes.
|
||||
if (!\Drupal::state()->get('node_access_test.private') || $node->private->value) {
|
||||
if (!\Drupal::state()->get('node_access_test.private') || (isset($node->private) && $node->private->value)) {
|
||||
// Groups 8888 and 8889 for the node_access_test realm both receive a view
|
||||
// grant for all controlled nodes. See node_access_test_node_grants().
|
||||
$grants[] = [
|
||||
|
|
|
@ -97,6 +97,7 @@ class ShortcutSet extends ConfigEntityBundleBase implements ShortcutSetInterface
|
|||
|
||||
// Next, delete the shortcuts for this set.
|
||||
$shortcut_ids = \Drupal::entityQuery('shortcut')
|
||||
->accessCheck(FALSE)
|
||||
->condition('shortcut_set', $entity->id(), '=')
|
||||
->execute();
|
||||
|
||||
|
|
|
@ -101,7 +101,8 @@ class PrepareModulesEntityUninstallForm extends ConfirmFormBase {
|
|||
$form = parent::buildForm($form, $form_state);
|
||||
|
||||
$storage = $this->entityTypeManager->getStorage($entity_type_id);
|
||||
$count = $storage->getQuery()->count()->execute();
|
||||
$count = $storage->getQuery()->accessCheck(FALSE)->count()->execute();
|
||||
$accessible_count = $storage->getQuery()->accessCheck(TRUE)->count()->execute();
|
||||
|
||||
$form['entity_type_id'] = [
|
||||
'#type' => 'value',
|
||||
|
@ -118,8 +119,9 @@ class PrepareModulesEntityUninstallForm extends ConfirmFormBase {
|
|||
),
|
||||
];
|
||||
}
|
||||
elseif ($entity_type->hasKey('label')) {
|
||||
elseif ($accessible_count > 0 && $entity_type->hasKey('label')) {
|
||||
$recent_entity_ids = $storage->getQuery()
|
||||
->accessCheck(TRUE)
|
||||
->sort($entity_type->getKey('id'), 'DESC')
|
||||
->pager(10)
|
||||
->execute();
|
||||
|
@ -216,11 +218,12 @@ class PrepareModulesEntityUninstallForm extends ConfirmFormBase {
|
|||
|
||||
if (!isset($context['sandbox']['progress'])) {
|
||||
$context['sandbox']['progress'] = 0;
|
||||
$context['sandbox']['max'] = $storage->getQuery()->count()->execute();
|
||||
$context['sandbox']['max'] = $storage->getQuery()->accessCheck(FALSE)->count()->execute();
|
||||
}
|
||||
|
||||
$entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
|
||||
$entity_ids = $storage->getQuery()
|
||||
->accessCheck(FALSE)
|
||||
->sort($entity_type->getKey('id'), 'ASC')
|
||||
->range(0, 10)
|
||||
->execute();
|
||||
|
@ -229,7 +232,7 @@ class PrepareModulesEntityUninstallForm extends ConfirmFormBase {
|
|||
}
|
||||
// Sometimes deletes cause secondary deletes. For example, deleting a
|
||||
// taxonomy term can cause its children to be deleted too.
|
||||
$context['sandbox']['progress'] = $context['sandbox']['max'] - $storage->getQuery()->count()->execute();
|
||||
$context['sandbox']['progress'] = $context['sandbox']['max'] - $storage->getQuery()->accessCheck(FALSE)->count()->execute();
|
||||
|
||||
// Inform the batch engine that we are not finished and provide an
|
||||
// estimation of the completion level we reached.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\Tests\system\Functional\Module;
|
||||
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait;
|
||||
|
||||
|
@ -38,7 +39,7 @@ class PrepareUninstallTest extends BrowserTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $modules = ['node', 'taxonomy', 'entity_test'];
|
||||
protected static $modules = ['node', 'taxonomy', 'entity_test', 'node_access_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -49,10 +50,16 @@ class PrepareUninstallTest extends BrowserTestBase {
|
|||
$admin_user = $this->drupalCreateUser(['administer modules']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
node_access_rebuild();
|
||||
node_access_test_add_field(NodeType::load('article'));
|
||||
\Drupal::state()->set('node_access_test.private', TRUE);
|
||||
|
||||
// Create 10 nodes.
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$this->nodes[] = $this->drupalCreateNode(['type' => 'page']);
|
||||
$this->nodes[] = $this->drupalCreateNode(['type' => 'article']);
|
||||
// These 5 articles are inaccessible to the admin user doing the uninstalling.
|
||||
$this->nodes[] = $this->drupalCreateNode(['type' => 'article', 'uid' => 0, 'private' => TRUE]);
|
||||
}
|
||||
|
||||
// Create 3 top-level taxonomy terms, each with 11 children.
|
||||
|
@ -110,7 +117,19 @@ class PrepareUninstallTest extends BrowserTestBase {
|
|||
|
||||
// Delete Node data.
|
||||
$this->drupalGet('admin/modules/uninstall/entity/node');
|
||||
// All 10 nodes should be listed.
|
||||
// Only the 5 pages should be listed as the 5 articles are initially inaccessible.
|
||||
foreach ($this->nodes as $node) {
|
||||
if ($node->bundle() === 'page') {
|
||||
$this->assertText($node->label());
|
||||
}
|
||||
else {
|
||||
$node->set('private', FALSE)->save();
|
||||
}
|
||||
}
|
||||
$this->assertText('And 5 more content items.');
|
||||
|
||||
// All 10 nodes should now be listed as none are still inaccessible.
|
||||
$this->drupalGet('admin/modules/uninstall/entity/node');
|
||||
foreach ($this->nodes as $node) {
|
||||
$this->assertText($node->label());
|
||||
}
|
||||
|
@ -127,11 +146,9 @@ class PrepareUninstallTest extends BrowserTestBase {
|
|||
// the first 10's labels.
|
||||
$this->assertText('And 1 more content item.');
|
||||
|
||||
// Create another node so we have 12.
|
||||
$this->nodes[] = $this->drupalCreateNode(['type' => 'article']);
|
||||
// Create another node so we have 12, with one private.
|
||||
$this->nodes[] = $this->drupalCreateNode(['type' => 'article', 'private' => TRUE]);
|
||||
$this->drupalGet('admin/modules/uninstall/entity/node');
|
||||
// Ensures singular case is used when a single entity is left after listing
|
||||
// the first 10's labels.
|
||||
$this->assertText('And 2 more content items.');
|
||||
|
||||
$this->submitForm([], 'Delete all content items');
|
||||
|
|
|
@ -6,6 +6,7 @@ use Drupal\comment\CommentInterface;
|
|||
use Drupal\comment\Entity\Comment;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\user\Entity\User;
|
||||
|
||||
|
@ -280,6 +281,47 @@ class UserCancelTest extends BrowserTestBase {
|
|||
$this->assertFalse($comment->isPublished(), 'Comment of the user has been unpublished.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests nodes are unpublished even if inaccessible to cancelling user.
|
||||
*/
|
||||
public function testUserBlockUnpublishNodeAccess() {
|
||||
\Drupal::service('module_installer')->install(['node_access_test', 'user_form_test']);
|
||||
|
||||
// Setup node access
|
||||
node_access_rebuild();
|
||||
node_access_test_add_field(NodeType::load('page'));
|
||||
\Drupal::state()->set('node_access_test.private', TRUE);
|
||||
|
||||
$this->config('user.settings')->set('cancel_method', 'user_cancel_block_unpublish')->save();
|
||||
|
||||
// Create a user.
|
||||
$user_storage = $this->container->get('entity_type.manager')->getStorage('user');
|
||||
$account = $this->drupalCreateUser(['cancel account']);
|
||||
// Load a real user object.
|
||||
$user_storage->resetCache([$account->id()]);
|
||||
$account = $user_storage->load($account->id());
|
||||
|
||||
// Create a published private node.
|
||||
$node = $this->drupalCreateNode([
|
||||
'uid' => $account->id(),
|
||||
'type' => 'page',
|
||||
'status' => 1,
|
||||
'private' => TRUE,
|
||||
]);
|
||||
|
||||
// Cancel node author.
|
||||
$admin_user = $this->drupalCreateUser(['cancel other accounts']);
|
||||
$this->drupalLogin($admin_user);
|
||||
$this->drupalPostForm('user_form_test_cancel/' . $account->id(), [], 'Cancel account');
|
||||
|
||||
// Confirm node has been unpublished, even though the admin user
|
||||
// does not have permission to access it.
|
||||
$node_storage = $this->container->get('entity_type.manager')->getStorage('node');
|
||||
$node_storage->resetCache([$node->id()]);
|
||||
$test_node = $node_storage->load($node->id());
|
||||
$this->assertFalse($test_node->isPublished(), 'Node of the user has been unpublished.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete account and anonymize all content.
|
||||
*/
|
||||
|
|
|
@ -45,6 +45,7 @@ function hook_user_cancel($edit, UserInterface $account, $method) {
|
|||
// Unpublish nodes (current revisions).
|
||||
module_load_include('inc', 'node', 'node.admin');
|
||||
$nodes = \Drupal::entityQuery('node')
|
||||
->accessCheck(FALSE)
|
||||
->condition('uid', $account->id())
|
||||
->execute();
|
||||
node_mass_update($nodes, ['status' => 0], NULL, TRUE);
|
||||
|
@ -54,6 +55,7 @@ function hook_user_cancel($edit, UserInterface $account, $method) {
|
|||
// Anonymize nodes (current revisions).
|
||||
module_load_include('inc', 'node', 'node.admin');
|
||||
$nodes = \Drupal::entityQuery('node')
|
||||
->accessCheck(FALSE)
|
||||
->condition('uid', $account->id())
|
||||
->execute();
|
||||
node_mass_update($nodes, ['uid' => 0], NULL, TRUE);
|
||||
|
|
Loading…
Reference in New Issue