Problem/Motivation

Under certain configurations, a user can arrive at a node form and only find a Preview button, or if preview is disabled, no button at all.

Steps to reproduce

  1. Enable moderation on the Article content type
  2. Grant authenticated users the permission to create article content
  3. Log in as a normal authenticated user
  4. Try to add an article

Proposed resolution

Potential resolutions:

  1. Deny access to the add page if the user doesn't have access to the default moderation state
  2. Allow access to the add page, use a simple Save button, and then default the content to its default moderation state

Remaining tasks

Discuss potential resolution options, and implement.

User interface changes

Yes.

API changes

Data model changes

CommentFileSizeAuthor
#40 workbench_moderation-2738869-35.patch6.14 KBNamzhilma Zhambalova
#34 workbench_moderation_2738869_34.patch11.26 KBpericxc
#34 interdiff-workbench_moderation_2738869_09-34.txt2.93 KBpericxc
#31 workbench_moderation-2738869-09.patch11.21 KBpericxc
#31 interdiff-workbench_moderation-2738869-08-09.txt2.68 KBpericxc
#27 workbench_moderation-2738869-08.patch10.94 KBpericxc
#27 interdiff-workbench_moderation-2738869-07-08.txt2.3 KBpericxc
#25 workbench_moderation-2738869-07.patch10.58 KBpericxc
#25 interdiff-workbench_moderation-2738869-06-07.txt2.76 KBpericxc
#22 workbench_moderation-2738869-06.patch11.48 KBpericxc
#22 interdiff-workbench_moderation-2738869-05-06.txt1.52 KBpericxc
#17 workbench_moderation-2738869-05.patch11.25 KBpericxc
#17 interdiff-workbench_moderation-2738869-04-05.txt4.7 KBpericxc
#11 workbench_moderation-2738869-04.patch8.34 KBpericxc
#11 interdiff-workbench_moderation-2738869-03-04.txt4.95 KBpericxc
#8 workbench_moderation-2738869-03.patch5.14 KBpericxc
#8 interdiff-workbench_moderation-2738869-01-03.txt5.78 KBpericxc
#4 workbench_moderation-2738869-01.patch1.54 KBpericxc
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jhedstrom created an issue. See original summary.

scookie’s picture

Note: This can also occur on the Edit draft page when the user doesn't have access to any state transition for which the "from" state matches the current state of the node and the "to" state is enabled for the content type of the node. User only sees a Cancel button (when that button is enabled).

scookie’s picture

Another scenario in which this can occur is if no state transition has been added involving the default state for the content type.

pericxc’s picture

This patch take fix this issue with #1 proposed resolution.

pericxc’s picture

Status: Active » Needs review
jhedstrom’s picture

  1. +++ b/workbench_moderation.module
    @@ -235,3 +235,37 @@ function workbench_moderation_views_data_alter(array &$data) {
    +function wdc_user_node_create_access(AccountInterface $account, array $context, $entity_bundle) {
    

    This should be implemented on behalf of the workbench_moderation module.

    It should be noted that by solving this via a node-specific hook, this solution will only be applicable to nodes. I haven't done further investigation to determine if there is a more general solution, but this should be fine for the time being.

  2. +++ b/workbench_moderation.module
    @@ -235,3 +235,37 @@ function workbench_moderation_views_data_alter(array &$data) {
    +    $definitions = \Drupal::config('node.type.' . $entity_bundle)->get('third_party_settings');
    +    $default_moderation_state = $definitions['workbench_moderation']['default_moderation_state'];
    

    Rather than directly load the setting from config, I think it would be preferable here to load the config entity (in this case it would be a NodeTypeInterface) via the entity type manager, and then the getThirdPartySetting($module, $key, $default = NULL) method could be used.

kevin.dutra’s picture

I agree with @jhedstrom on his first point. I think it would be better to take the more generic approach using hook_entity_create_access().

Also, as @scookie mentioned in #2, we would also need the equivalent version of hook_entity_access() to cover edit access too.

jhedstrom’s picture

  1. +++ b/src/ModerationInformationInterface.php
    @@ -208,4 +209,20 @@ interface ModerationInformationInterface {
    +   * @param $entity_type_id
    ...
    +   * @param $entity_bundle
    

    Parameter type is missing here.

  2. +++ b/src/ModerationInformationInterface.php
    @@ -208,4 +209,20 @@ interface ModerationInformationInterface {
    +  public function isModerationBundleCreateValid(AccountInterface $account, $entity_type_id, $entity_bundle);
    

    Perhaps rename this method to hasValidTransitions()? It could then be used for the edit operation too (which still needs to be implemented).

  3. +++ b/workbench_moderation.module
    @@ -180,7 +180,7 @@ function workbench_moderation_node_access(NodeInterface $entity, $operation, Acc
    +    return !empty($transition_validation->getValidTransitionTargets($entity, $account))
    

    Is this change necessary?

  4. +++ b/workbench_moderation.module
    @@ -235,3 +235,16 @@ function workbench_moderation_views_data_alter(array &$data) {
    + * Implements hook_node_create_access().
    

    This is still node-specific. Can the same be achieved more generally via the entity hook mentioned above?

These changes are complex enough that I think some tests would help ensure this situation doesn't happen again (those tests can also be used to demonstrate the current bug this is fixing).

pericxc’s picture

@jhedstrom

#4 The reason I used hook_node_create_access() because hook_node_access() no longer fires for the 'create' operation: Issue.

#3 I think it is necessary in case an empty array for target states is returned. That is the fix for the bug scookie mentioned in #1.

The rest will be fixed.

jhedstrom’s picture

Status: Needs review » Reviewed & tested by the community

This is looking really good.

@pericxc pointed out that there isn't really a generic entity access hook, so for the time being, this will need to be mostly node-specific.

I'm going to mark this RTBC to get a few more eyes on for review.

kevin.dutra’s picture

Status: Reviewed & tested by the community » Needs work

Putting back to "needs work" for a minute just to make sure I'm understanding things correctly about the generic entity access point. There are a couple generic entity access hooks available:

The current implementation uses the entity type specific variants of these hooks:

Wouldn't we want to use the more generic forms? Workbench Moderation is applicable to entity types beyond just nodes, right? Or am I missing something? :)

jhedstrom’s picture

@kevin.dutra you're totally right. When I spoke with @pericxc whatever search I was using to find docs on those seemed to not find them.

So given that, I think the node-specific access hooks should be refactored, and one additional test should be added that uses a non-node entity type (EntityTest probably).

pericxc’s picture

@jhedstrom and @kevin.dutra,

The module is using hook_node_access for the 'view' and 'update' operation, so it seemed logical to use hook_node_create_access to for 'create' operation.

jhedstrom’s picture

The module is using hook_node_access for the 'view' and 'update' operation

Indeed it is. So perhaps this patch can continue to utilize node-specific access, but we could open a follow-up to generalize this logic where possible. Note the isPublished() method utilized in workbench_moderation_node_access(), while used on several core entity types, does not appear to be part of a more general interface.

pericxc’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 17: workbench_moderation-2738869-05.patch, failed testing.

The last submitted patch, 17: workbench_moderation-2738869-05.patch, failed testing.

The last submitted patch, 17: workbench_moderation-2738869-05.patch, failed testing.

pericxc’s picture

pericxc’s picture

I was wondering if the title should be changed since the issue got extended to cover issues with hooks!

jhedstrom’s picture

  1. +++ b/src/Tests/ModerationStateTransitionsValidationTest.php
    @@ -0,0 +1,155 @@
    +
    ...
    +
    

    Nit: extra line breaks here.

  2. +++ b/workbench_moderation.module
    @@ -167,22 +167,25 @@ function workbench_moderation_entity_view(array &$build, EntityInterface $entity
    +  $type = $entity->getEntityType();
    

    This variable doesn't appear to be used.

  3. +++ b/workbench_moderation.module
    @@ -167,22 +167,25 @@ function workbench_moderation_entity_view(array &$build, EntityInterface $entity
    +    } elseif ($operation == 'update' && $moderation_info->isModeratableEntity($entity) && $entity->moderation_information && $entity->moderation_information->target_id) {
    +      /** @var \Drupal\workbench_moderation\StateTransitionValidation $transition_validation */
    +      $transition_validation = \Drupal::service('workbench_moderation.state_transition_validation');
    +
    +      return !empty($transition_validation->getValidTransitionTargets($entity, $account))
    +        ? AccessResult::neutral()
    +        : AccessResult::forbidden();
    

    Unless I'm missing something, this part isn't node specific at all, so could be moved to apply to all entities? If that is the case, the non-node test should test the update operation too.

jhedstrom’s picture

This is looking really close.

+++ b/workbench_moderation.module
@@ -168,24 +168,21 @@
+  elseif ($operation == 'update' && $moderation_info->isModeratableEntity($entity) && $entity->moderation_information && $entity->moderation_information->target_id) {

Can you update the non-node test to check for the 'update' operation and expected access?

Status: Needs review » Needs work

The last submitted patch, 27: workbench_moderation-2738869-08.patch, failed testing.

The last submitted patch, 27: workbench_moderation-2738869-08.patch, failed testing.

The last submitted patch, 27: workbench_moderation-2738869-08.patch, failed testing.

pericxc’s picture

jhedstrom’s picture

Status: Needs review » Reviewed & tested by the community

This looks good. I manually tested as well to confirm. I also like that it takes a further step toward non-node-specific entity moderation.

larowlan’s picture

Looking good, some minor adjustments

  1. +++ b/src/ModerationInformation.php
    @@ -212,5 +212,30 @@ class ModerationInformation implements ModerationInformationInterface {
    +  $entity = $this->entityTypeManager->getDefinition($entity_type_id);
    ...
    +    foreach (\Drupal::entityTypeManager()->getStorage('moderation_state_transition')->loadMultiple() as $transition) {
    

    Please use the injected version instead of the global singleton

  2. +++ b/workbench_moderation.module
    @@ -235,3 +235,18 @@ function workbench_moderation_views_data_alter(array &$data) {
    +    $modinfo = Drupal::service('workbench_moderation.moderation_information');
    ...
    +    if (!$modinfo->hasValidTransitions($account, $context['entity_type_id'], $entity_bundle)) {
    

    nit: can you use a better variable name than $modinfo - eg $moderation_info

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 34: workbench_moderation_2738869_34.patch, failed testing.

The last submitted patch, 34: workbench_moderation_2738869_34.patch, failed testing.

The last submitted patch, 34: workbench_moderation_2738869_34.patch, failed testing.

The last submitted patch, 34: workbench_moderation_2738869_34.patch, failed testing.

pericxc’s picture

Status: Needs work » Needs review
Namzhilma Zhambalova’s picture

Hello,

I had bug with https://www.drupal.org/files/issues/workbench_moderation_2738869_34.patch patch.

On site I have 2 CTs, Article has moderation, Page doesn't have.
User (not admin) has permission to create Page.
But when user goes to page node/add/page, he sees Access Denied page.

I changed https://www.drupal.org/files/issues/workbench_moderation_2738869_34.patch to fix the issue.

Status: Needs review » Needs work

The last submitted patch, 40: workbench_moderation-2738869-35.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.