diff options
author | Fabien Potencier <fabien.potencier@gmail.com> | 2013-11-23 22:11:41 +0100 |
---|---|---|
committer | Fabien Potencier <fabien.potencier@gmail.com> | 2013-11-23 22:11:41 +0100 |
commit | 79b21cbc2358461695473de6a5b4e6a92ae18674 (patch) | |
tree | e02b73dd7e69d0f8cf957aef187bec1713b8e4bd | |
parent | 2d03373e16a1f3f7947a0bf980ab76ecca61a310 (diff) | |
parent | 209339c87ca122559536159fbf528156624bda65 (diff) | |
download | symfony-security-79b21cbc2358461695473de6a5b4e6a92ae18674.zip symfony-security-79b21cbc2358461695473de6a5b4e6a92ae18674.tar.gz symfony-security-79b21cbc2358461695473de6a5b4e6a92ae18674.tar.bz2 |
Merge branch '2.2' into 2.3
* 2.2:
No Entity Manager defined exception
fixed CS
[Acl] Fix for issue #9433
[Validator] fix docblock typos
[DependencyInjection] removed the unused Reference and Parameter classes use statements from the compiled container class
Fix mistake in translation's service definition.
if handler_id is identical to null fix
CS fix
Fixed ModelChoiceList tests in Propel1 bridge.
[AclProvider] Fix incorrect behaviour when partial results returned from cache
Check if the pipe array is empty before calling stream_select()
re-factor Propel1 ModelChoiceList
[Locale] fixed the failing test described in #9455
[Process] fix phpdoc and timeout of 0
bug #9445 [BrowserKit] fixed protocol-relative url redirection
Conflicts:
src/Symfony/Component/BrowserKit/Tests/ClientTest.php
src/Symfony/Component/Locale/Tests/Stub/StubIntlDateFormatterTest.php
-rw-r--r-- | Acl/Dbal/AclProvider.php | 13 | ||||
-rw-r--r-- | Acl/Dbal/MutableAclProvider.php | 127 | ||||
-rw-r--r-- | Tests/Acl/Dbal/MutableAclProviderTest.php | 48 |
3 files changed, 158 insertions, 30 deletions
diff --git a/Acl/Dbal/AclProvider.php b/Acl/Dbal/AclProvider.php index 822a160..1d1cb16 100644 --- a/Acl/Dbal/AclProvider.php +++ b/Acl/Dbal/AclProvider.php @@ -165,8 +165,17 @@ class AclProvider implements AclProviderInterface // Is it time to load the current batch? if ((self::MAX_BATCH_SIZE === count($currentBatch) || ($i + 1) === $c) && count($currentBatch) > 0) { - $loadedBatch = $this->lookupObjectIdentities($currentBatch, $sids, $oidLookup); - + try { + $loadedBatch = $this->lookupObjectIdentities($currentBatch, $sids, $oidLookup); + } catch (AclNotFoundException $aclNotFoundexception) { + if ($result->count()) { + $partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.'); + $partialResultException->setPartialResult($result); + throw $partialResultException; + } else { + throw $aclNotFoundexception; + } + } foreach ($loadedBatch as $loadedOid) { $loadedAcl = $loadedBatch->offsetGet($loadedOid); diff --git a/Acl/Dbal/MutableAclProvider.php b/Acl/Dbal/MutableAclProvider.php index 0ac4fa7..29d3cfd 100644 --- a/Acl/Dbal/MutableAclProvider.php +++ b/Acl/Dbal/MutableAclProvider.php @@ -252,6 +252,22 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf } } + // check properties for deleted, and created ACEs, and perform deletions + // we need to perfom deletions before updating existing ACEs, in order to + // preserve uniqueness of the order field + if (isset($propertyChanges['classAces'])) { + $this->updateOldAceProperty('classAces', $propertyChanges['classAces']); + } + if (isset($propertyChanges['classFieldAces'])) { + $this->updateOldFieldAceProperty('classFieldAces', $propertyChanges['classFieldAces']); + } + if (isset($propertyChanges['objectAces'])) { + $this->updateOldAceProperty('objectAces', $propertyChanges['objectAces']); + } + if (isset($propertyChanges['objectFieldAces'])) { + $this->updateOldFieldAceProperty('objectFieldAces', $propertyChanges['objectFieldAces']); + } + // this includes only updates of existing ACEs, but neither the creation, nor // the deletion of ACEs; these are tracked by changes to the ACL's respective // properties (classAces, classFieldAces, objectAces, objectFieldAces) @@ -259,20 +275,20 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf $this->updateAces($propertyChanges['aces']); } - // check properties for deleted, and created ACEs + // check properties for deleted, and created ACEs, and perform creations if (isset($propertyChanges['classAces'])) { - $this->updateAceProperty('classAces', $propertyChanges['classAces']); + $this->updateNewAceProperty('classAces', $propertyChanges['classAces']); $sharedPropertyChanges['classAces'] = $propertyChanges['classAces']; } if (isset($propertyChanges['classFieldAces'])) { - $this->updateFieldAceProperty('classFieldAces', $propertyChanges['classFieldAces']); + $this->updateNewFieldAceProperty('classFieldAces', $propertyChanges['classFieldAces']); $sharedPropertyChanges['classFieldAces'] = $propertyChanges['classFieldAces']; } if (isset($propertyChanges['objectAces'])) { - $this->updateAceProperty('objectAces', $propertyChanges['objectAces']); + $this->updateNewAceProperty('objectAces', $propertyChanges['objectAces']); } if (isset($propertyChanges['objectFieldAces'])) { - $this->updateFieldAceProperty('objectFieldAces', $propertyChanges['objectFieldAces']); + $this->updateNewFieldAceProperty('objectFieldAces', $propertyChanges['objectFieldAces']); } // if there have been changes to shared properties, we need to synchronize other @@ -740,12 +756,12 @@ QUERY; } /** - * This processes changes on an ACE related property (classFieldAces, or objectFieldAces). + * This processes new entries changes on an ACE related property (classFieldAces, or objectFieldAces). * * @param string $name * @param array $changes */ - private function updateFieldAceProperty($name, array $changes) + private function updateNewFieldAceProperty($name, array $changes) { $sids = new \SplObjectStorage(); $classIds = new \SplObjectStorage(); @@ -782,9 +798,29 @@ QUERY; } } } + } + + /** + * This process old entries changes on an ACE related property (classFieldAces, or objectFieldAces). + * + * @param string $name + * @param array $changes + */ + private function updateOldFieldAceProperty($ane, array $changes) + { + $currentIds = array(); + foreach ($changes[1] as $field => $new) { + for ($i = 0, $c = count($new); $i < $c; $i++) { + $ace = $new[$i]; + + if (null !== $ace->getId()) { + $currentIds[$ace->getId()] = true; + } + } + } foreach ($changes[0] as $old) { - for ($i=0,$c=count($old); $i<$c; $i++) { + for ($i = 0, $c = count($old); $i < $c; $i++) { $ace = $old[$i]; if (!isset($currentIds[$ace->getId()])) { @@ -796,12 +832,12 @@ QUERY; } /** - * This processes changes on an ACE related property (classAces, or objectAces). + * This processes new entries changes on an ACE related property (classAces, or objectAces). * * @param string $name * @param array $changes */ - private function updateAceProperty($name, array $changes) + private function updateNewAceProperty($name, array $changes) { list($old, $new) = $changes; @@ -838,8 +874,28 @@ QUERY; $currentIds[$ace->getId()] = true; } } + } - for ($i=0,$c=count($old); $i<$c; $i++) { + /** + * This processes old entries changes on an ACE related property (classAces, or objectAces). + * + * @param string $name + * @param array $changes + */ + private function updateOldAceProperty($name, array $changes) + { + list($old, $new) = $changes; + $currentIds = array(); + + for ($i=0,$c=count($new); $i<$c; $i++) { + $ace = $new[$i]; + + if (null !== $ace->getId()) { + $currentIds[$ace->getId()] = true; + } + } + + for ($i = 0, $c = count($old); $i < $c; $i++) { $ace = $old[$i]; if (!isset($currentIds[$ace->getId()])) { @@ -857,26 +913,41 @@ QUERY; private function updateAces(\SplObjectStorage $aces) { foreach ($aces as $ace) { - $propertyChanges = $aces->offsetGet($ace); - $sets = array(); + $this->updateAce($aces, $ace); + } + } - if (isset($propertyChanges['mask'])) { - $sets[] = sprintf('mask = %d', $propertyChanges['mask'][1]); - } - if (isset($propertyChanges['strategy'])) { - $sets[] = sprintf('granting_strategy = %s', $this->connection->quote($propertyChanges['strategy'])); - } - if (isset($propertyChanges['aceOrder'])) { - $sets[] = sprintf('ace_order = %d', $propertyChanges['aceOrder'][1]); - } - if (isset($propertyChanges['auditSuccess'])) { - $sets[] = sprintf('audit_success = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditSuccess'][1])); - } - if (isset($propertyChanges['auditFailure'])) { - $sets[] = sprintf('audit_failure = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditFailure'][1])); + private function updateAce(\SplObjectStorage $aces, $ace) + { + $propertyChanges = $aces->offsetGet($ace); + $sets = array(); + + if (isset($propertyChanges['aceOrder']) + && $propertyChanges['aceOrder'][1] > $propertyChanges['aceOrder'][0] + && $propertyChanges == $aces->offsetGet($ace)) { + $aces->next(); + if ($aces->valid()) { + $this->updateAce($aces, $aces->current()); + } } - $this->connection->executeQuery($this->getUpdateAccessControlEntrySql($ace->getId(), $sets)); + if (isset($propertyChanges['mask'])) { + $sets[] = sprintf('mask = %d', $propertyChanges['mask'][1]); } + if (isset($propertyChanges['strategy'])) { + $sets[] = sprintf('granting_strategy = %s', $this->connection->quote($propertyChanges['strategy'])); + } + if (isset($propertyChanges['aceOrder'])) { + $sets[] = sprintf('ace_order = %d', $propertyChanges['aceOrder'][1]); + } + if (isset($propertyChanges['auditSuccess'])) { + $sets[] = sprintf('audit_success = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditSuccess'][1])); + } + if (isset($propertyChanges['auditFailure'])) { + $sets[] = sprintf('audit_failure = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditFailure'][1])); + } + + $this->connection->executeQuery($this->getUpdateAccessControlEntrySql($ace->getId(), $sets)); } + } diff --git a/Tests/Acl/Dbal/MutableAclProviderTest.php b/Tests/Acl/Dbal/MutableAclProviderTest.php index edcdd4d..00a2228 100644 --- a/Tests/Acl/Dbal/MutableAclProviderTest.php +++ b/Tests/Acl/Dbal/MutableAclProviderTest.php @@ -359,6 +359,54 @@ class MutableAclProviderTest extends \PHPUnit_Framework_TestCase $this->assertEquals($newParentParentAcl->getId(), $reloadedAcl->getParentAcl()->getParentAcl()->getId()); } + public function testUpdateAclInsertingMultipleObjectFieldAcesThrowsDBConstraintViolations() + { + $provider = $this->getProvider(); + $oid = new ObjectIdentity(1, 'Foo'); + $sid1 = new UserSecurityIdentity('johannes', 'FooClass'); + $sid2 = new UserSecurityIdentity('guilro', 'FooClass'); + $sid3 = new UserSecurityIdentity('bmaz', 'FooClass'); + $fieldName = 'fieldName'; + + $acl = $provider->createAcl($oid); + $acl->insertObjectFieldAce($fieldName, $sid1, 4); + $provider->updateAcl($acl); + + $acl = $provider->findAcl($oid); + $acl->insertObjectFieldAce($fieldName, $sid2, 4); + $provider->updateAcl($acl); + + $acl = $provider->findAcl($oid); + $acl->insertObjectFieldAce($fieldName, $sid3, 4); + $provider->updateAcl($acl); + } + + public function testUpdateAclDeletingObjectFieldAcesThrowsDBConstraintViolations() + { + $provider = $this->getProvider(); + $oid = new ObjectIdentity(1, 'Foo'); + $sid1 = new UserSecurityIdentity('johannes', 'FooClass'); + $sid2 = new UserSecurityIdentity('guilro', 'FooClass'); + $sid3 = new UserSecurityIdentity('bmaz', 'FooClass'); + $fieldName = 'fieldName'; + + $acl = $provider->createAcl($oid); + $acl->insertObjectFieldAce($fieldName, $sid1, 4); + $provider->updateAcl($acl); + + $acl = $provider->findAcl($oid); + $acl->insertObjectFieldAce($fieldName, $sid2, 4); + $provider->updateAcl($acl); + + $index = 0; + $acl->deleteObjectFieldAce($index, $fieldName); + $provider->updateAcl($acl); + + $acl = $provider->findAcl($oid); + $acl->insertObjectFieldAce($fieldName, $sid3, 4); + $provider->updateAcl($acl); + } + /** * Data must have the following format: * array( |