diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
index a1e93d975e035..7cdde385cdc3f 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
@@ -62,13 +62,13 @@ public function load(array $configs, ContainerBuilder $container)
// set some global scalars
$container->setParameter('security.access.denied_url', $config['access_denied_url']);
+ $container->setParameter('security.access.allow_if_all_abstain', $config['access_decision_manager']['allow_if_all_abstain']);
+ $container->setParameter('security.access.allow_if_equal_granted_denied', $config['access_decision_manager']['allow_if_equal_granted_denied']);
+
+ $strategy = sprintf('security.access.%s_access_strategy', $config['access_decision_manager']['strategy']);
+ $container->setAlias('security.access.strategy', $strategy);
+
$container->getDefinition('security.authentication.session_strategy')->replaceArgument(0, $config['session_fixation_strategy']);
- $container
- ->getDefinition('security.access.decision_manager')
- ->addArgument($config['access_decision_manager']['strategy'])
- ->addArgument($config['access_decision_manager']['allow_if_all_abstain'])
- ->addArgument($config['access_decision_manager']['allow_if_equal_granted_denied'])
- ;
$container->setParameter('security.access.always_authenticate_before_granting', $config['always_authenticate_before_granting']);
$this->createFirewalls($config, $container);
@@ -86,6 +86,9 @@ public function load(array $configs, ContainerBuilder $container)
// add some required classes for compilation
$this->addClassesToCompile(array(
+ 'Symfony\\Component\\HttpFoundation\\RequestMatcher',
+ 'Symfony\\Component\\HttpFoundation\\RequestMatcherInterface',
+
'Symfony\\Component\\Security\\Http\\Firewall',
'Symfony\\Component\\Security\\Http\\FirewallMapInterface',
'Symfony\\Component\\Security\\Core\\SecurityContext',
@@ -95,13 +98,14 @@ public function load(array $configs, ContainerBuilder $container)
'Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationManagerInterface',
'Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager',
'Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManagerInterface',
+ 'Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AccessStrategy',
+ 'Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AccessStrategyInterface',
+ 'Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\AffirmativeAccessStrategy',
+ 'Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\ConsensusAccessStrategy',
+ 'Symfony\\Component\\Security\\Core\\Authorization\\Strategy\\UnanimousAccessStrategy',
'Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface',
-
'Symfony\\Bundle\\SecurityBundle\\Security\\FirewallMap',
'Symfony\\Bundle\\SecurityBundle\\Security\\FirewallContext',
-
- 'Symfony\\Component\\HttpFoundation\\RequestMatcher',
- 'Symfony\\Component\\HttpFoundation\\RequestMatcherInterface',
));
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
index 276a68880c142..752716406a2d9 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
@@ -28,6 +28,12 @@
Symfony\Component\Security\Core\Authorization\AccessDecisionManager
+ Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeAccessStrategy
+ Symfony\Component\Security\Core\Authorization\Strategy\ConsensusAccessStrategy
+ Symfony\Component\Security\Core\Authorization\Strategy\UnanimousAccessStrategy
+ false
+ true
+
Symfony\Component\Security\Core\Authorization\Voter\RoleVoter
Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter
Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter
@@ -66,13 +72,31 @@
-
+
+
+
+
+
+
+
+
+ %security.access.allow_if_all_abstain%
+
+
+
+
+ %security.access.allow_if_all_abstain%
+ %security.access.allow_if_equal_granted_denied%
+
+
+
+ %security.access.allow_if_all_abstain%
diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php
index a8bb5cfec750f..b26f159c58364 100644
--- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php
+++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\Security\Core\Authorization;
+use Symfony\Component\Security\Core\Authorization\Strategy\AccessStrategyInterface;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
@@ -22,29 +23,16 @@
*/
class AccessDecisionManager implements AccessDecisionManagerInterface
{
- private $voters;
private $strategy;
- private $allowIfAllAbstainDecisions;
- private $allowIfEqualGrantedDeniedDecisions;
/**
* Constructor.
*
- * @param VoterInterface[] $voters An array of VoterInterface instances
- * @param string $strategy The vote strategy
- * @param Boolean $allowIfAllAbstainDecisions Whether to grant access if all voters abstained or not
- * @param Boolean $allowIfEqualGrantedDeniedDecisions Whether to grant access if result are equals
+ * @param AccessStrategyInterface $strategy The access decision strategy
*/
- public function __construct(array $voters, $strategy = 'affirmative', $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true)
+ public function __construct(AccessStrategyInterface $strategy)
{
- if (!$voters) {
- throw new \InvalidArgumentException('You must at least add one voter.');
- }
-
- $this->voters = $voters;
- $this->strategy = 'decide'.ucfirst($strategy);
- $this->allowIfAllAbstainDecisions = (Boolean) $allowIfAllAbstainDecisions;
- $this->allowIfEqualGrantedDeniedDecisions = (Boolean) $allowIfEqualGrantedDeniedDecisions;
+ $this->strategy = $strategy;
}
/**
@@ -52,7 +40,7 @@ public function __construct(array $voters, $strategy = 'affirmative', $allowIfAl
*/
public function decide(TokenInterface $token, array $attributes, $object = null)
{
- return $this->{$this->strategy}($token, $attributes, $object);
+ return $this->strategy->decide($token, $attributes, $object);
}
/**
@@ -60,7 +48,7 @@ public function decide(TokenInterface $token, array $attributes, $object = null)
*/
public function supportsAttribute($attribute)
{
- foreach ($this->voters as $voter) {
+ foreach ($this->strategy->getVoters() as $voter) {
if ($voter->supportsAttribute($attribute)) {
return true;
}
@@ -74,7 +62,7 @@ public function supportsAttribute($attribute)
*/
public function supportsClass($class)
{
- foreach ($this->voters as $voter) {
+ foreach ($this->strategy->getVoters() as $voter) {
if ($voter->supportsClass($class)) {
return true;
}
@@ -82,127 +70,4 @@ public function supportsClass($class)
return false;
}
-
- /**
- * Grants access if any voter returns an affirmative response.
- *
- * If all voters abstained from voting, the decision will be based on the
- * allowIfAllAbstainDecisions property value (defaults to false).
- */
- private function decideAffirmative(TokenInterface $token, array $attributes, $object = null)
- {
- $deny = 0;
- foreach ($this->voters as $voter) {
- $result = $voter->vote($token, $object, $attributes);
- switch ($result) {
- case VoterInterface::ACCESS_GRANTED:
- return true;
-
- case VoterInterface::ACCESS_DENIED:
- ++$deny;
-
- break;
-
- default:
- break;
- }
- }
-
- if ($deny > 0) {
- return false;
- }
-
- return $this->allowIfAllAbstainDecisions;
- }
-
- /**
- * Grants access if there is consensus of granted against denied responses.
- *
- * Consensus means majority-rule (ignoring abstains) rather than unanimous
- * agreement (ignoring abstains). If you require unanimity, see
- * UnanimousBased.
- *
- * If there were an equal number of grant and deny votes, the decision will
- * be based on the allowIfEqualGrantedDeniedDecisions property value
- * (defaults to true).
- *
- * If all voters abstained from voting, the decision will be based on the
- * allowIfAllAbstainDecisions property value (defaults to false).
- */
- private function decideConsensus(TokenInterface $token, array $attributes, $object = null)
- {
- $grant = 0;
- $deny = 0;
- $abstain = 0;
- foreach ($this->voters as $voter) {
- $result = $voter->vote($token, $object, $attributes);
-
- switch ($result) {
- case VoterInterface::ACCESS_GRANTED:
- ++$grant;
-
- break;
-
- case VoterInterface::ACCESS_DENIED:
- ++$deny;
-
- break;
-
- default:
- ++$abstain;
-
- break;
- }
- }
-
- if ($grant > $deny) {
- return true;
- }
-
- if ($deny > $grant) {
- return false;
- }
-
- if ($grant == $deny && $grant != 0) {
- return $this->allowIfEqualGrantedDeniedDecisions;
- }
-
- return $this->allowIfAllAbstainDecisions;
- }
-
- /**
- * Grants access if only grant (or abstain) votes were received.
- *
- * If all voters abstained from voting, the decision will be based on the
- * allowIfAllAbstainDecisions property value (defaults to false).
- */
- private function decideUnanimous(TokenInterface $token, array $attributes, $object = null)
- {
- $grant = 0;
- foreach ($attributes as $attribute) {
- foreach ($this->voters as $voter) {
- $result = $voter->vote($token, $object, array($attribute));
-
- switch ($result) {
- case VoterInterface::ACCESS_GRANTED:
- ++$grant;
-
- break;
-
- case VoterInterface::ACCESS_DENIED:
- return false;
-
- default:
- break;
- }
- }
- }
-
- // no deny votes
- if ($grant > 0) {
- return true;
- }
-
- return $this->allowIfAllAbstainDecisions;
- }
}
diff --git a/src/Symfony/Component/Security/Core/Authorization/Strategy/AccessStrategy.php b/src/Symfony/Component/Security/Core/Authorization/Strategy/AccessStrategy.php
new file mode 100644
index 0000000000000..50081e4aca56c
--- /dev/null
+++ b/src/Symfony/Component/Security/Core/Authorization/Strategy/AccessStrategy.php
@@ -0,0 +1,51 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Core\Authorization\Strategy;
+
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+
+/**
+ * AccessStrategy is the base class for all access strategy classes.
+ *
+ * @author Fabien Potencier
+ * @author Hugo Hamon
+ */
+abstract class AccessStrategy implements AccessStrategyInterface
+{
+ protected $voters;
+ protected $allowIfAllAbstainDecisions;
+
+ /**
+ * Constructor.
+ *
+ * @param VoterInterface[] An array of VoterInterface objects.
+ * @param Boolean $allowIfAllAbstainDecisions Allow access if all voters abstain decisions.
+ */
+ public function __construct(array $voters, $allowIfAllAbstainDecisions = false)
+ {
+ if (!$voters) {
+ throw new \InvalidArgumentException('You must at least add one voter.');
+ }
+
+ $this->voters = $voters;
+ $this->allowIfAllAbstainDecisions = $allowIfAllAbstainDecisions;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getVoters()
+ {
+ return $this->voters;
+ }
+}
\ No newline at end of file
diff --git a/src/Symfony/Component/Security/Core/Authorization/Strategy/AccessStrategyInterface.php b/src/Symfony/Component/Security/Core/Authorization/Strategy/AccessStrategyInterface.php
new file mode 100644
index 0000000000000..e482ca63cdf44
--- /dev/null
+++ b/src/Symfony/Component/Security/Core/Authorization/Strategy/AccessStrategyInterface.php
@@ -0,0 +1,39 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Core\Authorization\Strategy;
+
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+
+/**
+ * AccessStrategyInterface is the base interface to define behaviors for access
+ * decision strategies. Access decision strategies are used by the
+ * AccessDecisionManager service.
+ *
+ * @author Fabien Potencier
+ * @author Hugo Hamon
+ */
+interface AccessStrategyInterface
+{
+ /**
+ * Returns an array of VoterInterface objects.
+ *
+ * @return VoterInterface[] An array of VoterInterface objects.
+ */
+ public function getVoters();
+
+ /**
+ * Decides which access must be applied for a given TokenInterface object.
+ *
+ * @return int One of the constant of the VoterInterface interface.
+ */
+ public function decide(TokenInterface $token, array $attributes, $object = null);
+}
\ No newline at end of file
diff --git a/src/Symfony/Component/Security/Core/Authorization/Strategy/AffirmativeAccessStrategy.php b/src/Symfony/Component/Security/Core/Authorization/Strategy/AffirmativeAccessStrategy.php
new file mode 100644
index 0000000000000..30435b060a86a
--- /dev/null
+++ b/src/Symfony/Component/Security/Core/Authorization/Strategy/AffirmativeAccessStrategy.php
@@ -0,0 +1,57 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Core\Authorization\Strategy;
+
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+
+/**
+ * AffirmativeAccessStrategy grants access if any voter returns an affirmative
+ * response.
+ *
+ * If all voters abstained from voting, the decision will be based on the
+ * allowIfAllAbstainDecisions property value (defaults to false).
+ *
+ * @author Fabien Potencier
+ * @author Hugo Hamon
+ */
+class AffirmativeAccessStrategy extends AccessStrategy implements AccessStrategyInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function decide(TokenInterface $token, array $attributes, $object = null)
+ {
+ $deny = 0;
+ foreach ($this->voters as $voter) {
+ $result = $voter->vote($token, $object, $attributes);
+ switch ($result) {
+ case VoterInterface::ACCESS_GRANTED:
+ return true;
+
+ case VoterInterface::ACCESS_DENIED:
+ ++$deny;
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ($deny > 0) {
+ return false;
+ }
+
+ return $this->allowIfAllAbstainDecisions;
+ }
+}
\ No newline at end of file
diff --git a/src/Symfony/Component/Security/Core/Authorization/Strategy/ConsensusAccessStrategy.php b/src/Symfony/Component/Security/Core/Authorization/Strategy/ConsensusAccessStrategy.php
new file mode 100644
index 0000000000000..6086de290c698
--- /dev/null
+++ b/src/Symfony/Component/Security/Core/Authorization/Strategy/ConsensusAccessStrategy.php
@@ -0,0 +1,96 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Core\Authorization\Strategy;
+
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+
+/**
+ * ConsensusAccessStrategy grants access if there is consensus of granted
+ * against denied responses.
+ *
+ * Consensus means majority-rule (ignoring abstains) rather than unanimous
+ * agreement (ignoring abstains). If you require unanimity, see
+ * UnanimousBased.
+ *
+ * If there were an equal number of grant and deny votes, the decision will
+ * be based on the allowIfEqualGrantedDeniedDecisions property value
+ * (defaults to true).
+ *
+ * If all voters abstained from voting, the decision will be based on the
+ * allowIfAllAbstainDecisions property value (defaults to false).
+ *
+ * @author Fabien Potencier
+ * @author Hugo Hamon
+ */
+class ConsensusAccessStrategy extends AccessStrategy implements AccessStrategyInterface
+{
+ private $allowIfEqualGrantedDeniedDecisions;
+
+ /**
+ * Constructor.
+ *
+ * @param VoterInterface[] An array of VoterInterface objects.
+ * @param Boolean $allowIfAllAbstainDecisions Allow access if all voters abstain decisions.
+ * @param Boolean $allowIfEqualGrantedDeniedDecisions Allow access if denied decisions equals granted decisions.
+ */
+ public function __construct(array $voters, $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true)
+ {
+ parent::__construct($voters, $allowIfAllAbstainDecisions);
+
+ $this->allowIfEqualGrantedDeniedDecisions = (Boolean) $allowIfEqualGrantedDeniedDecisions;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function decide(TokenInterface $token, array $attributes, $object = null)
+ {
+ $grant = 0;
+ $deny = 0;
+ $abstain = 0;
+ foreach ($this->voters as $voter) {
+ $result = $voter->vote($token, $object, $attributes);
+
+ switch ($result) {
+ case VoterInterface::ACCESS_GRANTED:
+ ++$grant;
+
+ break;
+
+ case VoterInterface::ACCESS_DENIED:
+ ++$deny;
+
+ break;
+
+ default:
+ ++$abstain;
+
+ break;
+ }
+ }
+
+ if ($grant > $deny) {
+ return true;
+ }
+
+ if ($deny > $grant) {
+ return false;
+ }
+
+ if ($grant == $deny && $grant != 0) {
+ return $this->allowIfEqualGrantedDeniedDecisions;
+ }
+
+ return $this->allowIfAllAbstainDecisions;
+ }
+}
\ No newline at end of file
diff --git a/src/Symfony/Component/Security/Core/Authorization/Strategy/UnanimousAccessStrategy.php b/src/Symfony/Component/Security/Core/Authorization/Strategy/UnanimousAccessStrategy.php
new file mode 100644
index 0000000000000..8457e85987561
--- /dev/null
+++ b/src/Symfony/Component/Security/Core/Authorization/Strategy/UnanimousAccessStrategy.php
@@ -0,0 +1,61 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Security\Core\Authorization\Strategy;
+
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+
+/**
+ * UnanimousAccessStrategy Grants access if only grant (or abstain) votes were
+ * received.
+ *
+ * If all voters abstained from voting, the decision will be based on the
+ * allowIfAllAbstainDecisions property value (defaults to false).
+ *
+ * @author Fabien Potencier
+ * @author Hugo Hamon
+ */
+class UnanimousAccessStrategy extends AccessStrategy implements AccessStrategyInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function decide(TokenInterface $token, array $attributes, $object = null)
+ {
+ $grant = 0;
+ foreach ($attributes as $attribute) {
+ foreach ($this->voters as $voter) {
+ $result = $voter->vote($token, $object, array($attribute));
+
+ switch ($result) {
+ case VoterInterface::ACCESS_GRANTED:
+ ++$grant;
+
+ break;
+
+ case VoterInterface::ACCESS_DENIED:
+ return false;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ // no deny votes
+ if ($grant > 0) {
+ return true;
+ }
+
+ return $this->allowIfAllAbstainDecisions;
+ }
+}
\ No newline at end of file
diff --git a/tests/Symfony/Tests/Component/Security/Core/Authorization/AccessDecisionManagerTest.php b/tests/Symfony/Tests/Component/Security/Core/Authorization/AccessDecisionManagerTest.php
index 0ef6ccb306167..526a1d9fc2866 100644
--- a/tests/Symfony/Tests/Component/Security/Core/Authorization/AccessDecisionManagerTest.php
+++ b/tests/Symfony/Tests/Component/Security/Core/Authorization/AccessDecisionManagerTest.php
@@ -18,86 +18,81 @@ class AccessDecisionManagerTest extends \PHPUnit_Framework_TestCase
{
public function testSupportsClass()
{
- $manager = new AccessDecisionManager(array(
+ $strategy = $this->getAccessStrategy(array(
$this->getVoterSupportsClass(true),
$this->getVoterSupportsClass(false),
));
+
+ $manager = new AccessDecisionManager($strategy);
$this->assertTrue($manager->supportsClass('FooClass'));
- $manager = new AccessDecisionManager(array(
+ $strategy = $this->getAccessStrategy(array(
$this->getVoterSupportsClass(false),
$this->getVoterSupportsClass(false),
));
+
+ $manager = new AccessDecisionManager($strategy);
$this->assertFalse($manager->supportsClass('FooClass'));
}
public function testSupportsAttribute()
{
- $manager = new AccessDecisionManager(array(
+ $strategy = $this->getAccessStrategy(array(
$this->getVoterSupportsAttribute(true),
$this->getVoterSupportsAttribute(false),
));
+
+ $manager = new AccessDecisionManager($strategy);
$this->assertTrue($manager->supportsAttribute('foo'));
- $manager = new AccessDecisionManager(array(
+ $strategy = $this->getAccessStrategy(array(
$this->getVoterSupportsAttribute(false),
$this->getVoterSupportsAttribute(false),
));
- $this->assertFalse($manager->supportsAttribute('foo'));
- }
- /**
- * @expectedException InvalidArgumentException
- */
- public function testSetVotersEmpty()
- {
- $manager = new AccessDecisionManager(array());
+ $manager = new AccessDecisionManager($strategy);
+ $this->assertFalse($manager->supportsAttribute('foo'));
}
- /**
- * @dataProvider getStrategyTests
- */
- public function testStrategies($strategy, $voters, $allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions, $expected)
+ public function testDecide()
{
$token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
- $manager = new AccessDecisionManager($voters, $strategy, $allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions);
- $this->assertSame($expected, $manager->decide($token, array('ROLE_FOO')));
- }
+ $strategy = $this->getMockAccessStrategy(true);
+ $manager = new AccessDecisionManager($strategy);
- public function getStrategyTests()
- {
- return array(
- // affirmative
- array('affirmative', $this->getVoters(1, 0, 0), false, true, true),
- array('affirmative', $this->getVoters(1, 2, 0), false, true, true),
- array('affirmative', $this->getVoters(0, 1, 0), false, true, false),
- array('affirmative', $this->getVoters(0, 0, 1), false, true, false),
- array('affirmative', $this->getVoters(0, 0, 1), true, true, true),
+ $this->assertSame(true, $manager->decide($token, array('ROLE_FOO')));
- // consensus
- array('consensus', $this->getVoters(1, 0, 0), false, true, true),
- array('consensus', $this->getVoters(1, 2, 0), false, true, false),
- array('consensus', $this->getVoters(2, 1, 0), false, true, true),
+ $strategy = $this->getMockAccessStrategy(false);
+ $manager = new AccessDecisionManager($strategy);
- array('consensus', $this->getVoters(0, 0, 1), false, true, false),
+ $this->assertSame(false, $manager->decide($token, array('ROLE_FOO')));
+ }
- array('consensus', $this->getVoters(0, 0, 1), true, true, true),
+ private function getMockAccessStrategy($result)
+ {
+ $strategy = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\Strategy\AccessStrategy')
+ ->disableOriginalConstructor()
+ ->getMock();
- array('consensus', $this->getVoters(2, 2, 0), false, true, true),
- array('consensus', $this->getVoters(2, 2, 1), false, true, true),
+ $strategy->expects($this->any())
+ ->method('decide')
+ ->will($this->returnValue($result));
- array('consensus', $this->getVoters(2, 2, 0), false, false, false),
- array('consensus', $this->getVoters(2, 2, 1), false, false, false),
+ return $strategy;
+ }
+
+ private function getAccessStrategy($voters)
+ {
+ $strategy = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\Strategy\AccessStrategy')
+ ->disableOriginalConstructor()
+ ->getMock();
- // unanimous
- array('unanimous', $this->getVoters(1, 0, 0), false, true, true),
- array('unanimous', $this->getVoters(1, 0, 1), false, true, true),
- array('unanimous', $this->getVoters(1, 1, 0), false, true, false),
+ $strategy->expects($this->any())
+ ->method('getVoters')
+ ->will($this->returnValue($voters));
- array('unanimous', $this->getVoters(0, 0, 2), false, true, false),
- array('unanimous', $this->getVoters(0, 0, 2), true, true, true),
- );
+ return $strategy;
}
protected function getVoters($grants, $denies, $abstains)
diff --git a/tests/Symfony/Tests/Component/Security/Core/Authorization/Strategy/AffirmativeAccessStrategyTest.php b/tests/Symfony/Tests/Component/Security/Core/Authorization/Strategy/AffirmativeAccessStrategyTest.php
new file mode 100644
index 0000000000000..6e69120ef4ffa
--- /dev/null
+++ b/tests/Symfony/Tests/Component/Security/Core/Authorization/Strategy/AffirmativeAccessStrategyTest.php
@@ -0,0 +1,68 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Tests\Component\Security\Core\Authorization;
+
+use Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeAccessStrategy;
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+
+class AffirmativeAccessStrategyTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider getDecisions
+ */
+ public function testDecide($voters, $allowIfAllAbstainDecisions, $expected)
+ {
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+
+ $strategy = new AffirmativeAccessStrategy($voters, $allowIfAllAbstainDecisions);
+
+ $this->assertSame($expected, $strategy->decide($token, array('ROLE_FOO')));
+ }
+
+ public function getDecisions()
+ {
+ return array(
+ array($this->getVoters(1, 0, 0), false, true),
+ array($this->getVoters(1, 2, 0), false, true),
+ array($this->getVoters(0, 1, 0), false, false),
+ array($this->getVoters(0, 0, 1), false, false),
+ array($this->getVoters(0, 0, 1), true, true),
+ );
+ }
+
+ protected function getVoters($grants, $denies, $abstains)
+ {
+ $voters = array();
+ for ($i = 0; $i < $grants; $i++) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_GRANTED);
+ }
+ for ($i = 0; $i < $denies; $i++) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_DENIED);
+ }
+ for ($i = 0; $i < $abstains; $i++) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_ABSTAIN);
+ }
+
+ return $voters;
+ }
+
+ protected function getVoter($vote)
+ {
+ $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface');
+ $voter->expects($this->any())
+ ->method('vote')
+ ->will($this->returnValue($vote));
+ ;
+
+ return $voter;
+ }
+}
\ No newline at end of file
diff --git a/tests/Symfony/Tests/Component/Security/Core/Authorization/Strategy/ConsensusAccessStrategyTest.php b/tests/Symfony/Tests/Component/Security/Core/Authorization/Strategy/ConsensusAccessStrategyTest.php
new file mode 100644
index 0000000000000..ed92b7b452795
--- /dev/null
+++ b/tests/Symfony/Tests/Component/Security/Core/Authorization/Strategy/ConsensusAccessStrategyTest.php
@@ -0,0 +1,76 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Tests\Component\Security\Core\Authorization;
+
+use Symfony\Component\Security\Core\Authorization\Strategy\ConsensusAccessStrategy;
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+
+class ConsensusAccessStrategyTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider getDecisions
+ */
+ public function testDecide($voters, $allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions, $expected)
+ {
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+
+ $strategy = new ConsensusAccessStrategy($voters, $allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions);
+
+ $this->assertSame($expected, $strategy->decide($token, array('ROLE_FOO')));
+ }
+
+ public function getDecisions()
+ {
+ return array(
+ array($this->getVoters(1, 0, 0), false, true, true),
+ array($this->getVoters(1, 2, 0), false, true, false),
+ array($this->getVoters(2, 1, 0), false, true, true),
+
+ array($this->getVoters(0, 0, 1), false, true, false),
+
+ array($this->getVoters(0, 0, 1), true, true, true),
+
+ array($this->getVoters(2, 2, 0), false, true, true),
+ array($this->getVoters(2, 2, 1), false, true, true),
+
+ array($this->getVoters(2, 2, 0), false, false, false),
+ array($this->getVoters(2, 2, 1), false, false, false),
+ );
+ }
+
+ protected function getVoters($grants, $denies, $abstains)
+ {
+ $voters = array();
+ for ($i = 0; $i < $grants; $i++) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_GRANTED);
+ }
+ for ($i = 0; $i < $denies; $i++) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_DENIED);
+ }
+ for ($i = 0; $i < $abstains; $i++) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_ABSTAIN);
+ }
+
+ return $voters;
+ }
+
+ protected function getVoter($vote)
+ {
+ $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface');
+ $voter->expects($this->any())
+ ->method('vote')
+ ->will($this->returnValue($vote));
+ ;
+
+ return $voter;
+ }
+}
\ No newline at end of file
diff --git a/tests/Symfony/Tests/Component/Security/Core/Authorization/Strategy/UnanimousAccessStrategyTest.php b/tests/Symfony/Tests/Component/Security/Core/Authorization/Strategy/UnanimousAccessStrategyTest.php
new file mode 100644
index 0000000000000..55cc1941d8926
--- /dev/null
+++ b/tests/Symfony/Tests/Component/Security/Core/Authorization/Strategy/UnanimousAccessStrategyTest.php
@@ -0,0 +1,69 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Tests\Component\Security\Core\Authorization;
+
+use Symfony\Component\Security\Core\Authorization\Strategy\UnanimousAccessStrategy;
+use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
+
+class UnanimousAccessStrategyTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider getDecisions
+ */
+ public function testDecide($voters, $allowIfAllAbstainDecisions, $expected)
+ {
+ $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
+
+ $strategy = new UnanimousAccessStrategy($voters, $allowIfAllAbstainDecisions);
+
+ $this->assertSame($expected, $strategy->decide($token, array('ROLE_FOO')));
+ }
+
+ public function getDecisions()
+ {
+ return array(
+ array($this->getVoters(1, 0, 0), false, true),
+ array($this->getVoters(1, 0, 1), false, true),
+ array($this->getVoters(1, 1, 0), false, false),
+
+ array($this->getVoters(0, 0, 2), false, false),
+ array($this->getVoters(0, 0, 2), true, true),
+ );
+ }
+
+ protected function getVoters($grants, $denies, $abstains)
+ {
+ $voters = array();
+ for ($i = 0; $i < $grants; $i++) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_GRANTED);
+ }
+ for ($i = 0; $i < $denies; $i++) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_DENIED);
+ }
+ for ($i = 0; $i < $abstains; $i++) {
+ $voters[] = $this->getVoter(VoterInterface::ACCESS_ABSTAIN);
+ }
+
+ return $voters;
+ }
+
+ protected function getVoter($vote)
+ {
+ $voter = $this->getMock('Symfony\Component\Security\Core\Authorization\Voter\VoterInterface');
+ $voter->expects($this->any())
+ ->method('vote')
+ ->will($this->returnValue($vote));
+ ;
+
+ return $voter;
+ }
+}
\ No newline at end of file