summaryrefslogtreecommitdiffstats
path: root/Acl
diff options
context:
space:
mode:
Diffstat (limited to 'Acl')
-rw-r--r--Acl/Dbal/AclProvider.php30
-rw-r--r--Acl/Dbal/MutableAclProvider.php70
-rw-r--r--Acl/Permission/MaskBuilder.php54
-rw-r--r--Acl/README.md2
-rw-r--r--Acl/Tests/Dbal/MutableAclProviderTest.php30
-rw-r--r--Acl/Tests/Domain/AuditLoggerTest.php4
-rw-r--r--Acl/composer.json2
7 files changed, 150 insertions, 42 deletions
diff --git a/Acl/Dbal/AclProvider.php b/Acl/Dbal/AclProvider.php
index 96b6a4b..5bcaf82 100644
--- a/Acl/Dbal/AclProvider.php
+++ b/Acl/Dbal/AclProvider.php
@@ -176,13 +176,13 @@ class AclProvider implements AclProviderInterface
if ((self::MAX_BATCH_SIZE === count($currentBatch) || ($i + 1) === $c) && count($currentBatch) > 0) {
try {
$loadedBatch = $this->lookupObjectIdentities($currentBatch, $sids, $oidLookup);
- } catch (AclNotFoundException $aclNotFoundexception) {
+ } 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;
+ throw $aclNotFoundException;
}
}
foreach ($loadedBatch as $loadedOid) {
@@ -205,7 +205,8 @@ class AclProvider implements AclProviderInterface
foreach ($oids as $oid) {
if (!$result->contains($oid)) {
if (1 === count($oids)) {
- throw new AclNotFoundException(sprintf('No ACL found for %s.', $oid));
+ $objectName = method_exists($oid, '__toString') ? $oid : get_class($oid);
+ throw new AclNotFoundException(sprintf('No ACL found for %s.', $objectName));
}
$partialResultException = new NotAllAclsFoundException('The provider could not find ACLs for all object identities.');
@@ -294,7 +295,8 @@ SELECTCLAUSE;
if (1 === count($types)) {
$ids = array();
for ($i = 0; $i < $count; $i++) {
- $ids[] = $this->connection->quote($batch[$i]->getIdentifier());
+ $identifier = (string) $batch[$i]->getIdentifier();
+ $ids[] = $this->connection->quote($identifier);
}
$sql .= sprintf(
@@ -336,17 +338,17 @@ SELECTCLAUSE;
$query = <<<FINDCHILDREN
SELECT o.object_identifier, c.class_type
FROM
- {$this->options['oid_table_name']} as o
- INNER JOIN {$this->options['class_table_name']} as c ON c.id = o.class_id
- INNER JOIN {$this->options['oid_ancestors_table_name']} as a ON a.object_identity_id = o.id
+ {$this->options['oid_table_name']} o
+ INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id
+ INNER JOIN {$this->options['oid_ancestors_table_name']} a ON a.object_identity_id = o.id
WHERE
a.ancestor_id = %d AND a.object_identity_id != a.ancestor_id
FINDCHILDREN;
} else {
$query = <<<FINDCHILDREN
SELECT o.object_identifier, c.class_type
- FROM {$this->options['oid_table_name']} as o
- INNER JOIN {$this->options['class_table_name']} as c ON c.id = o.class_id
+ FROM {$this->options['oid_table_name']} o
+ INNER JOIN {$this->options['class_table_name']} c ON c.id = o.class_id
WHERE o.parent_object_identity_id = %d
FINDCHILDREN;
}
@@ -374,8 +376,8 @@ QUERY;
$query,
$this->options['oid_table_name'],
$this->options['class_table_name'],
- $this->connection->quote($oid->getIdentifier()),
- $this->connection->quote($oid->getType())
+ $this->connection->quote((string) $oid->getIdentifier()),
+ $this->connection->quote((string) $oid->getType())
);
}
@@ -430,8 +432,8 @@ QUERY;
$ancestorIds = array();
foreach ($this->connection->executeQuery($sql)->fetchAll() as $data) {
// FIXME: skip ancestors which are cached
-
- $ancestorIds[] = $data['ancestor_id'];
+ // Fix: Oracle returns keys in uppercase
+ $ancestorIds[] = reset($data);
}
return $ancestorIds;
@@ -535,7 +537,7 @@ QUERY;
$auditSuccess,
$auditFailure,
$username,
- $securityIdentifier) = $data;
+ $securityIdentifier) = array_values($data);
// has the ACL been hydrated during this hydration cycle?
if (isset($acls[$aclId])) {
diff --git a/Acl/Dbal/MutableAclProvider.php b/Acl/Dbal/MutableAclProvider.php
index 2a4eac0..261d932 100644
--- a/Acl/Dbal/MutableAclProvider.php
+++ b/Acl/Dbal/MutableAclProvider.php
@@ -51,7 +51,8 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf
public function createAcl(ObjectIdentityInterface $oid)
{
if (false !== $this->retrieveObjectIdentityPrimaryKey($oid)) {
- throw new AclAlreadyExistsException(sprintf('%s is already associated with an ACL.', $oid));
+ $objectName = method_exists($oid, '__toString') ? $oid : get_class($oid);
+ throw new AclAlreadyExistsException(sprintf('%s is already associated with an ACL.', $objectName));
}
$this->connection->beginTransaction();
@@ -109,6 +110,18 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf
}
/**
+ * Deletes the security identity from the database.
+ * ACL entries have the CASCADE option on their foreign key so they will also get deleted
+ *
+ * @param SecurityIdentityInterface $sid
+ * @throws \InvalidArgumentException
+ */
+ public function deleteSecurityIdentity(SecurityIdentityInterface $sid)
+ {
+ $this->connection->executeQuery($this->getDeleteSecurityIdentityIdSql($sid));
+ }
+
+ /**
* {@inheritdoc}
*/
public function findAcls(array $oids, array $sids = array())
@@ -253,7 +266,7 @@ 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
+ // we need to perform deletions before updating existing ACEs, in order to
// preserve uniqueness of the order field
if (isset($propertyChanges['classAces'])) {
$this->updateOldAceProperty('classAces', $propertyChanges['classAces']);
@@ -352,6 +365,17 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf
}
/**
+ * Updates a user security identity when the user's username changes
+ *
+ * @param UserSecurityIdentity $usid
+ * @param string $oldUsername
+ */
+ public function updateUserSecurityIdentity(UserSecurityIdentity $usid, $oldUsername)
+ {
+ $this->connection->executeQuery($this->getUpdateUserSecurityIdentitySql($usid, $oldUsername));
+ }
+
+ /**
* Constructs the SQL for deleting access control entries.
*
* @param int $oidPK
@@ -360,7 +384,7 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf
protected function getDeleteAccessControlEntriesSql($oidPK)
{
return sprintf(
- 'DELETE FROM %s WHERE object_identity_id = %d',
+ 'DELETE FROM %s WHERE object_identity_id = %d',
$this->options['entry_table_name'],
$oidPK
);
@@ -612,6 +636,21 @@ QUERY;
}
/**
+ * Constructs the SQL to delete a security identity.
+ *
+ * @param SecurityIdentityInterface $sid
+ * @throws \InvalidArgumentException
+ * @return string
+ */
+ protected function getDeleteSecurityIdentityIdSql(SecurityIdentityInterface $sid)
+ {
+ $select = $this->getSelectSecurityIdentityIdSql($sid);
+ $delete = preg_replace('/^SELECT id FROM/', 'DELETE FROM', $select);
+
+ return $delete;
+ }
+
+ /**
* Constructs the SQL for updating an object identity.
*
* @param int $pk
@@ -634,6 +673,31 @@ QUERY;
}
/**
+ * Constructs the SQL for updating a user security identity.
+ *
+ * @param UserSecurityIdentity $usid
+ * @param string $oldUsername
+ * @return string
+ */
+ protected function getUpdateUserSecurityIdentitySql(UserSecurityIdentity $usid, $oldUsername)
+ {
+ if ($usid->getUsername() == $oldUsername) {
+ throw new \InvalidArgumentException('There are no changes.');
+ }
+
+ $oldIdentifier = $usid->getClass().'-'.$oldUsername;
+ $newIdentifier = $usid->getClass().'-'.$usid->getUsername();
+
+ return sprintf(
+ 'UPDATE %s SET identifier = %s WHERE identifier = %s AND username = %s',
+ $this->options['sid_table_name'],
+ $this->connection->quote($newIdentifier),
+ $this->connection->quote($oldIdentifier),
+ $this->connection->getDatabasePlatform()->convertBooleans(true)
+ );
+ }
+
+ /**
* Constructs the SQL for updating an ACE.
*
* @param int $pk
diff --git a/Acl/Permission/MaskBuilder.php b/Acl/Permission/MaskBuilder.php
index 8ca25bc..86200a8 100644
--- a/Acl/Permission/MaskBuilder.php
+++ b/Acl/Permission/MaskBuilder.php
@@ -96,13 +96,7 @@ class MaskBuilder
*/
public function add($mask)
{
- if (is_string($mask) && defined($name = 'static::MASK_'.strtoupper($mask))) {
- $mask = constant($name);
- } elseif (!is_int($mask)) {
- throw new \InvalidArgumentException('$mask must be an integer.');
- }
-
- $this->mask |= $mask;
+ $this->mask |= $this->getMask($mask);
return $this;
}
@@ -152,13 +146,7 @@ class MaskBuilder
*/
public function remove($mask)
{
- if (is_string($mask) && defined($name = 'static::MASK_'.strtoupper($mask))) {
- $mask = constant($name);
- } elseif (!is_int($mask)) {
- throw new \InvalidArgumentException('$mask must be an integer.');
- }
-
- $this->mask &= ~$mask;
+ $this->mask &= ~$this->getMask($mask);
return $this;
}
@@ -191,19 +179,43 @@ class MaskBuilder
$reflection = new \ReflectionClass(get_called_class());
foreach ($reflection->getConstants() as $name => $cMask) {
- if (0 !== strpos($name, 'MASK_')) {
+ if (0 !== strpos($name, 'MASK_') || $mask !== $cMask) {
continue;
}
- if ($mask === $cMask) {
- if (!defined($cName = 'static::CODE_'.substr($name, 5))) {
- throw new \RuntimeException('There was no code defined for this mask.');
- }
-
- return constant($cName);
+ if (!defined($cName = 'static::CODE_'.substr($name, 5))) {
+ throw new \RuntimeException('There was no code defined for this mask.');
}
+
+ return constant($cName);
}
throw new \InvalidArgumentException(sprintf('The mask "%d" is not supported.', $mask));
}
+
+ /**
+ * Returns the mask for the passed code
+ *
+ * @param mixed $code
+ *
+ * @return int
+ *
+ * @throws \InvalidArgumentException
+ */
+ private function getMask($code)
+ {
+ if (is_string($code)) {
+ if (!defined($name = sprintf('static::MASK_%s', strtoupper($code)))) {
+ throw new \InvalidArgumentException(sprintf('The code "%s" is not supported', $code));
+ }
+
+ return constant($name);
+ }
+
+ if (!is_int($code)) {
+ throw new \InvalidArgumentException('$code must be an integer.');
+ }
+
+ return $code;
+ }
}
diff --git a/Acl/README.md b/Acl/README.md
index 87e5092..6c009a3 100644
--- a/Acl/README.md
+++ b/Acl/README.md
@@ -11,7 +11,7 @@ Resources
Documentation:
-http://symfony.com/doc/2.4/book/security.html
+http://symfony.com/doc/2.5/book/security.html
Tests
-----
diff --git a/Acl/Tests/Dbal/MutableAclProviderTest.php b/Acl/Tests/Dbal/MutableAclProviderTest.php
index f74e04c..f0a68a0 100644
--- a/Acl/Tests/Dbal/MutableAclProviderTest.php
+++ b/Acl/Tests/Dbal/MutableAclProviderTest.php
@@ -410,6 +410,36 @@ class MutableAclProviderTest extends \PHPUnit_Framework_TestCase
$provider->updateAcl($acl);
}
+ public function testUpdateUserSecurityIdentity()
+ {
+ $provider = $this->getProvider();
+ $acl = $provider->createAcl(new ObjectIdentity(1, 'Foo'));
+ $sid = new UserSecurityIdentity('johannes', 'FooClass');
+ $acl->setEntriesInheriting(!$acl->isEntriesInheriting());
+
+ $acl->insertObjectAce($sid, 1);
+ $acl->insertClassAce($sid, 5, 0, false);
+ $acl->insertObjectAce($sid, 2, 1, true);
+ $acl->insertClassFieldAce('field', $sid, 2, 0, true);
+ $provider->updateAcl($acl);
+
+ $newSid = new UserSecurityIdentity('mathieu', 'FooClass');
+ $provider->updateUserSecurityIdentity($newSid, 'johannes');
+
+ $reloadProvider = $this->getProvider();
+ $reloadedAcl = $reloadProvider->findAcl(new ObjectIdentity(1, 'Foo'));
+
+ $this->assertNotSame($acl, $reloadedAcl);
+ $this->assertSame($acl->isEntriesInheriting(), $reloadedAcl->isEntriesInheriting());
+
+ $aces = $acl->getObjectAces();
+ $reloadedAces = $reloadedAcl->getObjectAces();
+ $this->assertEquals(count($aces), count($reloadedAces));
+ foreach ($reloadedAces as $ace) {
+ $this->assertTrue($ace->getSecurityIdentity()->equals($newSid));
+ }
+ }
+
/**
* Data must have the following format:
* array(
diff --git a/Acl/Tests/Domain/AuditLoggerTest.php b/Acl/Tests/Domain/AuditLoggerTest.php
index 6c600fb..15538d3 100644
--- a/Acl/Tests/Domain/AuditLoggerTest.php
+++ b/Acl/Tests/Domain/AuditLoggerTest.php
@@ -26,12 +26,12 @@ class AuditLoggerTest extends \PHPUnit_Framework_TestCase
->expects($this->once())
->method('isAuditSuccess')
->will($this->returnValue($audit))
- ;
+ ;
$ace
->expects($this->never())
->method('isAuditFailure')
- ;
+ ;
} else {
$ace
->expects($this->never())
diff --git a/Acl/composer.json b/Acl/composer.json
index 0e68d9e..5f5787f 100644
--- a/Acl/composer.json
+++ b/Acl/composer.json
@@ -36,7 +36,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.4-dev"
+ "dev-master": "2.5-dev"
}
}
}