Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8d39213

Browse filesBrowse files
committed
feature #8650 [Security][Acl] Add MutableAclProvider::updateUserSecurityIdentity (lemoinem)
This PR was merged into the 2.5-dev branch. Discussion ---------- [Security][Acl] Add MutableAclProvider::updateUserSecurityIdentity | Q | A | ------------- | --- | Bug fix? | yes | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #5787 | License | MIT | Doc PR | symfony/symfony-docs#3319 This provides a very simple function to enable the update of a User's username while keeping its associated ACEs (by updating its corresponding UserSecurityIdentity) Developers can add a listener on the preUpdate of a user and remove all the related ACLs: ```php if ($args->hasChangedField('username')) { $aclProvider = $this->container->get('security.acl.provider'); $oldUsername = $args->getOldValue ('username'); $user = $args->getEntity(); $aclProvider->updateUserSecurityIdentity(UserSecurityIdentity::fromAccount($user) , $oldUsername); } ``` Among the problems of not updating the UserSecurityIdentity: - Inconsistent database, referring to a non-existent user. - The user loses all its associated permissions - If another user is created with the old username, it will inherit all the first user’s ACEs This PR intends to fix Issue #5787 and is similar to and inspired from PR #8305. This will also be heavily impacted by the outcome of #8848 Commits ------- da53d92 [Security][Acl] Fix #5787 : Add MutableAclProvider::updateUserSecurityIdentity
2 parents 2b7af12 + da53d92 commit 8d39213
Copy full SHA for 8d39213

File tree

Expand file treeCollapse file tree

2 files changed

+66
-0
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+66
-0
lines changed

‎src/Symfony/Component/Security/Acl/Dbal/MutableAclProvider.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Acl/Dbal/MutableAclProvider.php
+36Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,17 @@ public function updateAcl(MutableAclInterface $acl)
351351
}
352352
}
353353

354+
/**
355+
* Updates a user security identity when the user's username changes
356+
*
357+
* @param UserSecurityIdentity $usid
358+
* @param string $oldUsername
359+
*/
360+
public function updateUserSecurityIdentity(UserSecurityIdentity $usid, $oldUsername)
361+
{
362+
$this->connection->executeQuery($this->getUpdateUserSecurityIdentitySql($usid, $oldUsername));
363+
}
364+
354365
/**
355366
* Constructs the SQL for deleting access control entries.
356367
*
@@ -633,6 +644,31 @@ protected function getUpdateObjectIdentitySql($pk, array $changes)
633644
);
634645
}
635646

647+
/**
648+
* Constructs the SQL for updating a user security identity.
649+
*
650+
* @param UserSecurityIdentity $usid
651+
* @param string $oldUsername
652+
* @return string
653+
*/
654+
protected function getUpdateUserSecurityIdentitySql(UserSecurityIdentity $usid, $oldUsername)
655+
{
656+
if ($usid->getUsername() == $oldUsername) {
657+
throw new \InvalidArgumentException('There are no changes.');
658+
}
659+
660+
$oldIdentifier = $usid->getClass().'-'.$oldUsername;
661+
$newIdentifier = $usid->getClass().'-'.$usid->getUsername();
662+
663+
return sprintf(
664+
'UPDATE %s SET identifier = %s WHERE identifier = %s AND username = %s',
665+
$this->options['sid_table_name'],
666+
$this->connection->quote($newIdentifier),
667+
$this->connection->quote($oldIdentifier),
668+
$this->connection->getDatabasePlatform()->convertBooleans(true)
669+
);
670+
}
671+
636672
/**
637673
* Constructs the SQL for updating an ACE.
638674
*

‎src/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Acl/Tests/Dbal/MutableAclProviderTest.php
+30Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,36 @@ public function testUpdateAclDeletingObjectFieldAcesThrowsDBConstraintViolations
407407
$provider->updateAcl($acl);
408408
}
409409

410+
public function testUpdateUserSecurityIdentity()
411+
{
412+
$provider = $this->getProvider();
413+
$acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
414+
$sid = new UserSecurityIdentity('johannes', 'FooClass');
415+
$acl->setEntriesInheriting(!$acl->isEntriesInheriting());
416+
417+
$acl->insertObjectAce($sid, 1);
418+
$acl->insertClassAce($sid, 5, 0, false);
419+
$acl->insertObjectAce($sid, 2, 1, true);
420+
$acl->insertClassFieldAce('field', $sid, 2, 0, true);
421+
$provider->updateAcl($acl);
422+
423+
$newSid = new UserSecurityIdentity('mathieu', 'FooClass');
424+
$provider->updateUserSecurityIdentity($newSid, 'johannes');
425+
426+
$reloadProvider = $this->getProvider();
427+
$reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo'));
428+
429+
$this->assertNotSame($acl, $reloadedAcl);
430+
$this->assertSame($acl->isEntriesInheriting(), $reloadedAcl->isEntriesInheriting());
431+
432+
$aces = $acl->getObjectAces();
433+
$reloadedAces = $reloadedAcl->getObjectAces();
434+
$this->assertEquals(count($aces), count($reloadedAces));
435+
foreach ($reloadedAces as $ace) {
436+
$this->assertTrue($ace->getSecurityIdentity()->equals($newSid));
437+
}
438+
}
439+
410440
/**
411441
* Data must have the following format:
412442
* array(

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.