Adding non-existent permissions to a role is not allowed.

Created on 23 November 2023, 7 months ago
Updated 14 December 2023, 7 months ago

Problem/Motivation

When i try to save user permissions, I get this error:

RuntimeException: Adding non-existent permissions to a role is not allowed. The incorrect permissions are "legal re-accept term_condition", "legal view term_condition". in Drupal\user\Entity\Role->calculateDependencies() (line 207 of core/modules/user/src/Entity/Role.php).
Drupal\Core\Config\Entity\ConfigEntityBase->preSave(Object) (Line: 179)
Drupal\user\Entity\Role->preSave(Object) (Line: 528)
Drupal\Core\Entity\EntityStorageBase->doPreSave(Object) (Line: 483)
Drupal\Core\Entity\EntityStorageBase->save(Object) (Line: 257)
Drupal\Core\Config\Entity\ConfigEntityStorage->save(Object) (Line: 339)
Drupal\Core\Entity\EntityBase->save() (Line: 609)
Drupal\Core\Config\Entity\ConfigEntityBase->save() (Line: 990)
user_role_grant_permissions('authenticated', Array) (Line: 964)
user_role_change_permissions('authenticated', Array) (Line: 228)
Drupal\user\Form\UserPermissionsForm->submitForm(Array, Object)
call_user_func_array(Array, Array) (Line: 114)
Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 52)
Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 597)
Drupal\Core\Form\FormBuilder->processForm('user_admin_permissions', Array, Object) (Line: 325)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 592)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 121)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 181)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 76)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 704)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Steps to reproduce

Create a legal document "term_condition"
Assign permission to user
Remove legal document "term_condition"
Go to permission page and update permissions

🐛 Bug report
Status

Fixed

Version

4.0

Component

Code

Created by

🇮🇹Italy trickfun

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

Merge Requests

Comments & Activities

  • Issue created by @trickfun
  • @trickfun I don't think it's the module issue, as I was trying to recreate it and you are able to get this error only when you leave the permission page open while you remove legal document in new tab, and you try to save outdated permission page what leads to this error.
    It's the only way I was able to recreate it, and it seems more like core's permission form issue and how it handles outdated forms, not the module. But maybe you can provide more details about steps to reproduce if your steps were different..

  • Open in Jenkins → Open on Drupal.org →
    Core: 10.1.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    Build Successful
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.1 & MySQL 5.7
    last update 7 months ago
    Build Successful
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.1.x + Environment: PHP 8.1 & MySQL 8
    last update 7 months ago
    Build Successful
  • Status changed to Needs review 7 months ago
  • Okay so the issue is that permissions should be revoked when entity_legal_document config entity is deleted, and it's not. It leads this error to appear. It seems to be quite well known issue for multiple projects and I think the best solution is to add dependencies to our permissions in EntityLegalPermissions, it has been introduced here: https://www.drupal.org/node/3055548 .
    I've created fork issue and merge request.

  • I think it may be good to mention that this code fix the source, but it won't fix the error which appeared already. In this case we might need to prepare hook update which goes through roles and revoke permissions for deleted legal document entities already. Let me know if we need to do that as well in scope of the module.

  • Status changed to Needs work 7 months ago
  • 🇷🇴Romania claudiu.cristea Arad 🇷🇴

    Thank you for catching this.

    • I think it needs a simple kernel test that created a document, sets the permission to a role. After the document is deleted, we have to assert that the permission has been removed from the role
    • Indeed, we need an update path. Try and get some inspiration from entity_legal_post_update_9002().
  • Assigned to ad0z
  • @claudiu.cristea got it, I will code it.

  • Issue was unassigned.
  • @claudiu.cristea added simple kernel test, but second point does not make sense for me..

    >Indeed, we need an update path. Try and get some inspiration from entity_legal_post_update_9002().

    Why do we need to update path? Did you mean update existing roles permissions?

  • 🇷🇴Romania claudiu.cristea Arad 🇷🇴

    Why do we need to update path? Did you mean update existing roles permissions?

    I was thinking that some sites might have already roles with stale permissions. But, indeed, it might be overkill to cover this scenario

  • Status changed to Needs review 7 months ago
  • @claudiu.cristea

    That's the code which resolve stale permissions issue, I suppose we could put it into post_update hook.

      $legal_entities = array_keys(EntityLegalDocument::loadMultiple());
      $roles = Role::loadMultiple();
      foreach ($roles as $role) {
        $update = FALSE;
        $permissions = $role->getPermissions();
        foreach ($permissions as $permission) {
          preg_match("/^(legal view |legal re-accept )(.*)/", $permission, $match);
          $machine_name = $match[2] ?? NULL;
          // Check if there is legal entity matching to checked permission.
          if ($machine_name && !in_array($machine_name, $legal_entities)) {
            $role->revokePermission($permission);
            $update = TRUE;
          }
        }
        if ($update) {
          $role->save();
        }
      }
    
  • Status changed to RTBC 7 months ago
  • 🇷🇴Romania claudiu.cristea Arad 🇷🇴

    Let's not complicate. We're in alpha with 4. I will merge it as it is. Projects with such cases will have to deal manually with it

  • Status changed to Fixed 7 months ago
  • 🇷🇴Romania claudiu.cristea Arad 🇷🇴
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.69.0 2024