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