Roles can be deleted when upgrading from 9.5 to 10 if a module had removed permissions

Created on 8 March 2023, over 1 year ago
Updated 7 February 2024, 10 months ago

Problem/Motivation

We deployed the Drupal 10 upgrade to one of our largest sites yesterday and 4 roles were marked by user_update_10000 as having missing permissions. During the deployment at the config import step those roles were deleted and recreated resulting in all users tagged against those roles to lose them.

This does NOT happen when upgrading from 9.5.x to 10.1.x.

I have reproduced this issue with a vanilla installation but it does require some very specific steps as per below.

Marking Major (maybe should be critical) due to the data loss

Steps to reproduce

  1. Install the standard profile on 9.5.x
  2. Add a simple custom module test_module with a single permission "test module permission"
  3. Install the module and add "test module permission" to the content_editor role
  4. Export config to disk - I used drush cex
  5. Edit test_module.permissions.yml and remove the permission
  6. Manually edit user.role.content_editor.yml and remove the permission and the module dependency
  7. Manually edit core.extension.yml and remove test_module
  8. Checkout 10.0.x (not this does NOT happen on 10.1.x)
  9. Run update database and config import (in my case I used drush deploy which just runs those commands in sequence.

During database updates you'll get The role Content editor has had the following non-existent permission(s) removed: test module permission.

During config import you'll see the following:

>  [notice] Synchronized extensions: uninstall test_module.
>  [notice] Synchronized configuration: create user.role.content_editor.
>  [notice] Synchronized configuration: create system.action.user_remove_role_action.content_editor.
>  [notice] Synchronized configuration: create system.action.user_add_role_action.content_editor.

The module is being uninstalled because of the removal from core.extension.yml, and for some reason this deletes the role.

This must be something to do with the combination of the module being uninstalled while it had missing permissions and while the active role configuration still contains the module as a config dependency.

Proposed resolution

No idea, haven't found the case.

Remaining tasks

Figure out what causes this
Fix
Tests

πŸ› Bug report
Status

Active

Version

10.0 ✨

Component
User systemΒ  β†’

Last updated about 18 hours ago

Created by

πŸ‡¦πŸ‡ΊAustralia acbramley

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

Comments & Activities

  • Issue created by @acbramley
  • πŸ‡¦πŸ‡ΊAustralia larowlan πŸ‡¦πŸ‡ΊπŸ.au GMT+10

    I think the issue here is that a module is removing permissions while all this is happening, I think that needs to be done in a subsequent deploy

  • πŸ‡¦πŸ‡ΊAustralia acbramley

    So I've tracked the code path that causes this issue, but still no idea how to fix it. What happens is the following:

    1. user_update_10000 runs and removes the permission from the Role because it doesn't exist anymore
    2. When the module is being uninstalled by config import we come to ConfigManager::getConfigEntitiesToChangeOnDependencyRemoval
    3. This calls callOnDependencyRemoval which eventually ends up in Role::onDependencyRemoval
    4. Since $this->permissions doesn't contain the permission (because it was removed in step 1) this function returns FALSE
    5. That means back in getConfigEntitiesToChangeOnDependencyRemoval, $fixed is FALSE and therefore the role is added to $return['delete']
  • πŸ‡¦πŸ‡ΊAustralia acbramley

    I think the issue here is that a module is removing permissions while all this is happening, I think that needs to be done in a subsequent deploy

    In an ideal world, yeah. But I can imagine that there may be some modules out there that removed permissions in a D10 release. Maybe a site updates to that release in order to uninstall it during their D10 upgrade. That would result in the same bug.

    For us, we were removing the block_content_revision_ui module. We use stub modules (i.e a custom module committed to the repo with just an info file) to allow us to uninstall the module at the same time as removing it from composer. This is a fairly edge case workflow but it could definitely happen with real module upgrades.

  • πŸ‡ΊπŸ‡ΈUnited States clayfreeman Paragould, AR

    I'm experiencing something similar. We had the comment module installed (via the standard install profile in Drupal core) and removed it recently because of the security advisory related to that module. This caused some roles to be updated to remove permissions that were provided by that module. As a result, views which used role-based access control and referenced a role that was updated were deleted. We were able to import these views without modification using Configuration > Development > Config synchronization > Import.

  • πŸ‡ΊπŸ‡ΈUnited States hyperlinked San Jose, CA

    This was happening to me too and in my situation there was a very easy workaround. I normally run "drush config-import" first before running "drush updatedb".

    I just ran drush updatedb first so that permissions that would be removed when I updated the config wouldn't be removed yet.

  • πŸ‡¦πŸ‡ΊAustralia acbramley

    @hyperlinked fwiw, you should always run updb before config import. Database updates can make changes to your configuration, those should be run on a local/development environment first and then the config changes should be exported. Then when deployed you'll have a clean deploy process with updb then import. This is how drush deploy works (highly recommend using that :))

Production build 0.71.5 2024