Deleting user account reverted all content authored by user to old revisions in live environment

Created on 23 October 2019, over 5 years ago
Updated 2 June 2023, almost 2 years ago

We were cleaning up user accounts from our live environment and deleted some users from our application. When deleting we selected

"Delete the account and make its content belong to the Anonymous user."

This has reverted all content originally authored by this user to prior revisions, bypassing all workflows for pushing content live. This happened to multiple pages, one is demonstrated in attached screen shot.

πŸ› Bug report
Status

Active

Version

11.0 πŸ”₯

Component
Content moderationΒ  β†’

Last updated 2 days ago

  • Maintained by
  • πŸ‡¦πŸ‡ΊAustralia @Sam152
Created by

πŸ‡ΊπŸ‡ΈUnited States erincarey

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States bkosborne New Jersey, USA

    As per #4, this is apparently happening with people using core's Content Moderation module (which makes sense, since it was mostly a port of the contrib Workbench Moderation module). Moving this to the core issue queue. Also marking πŸ› Deleting user account reverted all content authored by user to old revisions Closed: duplicate as a duplicate of this, as I assume that user was also using Content Moderation.

    See also πŸ› Revision user incorrectly appears as anonymous user when node author is cancelled Needs work . The user in comment #29 experienced this as well, though it's not clear they were using Content Moderation or Workbench Moderation at the time.

  • πŸ‡ͺπŸ‡ΈSpain tunic Madrid

    In our case an admin deleted a user and suddenly web reverted back to few months ago, we had to use a backup. This is a major bug because the damage that can be done to the website is enormous.

    I can't provide more data because we are still investigating to reproduce the bug.

  • πŸ‡ͺπŸ‡ΈSpain lpeidro Madrid

    In our case, we have identified the cause of the activation of an outdated revision as the default revision and the duplication of revisions.

    It is caused by the Content Moderation module.

    This module intervenes in the process through a "presave" hook, and under certain circumstances, it incorrectly designates that revision as new and sets it as the default revision.

    
    namespace Drupal\content_moderation\Entity\Handler;
    
    [.....]
    
     /**
       * {@inheritdoc}
       */
      public function onPresave(ContentEntityInterface $entity, $default_revision, $published_state) {
        // When entities are syncing, content moderation should not force a new
        // revision to be created and should not update the default status of a
        // revision. This is useful if changes are being made to entities or
        // revisions which are not part of editorial updates triggered by normal
        // content changes.
        if (!$entity->isSyncing()) {
         $entity->setNewRevision(TRUE);
         $entity->isDefaultRevision($default_revision);
        }
    
        // Update publishing status if it can be updated and if it needs updating.
        if (($entity instanceof EntityPublishedInterface) && $entity->isPublished() !== $published_state) {
          $published_state ? $entity->setPublished() : $entity->setUnpublished();
        }
      }
    

    Conditions for this case to occur:

    • - The Content Moderation module is enabled.
    • - The content type of the revision being modified is a moderated content.
    • - The Moderation State of the revision is not empty.

    At this point, a new revision will be created.

    For this revision to be set as the default, the current default revision has to belong to other user and meet one of these conditions:

    • - That the revision's state is considered a default revision state.
    • - Or that the default revision at this moment is not in a published state.

    It is clear that this problem is introduced by a contributed module and not the core, but we believe that the consequences are too severe, and it would be advisable to devise a strategy to ensure that at the very least, old revisions are not activated by any module.

  • πŸ‡ͺπŸ‡ΈSpain lpeidro Madrid

    As I mentioned in my previous comment ( https://www.drupal.org/project/drupal/issues/3089747#comment-15212151 πŸ› Content moderation can wrongly set old revisions as default when they're resaved Needs review ), there is a patch that addresses the issue of obsolete revisions being triggered as default revisions in our project, but we believe it's not the best solution.

    The revision that is being updated should not pass through the Content Moderation presave hook, as this modification is unrelated to a publishing workflow.

    Here is the process of replacement:

    • First, obtain the identifiers of all revisions generated by the user.
    • Load the node of each revision.
    • Replace the uid and review_uid with 0 in all active translations for the content (I've found the same revision ID assigned to a user in both French and English).
    • Proceed with saving the node.

    This process cause that any presave or postsave hook can alter the entity or run inappropriate processes in this context.

  • πŸ‡¬πŸ‡§United Kingdom catch

    Bumping to critical and changing the title to make it clearer what the bug is.

  • πŸ‡ͺπŸ‡ΈSpain lpeidro Madrid

    It's a very drastic solution that needs careful consideration, but since this type of modification doesn't belong to an editorial workflow, would it be unreasonable for the solution to involve preventing the Content Moderation module hooks from being triggered?

    We conducted a test, and by disabling these hooks, the process went smoothly

  • πŸ‡ΊπŸ‡ΈUnited States luke.leber Pennsylvania

    I think that I agree with the approach in #8 (setting the syncing flag prior to re-saving).

    I think an optional parameter added to node_mass_update would be a fairly elegant solution:

    function node_mass_update(array $nodes, array $updates, $langcode = NULL, $load = FALSE, $revisions = FALSE, $syncing = FALSE) {
    
      // ...
      // ...
    
        foreach ($nodes as $node) {
          if ($load && $revisions) {
            $node = $storage->loadRevision($node);
          }
    +    if ($syncing) {
    +      $node->setSyncing(TRUE);
    +    }
          _node_mass_update_helper($node, $updates, $langcode);
        }
        \Drupal::messenger()->addStatus(t('The update has been performed.'));
    }
    

    then invoked via node_user_cancel:

          node_mass_update($vids, [
            'uid' => 0,
            'revision_uid' => 0,
          ], NULL, TRUE, TRUE, TRUE);
    
  • πŸ‡¬πŸ‡§United Kingdom catch

    Yeah I also think ::setSyncing() is the right approach here, user module is going back in time to alter metadata for old revisions, it's not really updating the content or anything.

  • πŸ‡ͺπŸ‡ΈSpain lpeidro Madrid

    Perfect. So, I'm going to try to improve the patch with Luke Leber's proposal.

    I will also attempt to address the issue of replacing all authors of revisions with an anonymous user since the current patch doesn't resolve that.

    This case doesn't occur exactly in the code snippet mentioned in my previous comment 8, so I'll need to find the exact location where it occurs.

    Thank you!

  • last update over 1 year ago
    Custom Commands Failed
  • last update over 1 year ago
    30,136 pass
  • πŸ‡ͺπŸ‡ΈSpain lpeidro Madrid

    I have just committed the proposed solution in the previous comments and generated the Merge Request.

    Ready for review.

    Thanks.

  • Status changed to Needs review over 1 year ago
  • πŸ‡ͺπŸ‡ΈSpain lpeidro Madrid
  • Status changed to Needs work over 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Appears to be an open thread.

    Also can we get a test case showing the issue?

  • πŸ‡ͺπŸ‡ΈSpain eduardo morales alberti Spain, πŸ‡ͺπŸ‡Ί

    Eduardo Morales Alberti β†’ made their first commit to this issue’s fork.

  • last update over 1 year ago
    Custom Commands Failed
  • Status changed to Needs review over 1 year ago
  • last update over 1 year ago
    Patch Failed to Apply
  • πŸ‡ͺπŸ‡ΈSpain eduardo morales alberti Spain, πŸ‡ͺπŸ‡Ί

    Added PHPUnit tests, waiting to see their success on the build.
    Added tests only patch to check that is failing without the fixes on the MR.

  • last update over 1 year ago
    30,380 pass
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Environment: PHP 8.1 & MariaDB 10.3.22
    last update over 1 year ago
    Patch Failed to Apply
  • last update over 1 year ago
    30,380 pass
  • πŸ‡ͺπŸ‡ΈSpain eduardo morales alberti Spain, πŸ‡ͺπŸ‡Ί

    Upload the right patch.

  • last update over 1 year ago
    30,380 pass
  • last update over 1 year ago
    30,342 pass
  • πŸ‡ͺπŸ‡ΈSpain eduardo morales alberti Spain, πŸ‡ͺπŸ‡Ί

    Seems like on the last version of Drupal (11.x) this error is not happening.

  • πŸ‡ͺπŸ‡ΈSpain eduardo morales alberti Spain, πŸ‡ͺπŸ‡Ί

    Currently, we are not able to reproduce this problem, so the PHPUnit test is not accurate.
    Someone could provide the step by step to reproduce this problem?

  • Status changed to Postponed: needs info over 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Hate putting a critical in PNMI but seems steps to reproduce are needed to continue.

    So if anyone experiencing this could add those.

    Also tagged for IS so steps could be added in addition to the solution was used.

    Leaving tests tag as #22 shows current test passes as is.

  • last update about 1 year ago
    Custom Commands Failed
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Just following up if anyone is still experiencing this?

Production build 0.71.5 2024