Browse Source

[Security/Acl] small voter refactoring

Johannes Schmitt 14 years ago
parent
commit
53f5c23c8f

+ 1 - 1
src/Symfony/Component/Security/Acl/Permission/BasicPermissionMap.php

@@ -84,7 +84,7 @@ class BasicPermissionMap implements PermissionMapInterface
     /**
      * {@inheritDoc}
      */
-    public function getMasks($permission)
+    public function getMasks($permission, $object)
     {
         if (!isset($this->map[$permission])) {
             throw new \InvalidArgumentException(sprintf('The permission "%s" is not supported by this implementation.', $permission));

+ 3 - 2
src/Symfony/Component/Security/Acl/Permission/PermissionMapInterface.php

@@ -25,9 +25,10 @@ interface PermissionMapInterface
      * these bitmasks.
      *
      * @param string $permission
-     * @return array
+     * @param object $object
+     * @return array may return null if permission/object combination is not supported
      */
-    function getMasks($permission);
+    function getMasks($permission, $object);
 
     /**
      * Whether this map contains the given permission

+ 28 - 35
src/Symfony/Component/Security/Acl/Voter/AclVoter.php

@@ -57,58 +57,45 @@ class AclVoter implements VoterInterface
 
     public function vote(TokenInterface $token, $object, array $attributes)
     {
-        $firstCall = true;
         foreach ($attributes as $attribute) {
-            if (!$this->supportsAttribute($attribute)) {
+            if (null === $masks = $this->permissionMap->getMasks($attribute, $object)) {
                 continue;
             }
 
-            if ($firstCall) {
-                $firstCall = false;
-
-                if (null === $object) {
-                    if (null !== $this->logger) {
-                        $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain'));
-                    }
-
-                    return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
-                } else if ($object instanceof FieldVote) {
-                    $field = $object->getField();
-                    $object = $object->getDomainObject();
-                } else {
-                    $field = null;
+            if (null === $object) {
+                if (null !== $this->logger) {
+                    $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain'));
                 }
 
-                if ($object instanceof ObjectIdentityInterface) {
-                    $oid = $object;
-                } else if (null === $oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($object)) {
-                    if (null !== $this->logger) {
-                        $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain'));
-                    }
+                return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
+            } else if ($object instanceof FieldVote) {
+                $field = $object->getField();
+                $object = $object->getDomainObject();
+            } else {
+                $field = null;
+            }
 
-                    return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
+            if ($object instanceof ObjectIdentityInterface) {
+                $oid = $object;
+            } else if (null === $oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($object)) {
+                if (null !== $this->logger) {
+                    $this->logger->debug(sprintf('Object identity unavailable. Voting to %s', $this->allowIfObjectIdentityUnavailable? 'grant access' : 'abstain'));
                 }
-                $sids = $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token);
 
-                try {
-                    $acl = $this->aclProvider->findAcl($oid, $sids);
-                } catch (AclNotFoundException $noAcl) {
-                    if (null !== $this->logger) {
-                        $this->logger->debug('No ACL found for the object identity. Voting to deny access.');
-                    }
-
-                    return self::ACCESS_DENIED;
-                }
+                return $this->allowIfObjectIdentityUnavailable ? self::ACCESS_GRANTED : self::ACCESS_ABSTAIN;
             }
+            $sids = $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token);
 
             try {
-                if (null === $field && $acl->isGranted($this->permissionMap->getMasks($attribute), $sids, false)) {
+                $acl = $this->aclProvider->findAcl($oid, $sids);
+
+                if (null === $field && $acl->isGranted($masks, $sids, false)) {
                     if (null !== $this->logger) {
                         $this->logger->debug('ACL found, permission granted. Voting to grant access');
                     }
 
                     return self::ACCESS_GRANTED;
-                } else if (null !== $field && $acl->isFieldGranted($field, $this->permissionMap->getMasks($attribute), $sids, false)) {
+                } else if (null !== $field && $acl->isFieldGranted($field, $masks, $sids, false)) {
                     if (null !== $this->logger) {
                         $this->logger->debug('ACL found, permission granted. Voting to grant access');
                     }
@@ -120,6 +107,12 @@ class AclVoter implements VoterInterface
                     $this->logger->debug('ACL found, insufficient permissions. Voting to deny access.');
                 }
 
+                return self::ACCESS_DENIED;
+            } catch (AclNotFoundException $noAcl) {
+                if (null !== $this->logger) {
+                    $this->logger->debug('No ACL found for the object identity. Voting to deny access.');
+                }
+
                 return self::ACCESS_DENIED;
             } catch (NoAceFoundException $noAce) {
                 if (null !== $this->logger) {

+ 8 - 33
tests/Symfony/Tests/Component/Security/Acl/Voter/AclVoterTest.php

@@ -71,8 +71,8 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
         list($voter,, $permissionMap,,) = $this->getVoter();
         $permissionMap
             ->expects($this->atLeastOnce())
-            ->method('contains')
-            ->will($this->returnValue(false))
+            ->method('getMasks')
+            ->will($this->returnValue(null))
         ;
 
         $this->assertSame(VoterInterface::ACCESS_ABSTAIN, $voter->vote($this->getToken(), null, array('VIEW', 'EDIT', 'DELETE')));
@@ -86,8 +86,8 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
         list($voter,, $permissionMap,,) = $this->getVoter($allowIfObjectIdentityUnavailable);
         $permissionMap
             ->expects($this->once())
-            ->method('contains')
-            ->will($this->returnValue(true))
+            ->method('getMasks')
+            ->will($this->returnValue(array()))
         ;
 
         if ($allowIfObjectIdentityUnavailable) {
@@ -107,8 +107,8 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
         list($voter,, $permissionMap, $oidStrategy,) = $this->getVoter($allowIfUnavailable);
         $permissionMap
             ->expects($this->once())
-            ->method('contains')
-            ->will($this->returnValue(true))
+            ->method('getMasks')
+            ->will($this->returnValue(array()))
         ;
 
         $oidStrategy
@@ -137,8 +137,8 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
 
         $permissionMap
             ->expects($this->once())
-            ->method('contains')
-            ->will($this->returnValue(true))
+            ->method('getMasks')
+            ->will($this->returnValue(array()))
         ;
 
         $oidStrategy
@@ -170,11 +170,6 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
     {
         list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
 
-        $permissionMap
-            ->expects($this->once())
-            ->method('contains')
-            ->will($this->returnValue(true))
-        ;
         $permissionMap
             ->expects($this->once())
             ->method('getMasks')
@@ -221,11 +216,6 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
     {
         list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
 
-        $permissionMap
-            ->expects($this->once())
-            ->method('contains')
-            ->will($this->returnValue(true))
-        ;
         $permissionMap
             ->expects($this->once())
             ->method('getMasks')
@@ -269,11 +259,6 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
     {
         list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
 
-        $permissionMap
-            ->expects($this->once())
-            ->method('contains')
-            ->will($this->returnValue(true))
-        ;
         $permissionMap
             ->expects($this->once())
             ->method('getMasks')
@@ -320,11 +305,6 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
     {
         list($voter, $provider, $permissionMap, $oidStrategy, $sidStrategy) = $this->getVoter();
 
-        $permissionMap
-            ->expects($this->once())
-            ->method('contains')
-            ->will($this->returnValue(true))
-        ;
         $permissionMap
             ->expects($this->once())
             ->method('getMasks')
@@ -367,11 +347,6 @@ class AclVoterTest extends \PHPUnit_Framework_TestCase
 
         $oid = new ObjectIdentity('someID','someType');
 
-        $permissionMap
-            ->expects($this->once())
-            ->method('contains')
-            ->will($this->returnValue(true))
-        ;
         $permissionMap
             ->expects($this->once())
             ->method('getMasks')