Problem/Motivation

We found out in #2248977: Complete support for multi-value base fields in ContentEntitySchemaHandler and use it for the user.roles field that #2217749: Entity base class should provide standardized cache tags and built-in invalidation accidentally removed the call to delete the references.

This could possibly be a security related problem, if you delete a role and then create a new one with the same name, your users will still/again have it, and that won't be what you expected.

Proposed resolution

Add back a call to it. We also need to move the method to UserStorage, because it is just wrong on RoleStorage, as it is about stored users, not roles.

This is a generic problem that all entity reference fields have, but I don't know how to solve this in a generic way...

We also need to clear the cache with $this->resetCache().

Remaining tasks

User interface changes

API changes

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Bug because leaves orphan data in users after deletion of roles
Issue priority Major because it is a potential security problem.
CommentFileSizeAuthor
#17 interdiff-13-17.txt1.28 KBAnonymous (not verified)
#17 user-role-permission-assignments-2390467-17.patch5.48 KBAnonymous (not verified)
#16 interdiff-3-16.txt6.18 KBAnonymous (not verified)
#16 user-role-permission-assignments-2390467-16.patch5.48 KBAnonymous (not verified)
#13 user-role-permission-assignments-2390467-13-test-only.patch2.35 KBAnonymous (not verified)
#13 user-role-permission-assignments-2390467-13.patch5.87 KBAnonymous (not verified)
#13 interdiff-3-13.txt6.23 KBAnonymous (not verified)
#8 interdiff-3-8.txt3.08 KBAnonymous (not verified)
#8 user-role-permission-assignments-2390467-8.patch3.09 KBAnonymous (not verified)
#3 user-role-permission-assignments-2390467-3.patch1.22 KBadamwhite
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Berdir’s picture

Issue tags: +Security improvements
adamwhite’s picture

Issue tags: +SprintWeekend2015

Issue was reproduced and confirmed to still be happening. Looking at this for SprintWeekend2015.

adamwhite’s picture

Here's a patch that calls RoleStorage::deleteRoleReferences() upon deletion of a role.

However for the first pass at this I've left it in RoleStorage rather than UserStorage. It could be argued that since cleaning up these references would be the responsibility of the Role the method should live there. Furthermore the methods in UserStorage seem to mostly be related so singular User entities and not the multiple as this method would address.

However it could absolutely run from UserStorage as well, you'd just swap:

$user_storage = \Drupal::entityManager()->getStorage('user');
$user_storage->resetCache();

for

$this->resetCache();

trevortwining’s picture

I've successfully tested the patch in #3.

You can create a role, assign it to a user, delete the role, recreate the role, and it doesn't 're-inherit' the original assignment.

trevortwining’s picture

Status: Active » Needs review
Berdir’s picture

Status: Needs review » Needs work

Thanks for starting this.

The method really needs to move. roles are stored in configuration, user__roles is a field that belongs to the user. If you would store your users in MongoDB for example, then that method in RoleStorage would fail, so you would have to replace RoleStorage as well.

We have someone at our local sprint that will try to do this.

Anonymous’s picture

Assigned: Unassigned »

I'll try it

Anonymous’s picture

Status: Needs work » Needs review
FileSize
3.09 KB
3.08 KB

I have moved the method from RoleStorage into the UserStorage.

Anonymous’s picture

Assigned: » Unassigned
Berdir’s picture

Status: Needs review » Needs work

This looks good, but we still need tests (which you are working on already as I can hear :))

Also, I'm wondering if Role::postDelete() should move to a user_role_delete() hook, as it the role entity should not have to know about it?

penyaskito’s picture

Thanks @trevortwining, @adamwhite and @iPat for working on this!

  1. +++ b/core/modules/user/src/Entity/Role.php
    @@ -154,4 +154,14 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
    +      $user_storage = \Drupal::entityManager()->getStorage('user');
    

    We could use $this->entityManager() here, it is already injected.

  2. +++ b/core/modules/user/src/UserStorage.php
    @@ -116,4 +116,16 @@ public function updateLastAccessTimestamp(AccountInterface $account, $timestamp)
    +    $this->resetCache();
    

    @berdir: Do you think this enough? Shouldn't the role cache be deleted too?

penyaskito’s picture

Talked with @Berdir on irc, and for #11.2 we don't need anything else.

Instead of #11.1, let's do user_role_delete() in user.module as suggested in #10.

Anonymous’s picture

addressed #10, and move functionality to user_user_role_delete().
Also wrote a test and attached separate, should fail.

penyaskito’s picture

Status: Needs review » Needs work
Issue tags: -Needs tests

Looks great, let's see what the testbot thinks!

Only minor issues:

  1. +++ b/core/modules/user/src/Entity/Role.php
    @@ -153,5 +153,4 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
    -
    

    We shouldn't remove this space :/

  2. +++ b/core/modules/user/src/Tests/UserRoleDeleteTest.php
    @@ -0,0 +1,77 @@
    +    // Create new role with same role as test role one
    

    "with same name"

  3. +++ b/core/modules/user/src/Tests/UserRoleDeleteTest.php
    @@ -0,0 +1,77 @@
    +    // Check that user still does not have role one.
    

    Remove the "still"

  4. +++ b/core/modules/user/src/Tests/UserRoleDeleteTest.php
    @@ -0,0 +1,77 @@
    +  }
    +}
    

    Needs a blank line before the class end bracket per coding standards.

The last submitted patch, 13: user-role-permission-assignments-2390467-13-test-only.patch, failed testing.

Anonymous’s picture

Status: Needs work » Needs review
FileSize
5.48 KB
6.18 KB

I have corrected these points.

Anonymous’s picture

Fixed interdiff and also added a missing dot.

penyaskito’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community

Looks good to me. Awesome work @iPat!
Filled beta evaluation form.

adamwhite’s picture

Thanks for taking the ball on this @iPat, I've tested on here and it looks great to me.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 99377f9 and pushed to 8.0.x. Thanks!

Thanks for adding the beta evaluation to the issue summary.

I discussed this with @Berdir in IRC - he pointed out that the general problem of entity reference cleanup is more a problem for config entities than content, because there is no risk of accidental re-assignment for them. I think we should open a followup to work on a generic fix.

  • alexpott committed 99377f9 on 8.0.x
    Issue #2390467 by iPat, adamwhite: User role permission assignments are...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

jonathanshaw’s picture

I think we should open a followup to work on a generic fix.

That follow-up now exists: #2723323: [META] Clean up references to deleted entities.