Commit a042df2e authored by catch's avatar catch
Browse files

Issue #2172017 by dawehner, larowlan, MegaChriz, kim.pepper, Désiré, Sam...

Issue #2172017 by dawehner, larowlan, MegaChriz, kim.pepper, Désiré, Sam Hermans, tim.plunkett, Antti J. Salminen: Bulk operations does not respect entity access
parent e2e00e91
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
use Drupal\Component\Plugin\PluginInspectionInterface; use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\Core\Executable\ExecutableInterface; use Drupal\Core\Executable\ExecutableInterface;
use Drupal\Core\Session\AccountInterface;
/** /**
* Provides an interface for an Action plugin. * Provides an interface for an Action plugin.
...@@ -44,4 +45,24 @@ interface ActionInterface extends ExecutableInterface, PluginInspectionInterface ...@@ -44,4 +45,24 @@ interface ActionInterface extends ExecutableInterface, PluginInspectionInterface
*/ */
public function executeMultiple(array $objects); public function executeMultiple(array $objects);
/**
* Checks object access.
*
* @param mixed $object
* The object to execute the action on.
* @param \Drupal\Core\Session\AccountInterface $account
* (optional) The user for which to check access, or NULL to check access
* for the current user. Defaults to NULL.
* @param bool $return_as_object
* (optional) Defaults to FALSE.
*
* @return bool|\Drupal\Core\Access\AccessResultInterface
* The access result. Returns a boolean if $return_as_object is FALSE (this
* is the default) and otherwise an AccessResultInterface object.
* When a boolean is returned, the result of AccessInterface::isAllowed() is
* returned, i.e. TRUE means access is explicitly allowed, FALSE means
* access is either explicitly forbidden or "no opinion".
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE);
} }
...@@ -7,11 +7,13 @@ ...@@ -7,11 +7,13 @@
namespace Drupal\action\Plugin\Action; namespace Drupal\action\Plugin\Action;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Action\ConfigurableActionBase; use Drupal\Core\Action\ConfigurableActionBase;
use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Mail\MailManagerInterface; use Drupal\Core\Mail\MailManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Utility\Token; use Drupal\Core\Utility\Token;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
...@@ -184,4 +186,12 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s ...@@ -184,4 +186,12 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
$this->configuration['message'] = $form_state->getValue('message'); $this->configuration['message'] = $form_state->getValue('message');
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
$result = AccessResult::allowed();
return $return_as_object ? $result : $result->isAllowed();
}
} }
...@@ -7,10 +7,12 @@ ...@@ -7,10 +7,12 @@
namespace Drupal\action\Plugin\Action; namespace Drupal\action\Plugin\Action;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Action\ConfigurableActionBase; use Drupal\Core\Action\ConfigurableActionBase;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
...@@ -113,4 +115,12 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s ...@@ -113,4 +115,12 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
$this->configuration['url'] = $form_state->getValue('url'); $this->configuration['url'] = $form_state->getValue('url');
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
$access = AccessResult::allowed();
return $return_as_object ? $access : $access->isAllowed();
}
} }
...@@ -8,9 +8,11 @@ ...@@ -8,9 +8,11 @@
namespace Drupal\action\Plugin\Action; namespace Drupal\action\Plugin\Action;
use Drupal\Component\Utility\Xss; use Drupal\Component\Utility\Xss;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Action\ConfigurableActionBase; use Drupal\Core\Action\ConfigurableActionBase;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Utility\Token; use Drupal\Core\Utility\Token;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
...@@ -89,4 +91,12 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s ...@@ -89,4 +91,12 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
unset($this->configuration['node']); unset($this->configuration['node']);
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
$result = AccessResult::allowed();
return $return_as_object ? $result : $result->isAllowed();
}
} }
...@@ -63,6 +63,14 @@ public function testBulkForm() { ...@@ -63,6 +63,14 @@ public function testBulkForm() {
$edit["node_bulk_form[$i]"] = TRUE; $edit["node_bulk_form[$i]"] = TRUE;
} }
// Log in as a user with 'administer nodes' permission to have access to the
// bulk operation.
$this->drupalCreateContentType(['type' => 'page']);
$admin_user = $this->drupalCreateUser(['administer nodes', 'edit any page content']);
$this->drupalLogin($admin_user);
$this->drupalGet('test_bulk_form');
// Set all nodes to sticky and check that. // Set all nodes to sticky and check that.
$edit += array('action' => 'node_make_sticky_action'); $edit += array('action' => 'node_make_sticky_action');
$this->drupalPostForm(NULL, $edit, t('Apply')); $this->drupalPostForm(NULL, $edit, t('Apply'));
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
namespace Drupal\comment\Plugin\Action; namespace Drupal\comment\Plugin\Action;
use Drupal\Core\Action\ActionBase; use Drupal\Core\Action\ActionBase;
use Drupal\comment\CommentInterface; use Drupal\Core\Session\AccountInterface;
/** /**
* Publishes a comment. * Publishes a comment.
...@@ -29,4 +29,15 @@ public function execute($comment = NULL) { ...@@ -29,4 +29,15 @@ public function execute($comment = NULL) {
$comment->save(); $comment->save();
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\comment\CommentInterface $object */
$result = $object->status->access('edit', $account, TRUE)
->andIf($object->access('update', $account, TRUE));
return $return_as_object ? $result : $result->isAllowed();
}
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace Drupal\comment\Plugin\Action; namespace Drupal\comment\Plugin\Action;
use Drupal\Core\Action\ActionBase; use Drupal\Core\Action\ActionBase;
use Drupal\Core\Session\AccountInterface;
/** /**
* Saves a comment. * Saves a comment.
...@@ -27,4 +28,12 @@ public function execute($comment = NULL) { ...@@ -27,4 +28,12 @@ public function execute($comment = NULL) {
$comment->save(); $comment->save();
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\comment\CommentInterface $object */
return $object->access('update', $account, $return_as_object);
}
} }
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
use Drupal\Component\Utility\Tags; use Drupal\Component\Utility\Tags;
use Drupal\Core\Action\ConfigurableActionBase; use Drupal\Core\Action\ConfigurableActionBase;
use Drupal\comment\CommentInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
/** /**
* Unpublishes a comment containing certain keywords. * Unpublishes a comment containing certain keywords.
...@@ -67,4 +67,15 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s ...@@ -67,4 +67,15 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
$this->configuration['keywords'] = Tags::explode($form_state->getValue('keywords')); $this->configuration['keywords'] = Tags::explode($form_state->getValue('keywords'));
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\comment\CommentInterface $object */
$result = $object->access('update', $account, TRUE)
->andIf($object->status->access('edit', $account, TRUE));
return $return_as_object ? $result : $result->isAllowed();
}
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
namespace Drupal\comment\Plugin\Action; namespace Drupal\comment\Plugin\Action;
use Drupal\Core\Action\ActionBase; use Drupal\Core\Action\ActionBase;
use Drupal\comment\CommentInterface; use Drupal\Core\Session\AccountInterface;
/** /**
* Unpublishes a comment. * Unpublishes a comment.
...@@ -29,4 +29,15 @@ public function execute($comment = NULL) { ...@@ -29,4 +29,15 @@ public function execute($comment = NULL) {
$comment->save(); $comment->save();
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\comment\CommentInterface $object */
$result = $object->status->access('edit', $account, TRUE)
->andIf($object->access('update', $account, TRUE));
return $return_as_object ? $result : $result->isAllowed();
}
} }
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
use Drupal\Core\Database\Connection; use Drupal\Core\Database\Connection;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
...@@ -132,4 +133,15 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s ...@@ -132,4 +133,15 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
$this->configuration['owner_uid'] = $this->connection->query('SELECT uid from {users_field_data} WHERE name = :name AND default_langcode = 1', array(':name' => $form_state->getValue('owner_name')))->fetchField(); $this->configuration['owner_uid'] = $this->connection->query('SELECT uid from {users_field_data} WHERE name = :name AND default_langcode = 1', array(':name' => $form_state->getValue('owner_name')))->fetchField();
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\node\NodeInterface $object */
$result = $object->access('update', $account, TRUE)
->andIf($object->uid->access('edit', $account, TRUE));
return $return_as_object ? $result : $result->isAllowed();
}
} }
...@@ -87,4 +87,12 @@ public function execute($object = NULL) { ...@@ -87,4 +87,12 @@ public function execute($object = NULL) {
$this->executeMultiple(array($object)); $this->executeMultiple(array($object));
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\node\NodeInterface $object */
return $object->access('delete', $account, $return_as_object);
}
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace Drupal\node\Plugin\Action; namespace Drupal\node\Plugin\Action;
use Drupal\Core\Action\ActionBase; use Drupal\Core\Action\ActionBase;
use Drupal\Core\Session\AccountInterface;
/** /**
* Demotes a node. * Demotes a node.
...@@ -28,4 +29,15 @@ public function execute($entity = NULL) { ...@@ -28,4 +29,15 @@ public function execute($entity = NULL) {
$entity->save(); $entity->save();
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\node\NodeInterface $object */
$result = $object->access('update', $account, TRUE)
->andIf($object->promote->access('edit', $account, TRUE));
return $return_as_object ? $result : $result->isAllowed();
}
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace Drupal\node\Plugin\Action; namespace Drupal\node\Plugin\Action;
use Drupal\Core\Action\ActionBase; use Drupal\Core\Action\ActionBase;
use Drupal\Core\Session\AccountInterface;
/** /**
* Promotes a node. * Promotes a node.
...@@ -24,9 +25,18 @@ class PromoteNode extends ActionBase { ...@@ -24,9 +25,18 @@ class PromoteNode extends ActionBase {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function execute($entity = NULL) { public function execute($entity = NULL) {
$entity->setPublished(TRUE);
$entity->setPromoted(TRUE); $entity->setPromoted(TRUE);
$entity->save(); $entity->save();
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\node\NodeInterface $object */
$access = $object->access('update', $account, TRUE)
->andif($object->promote->access('edit', $account, TRUE));
return $return_as_object ? $access : $access->isAllowed();
}
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace Drupal\node\Plugin\Action; namespace Drupal\node\Plugin\Action;
use Drupal\Core\Action\ActionBase; use Drupal\Core\Action\ActionBase;
use Drupal\Core\Session\AccountInterface;
/** /**
* Publishes a node. * Publishes a node.
...@@ -28,4 +29,15 @@ public function execute($entity = NULL) { ...@@ -28,4 +29,15 @@ public function execute($entity = NULL) {
$entity->save(); $entity->save();
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\node\NodeInterface $object */
$result = $object->access('update', $account, TRUE)
->andIf($object->status->access('edit', $account, TRUE));
return $return_as_object ? $result : $result->isAllowed();
}
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace Drupal\node\Plugin\Action; namespace Drupal\node\Plugin\Action;
use Drupal\Core\Action\ActionBase; use Drupal\Core\Action\ActionBase;
use Drupal\Core\Session\AccountInterface;
/** /**
* Provides an action that can save any entity. * Provides an action that can save any entity.
...@@ -27,4 +28,12 @@ public function execute($entity = NULL) { ...@@ -27,4 +28,12 @@ public function execute($entity = NULL) {
$entity->save(); $entity->save();
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\node\NodeInterface $object */
return $object->access('update', $account, $return_as_object);
}
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace Drupal\node\Plugin\Action; namespace Drupal\node\Plugin\Action;
use Drupal\Core\Action\ActionBase; use Drupal\Core\Action\ActionBase;
use Drupal\Core\Session\AccountInterface;
/** /**
* Makes a node sticky. * Makes a node sticky.
...@@ -24,9 +25,18 @@ class StickyNode extends ActionBase { ...@@ -24,9 +25,18 @@ class StickyNode extends ActionBase {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function execute($entity = NULL) { public function execute($entity = NULL) {
$entity->status = NODE_PUBLISHED;
$entity->sticky = NODE_STICKY; $entity->sticky = NODE_STICKY;
$entity->save(); $entity->save();
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\node\NodeInterface $object */
$access = $object->access('update', $account, TRUE)
->andif($object->sticky->access('edit', $account, TRUE));
return $return_as_object ? $access : $access->isAllowed();
}
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
use Drupal\Component\Utility\Tags; use Drupal\Component\Utility\Tags;
use Drupal\Core\Action\ConfigurableActionBase; use Drupal\Core\Action\ConfigurableActionBase;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
/** /**
* Unpublishes a node containing certain keywords. * Unpublishes a node containing certain keywords.
...@@ -65,4 +66,15 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s ...@@ -65,4 +66,15 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
$this->configuration['keywords'] = Tags::explode($form_state->getValue('keywords')); $this->configuration['keywords'] = Tags::explode($form_state->getValue('keywords'));
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\node\NodeInterface $object */
$access = $object->access('update', $account, TRUE)
->andIf($object->status->access('edit', $account, TRUE));
return $return_as_object ? $access : $access->isAllowed();
}
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace Drupal\node\Plugin\Action; namespace Drupal\node\Plugin\Action;
use Drupal\Core\Action\ActionBase; use Drupal\Core\Action\ActionBase;
use Drupal\Core\Session\AccountInterface;
/** /**
* Unpublishes a node. * Unpublishes a node.
...@@ -28,4 +29,15 @@ public function execute($entity = NULL) { ...@@ -28,4 +29,15 @@ public function execute($entity = NULL) {
$entity->save(); $entity->save();
} }
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\node\NodeInterface $object */
$access = $object->access('update', $account, TRUE)
->andIf($object->status->access('edit', $account, TRUE));
return $return_as_object ? $access : $access->isAllowed();
}
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace Drupal\node\Plugin\Action; namespace Drupal\node\Plugin\Action;
use Drupal\Core\Action\ActionBase; use Drupal\Core\Action\ActionBase;
use Drupal\Core\Session\AccountInterface;
/** /**
* Makes a node not sticky.