Skip to content

Commit e187ee1

Browse files
committed
Issue #3007716 by Sam152, kevin.dutra, jhedstrom, larowlan: Security update introduces breaking changes to content moderation
(cherry picked from commit 73d9d9b)
1 parent 64947e1 commit e187ee1

File tree

4 files changed

+56
-24
lines changed

4 files changed

+56
-24
lines changed

modules/content_moderation/src/Plugin/Validation/Constraint/ModerationStateConstraintValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public function validate($value, Constraint $constraint) {
123123
else {
124124
// If we're sure the transition exists, make sure the user has permission
125125
// to use it.
126-
if (!$this->stateTransitionValidation->isTransitionValid($workflow, $original_state, $new_state, $this->currentUser)) {
126+
if (!$this->stateTransitionValidation->isTransitionValid($workflow, $original_state, $new_state, $this->currentUser, $entity)) {
127127
$this->context->addViolation($constraint->invalidTransitionAccess, [
128128
'%original_state' => $original_state->label(),
129129
'%new_state' => $new_state->label(),

modules/content_moderation/src/StateTransitionValidation.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ public function getValidTransitions(ContentEntityInterface $entity, AccountInter
5252
/**
5353
* {@inheritdoc}
5454
*/
55-
public function isTransitionValid(WorkflowInterface $workflow, StateInterface $original_state, StateInterface $new_state, AccountInterface $user) {
55+
public function isTransitionValid(WorkflowInterface $workflow, StateInterface $original_state, StateInterface $new_state, AccountInterface $user, ContentEntityInterface $entity = NULL) {
56+
if ($entity === NULL) {
57+
@trigger_error(sprintf('Omitting the $entity parameter from %s is deprecated and will be required in Drupal 9.0.0.', __METHOD__), E_USER_DEPRECATED);
58+
}
5659
$transition = $workflow->getTypePlugin()->getTransitionFromStateToState($original_state->id(), $new_state->id());
5760
return $user->hasPermission('use ' . $workflow->id() . ' transition ' . $transition->id());
5861
}

modules/content_moderation/src/StateTransitionValidationInterface.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@ public function getValidTransitions(ContentEntityInterface $entity, AccountInter
3636
* The new workflow state.
3737
* @param \Drupal\Core\Session\AccountInterface $user
3838
* The user to validate.
39+
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
40+
* (optional) The entity to be transitioned. Omitting this parameter is
41+
* deprecated and will be required in Drupal 9.0.0.
3942
*
4043
* @return bool
4144
* Returns TRUE if transition is valid, otherwise FALSE.
4245
*/
43-
public function isTransitionValid(WorkflowInterface $workflow, StateInterface $original_state, StateInterface $new_state, AccountInterface $user);
46+
public function isTransitionValid(WorkflowInterface $workflow, StateInterface $original_state, StateInterface $new_state, AccountInterface $user, ContentEntityInterface $entity = NULL);
4447

4548
}

modules/content_moderation/tests/src/Unit/StateTransitionValidationTest.php

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Drupal\Tests\UnitTestCase;
1111
use Drupal\workflow_type_test\Plugin\WorkflowType\TestType;
1212
use Drupal\workflows\Entity\Workflow;
13+
use Drupal\workflows\State;
1314
use Drupal\workflows\WorkflowTypeManager;
1415
use Prophecy\Argument;
1516

@@ -19,6 +20,38 @@
1920
*/
2021
class StateTransitionValidationTest extends UnitTestCase {
2122

23+
/**
24+
* A test workflow.
25+
*
26+
* @var \Drupal\workflows\WorkflowInterface
27+
*/
28+
protected $workflow;
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
protected function setUp() {
34+
parent::setUp();
35+
36+
// Create a container so that the plugin manager and workflow type can be
37+
// mocked.
38+
$container = new ContainerBuilder();
39+
$workflow_manager = $this->prophesize(WorkflowTypeManager::class);
40+
$workflow_manager->createInstance('content_moderation', Argument::any())->willReturn(new TestType([], '', []));
41+
$container->set('plugin.manager.workflows.type', $workflow_manager->reveal());
42+
\Drupal::setContainer($container);
43+
44+
$this->workflow = new Workflow(['id' => 'process', 'type' => 'content_moderation'], 'workflow');
45+
$this->workflow
46+
->getTypePlugin()
47+
->addState('draft', 'draft')
48+
->addState('needs_review', 'needs_review')
49+
->addState('published', 'published')
50+
->addTransition('draft', 'draft', ['draft'], 'draft')
51+
->addTransition('review', 'review', ['draft'], 'needs_review')
52+
->addTransition('publish', 'publish', ['needs_review', 'published'], 'published');
53+
}
54+
2255
/**
2356
* Verifies user-aware transition validation.
2457
*
@@ -47,7 +80,10 @@ public function testUserSensitiveValidTransitions($from_id, $to_id, $permission,
4780
$entity->moderation_state = new \stdClass();
4881
$entity->moderation_state->value = $from_id;
4982

50-
$validator = new StateTransitionValidation($this->setUpModerationInformation($entity));
83+
$moderation_info = $this->prophesize(ModerationInformationInterface::class);
84+
$moderation_info->getWorkflowForEntity($entity)->willReturn($this->workflow);
85+
86+
$validator = new StateTransitionValidation($moderation_info->reveal());
5187
$has_transition = FALSE;
5288
foreach ($validator->getValidTransitions($entity, $user->reveal()) as $transition) {
5389
if ($transition->to()->id() === $to_id) {
@@ -58,27 +94,17 @@ public function testUserSensitiveValidTransitions($from_id, $to_id, $permission,
5894
$this->assertSame($result, $has_transition);
5995
}
6096

61-
protected function setUpModerationInformation(ContentEntityInterface $entity) {
62-
// Create a container so that the plugin manager and workflow type can be
63-
// mocked.
64-
$container = new ContainerBuilder();
65-
$workflow_manager = $this->prophesize(WorkflowTypeManager::class);
66-
$workflow_manager->createInstance('content_moderation', Argument::any())->willReturn(new TestType([], '', []));
67-
$container->set('plugin.manager.workflows.type', $workflow_manager->reveal());
68-
\Drupal::setContainer($container);
69-
70-
$workflow = new Workflow(['id' => 'process', 'type' => 'content_moderation'], 'workflow');
71-
$workflow
72-
->getTypePlugin()
73-
->addState('draft', 'draft')
74-
->addState('needs_review', 'needs_review')
75-
->addState('published', 'published')
76-
->addTransition('draft', 'draft', ['draft'], 'draft')
77-
->addTransition('review', 'review', ['draft'], 'needs_review')
78-
->addTransition('publish', 'publish', ['needs_review', 'published'], 'published');
97+
/**
98+
* @expectedDeprecation Omitting the $entity parameter from Drupal\content_moderation\StateTransitionValidation::isTransitionValid is deprecated and will be required in Drupal 9.0.0.
99+
* @group legacy
100+
*/
101+
public function testDeprecatedEntityParameter() {
79102
$moderation_info = $this->prophesize(ModerationInformationInterface::class);
80-
$moderation_info->getWorkflowForEntity($entity)->willReturn($workflow);
81-
return $moderation_info->reveal();
103+
$state = new State($this->workflow->getTypePlugin(), 'draft', 'draft');
104+
$user = $this->prophesize(AccountInterface::class);
105+
106+
$validator = new StateTransitionValidation($moderation_info->reveal());
107+
$validator->isTransitionValid($this->workflow, $state, $state, $user->reveal());
82108
}
83109

84110
/**

0 commit comments

Comments
 (0)