diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md index de9a230a55468..9d842155f08ac 100644 --- a/UPGRADE-3.0.md +++ b/UPGRADE-3.0.md @@ -680,6 +680,43 @@ UPGRADE FROM 2.x to 3.0 )); ``` + * The `AbstractVoter::getSupportedAttributes()` and `AbstractVoter::getSupportedClasses()` + methods have been removed in favor of `AbstractVoter::supports()`. + + Before: + + ```php + class MyVoter extends AbstractVoter + { + protected function getSupportedAttributes() + { + return array('CREATE', 'EDIT'); + } + + protected function getSupportedClasses() + { + return array('AppBundle\Entity\Post'); + } + + // ... + } + ``` + + After: + + ```php + class MyVoter extends AbstractVoter + { + protected function supports($attribute, $class) + { + return $this->isClassInstanceOf($class, 'AppBundle\Entity\Post') + && in_array($attribute, array('CREATE', 'EDIT')); + } + + // ... + } + ``` + ### Translator * The `Translator::setFallbackLocale()` method has been removed in favor of diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 0728da9bdb70a..5e89a92aea65c 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -12,6 +12,11 @@ CHANGELOG `Symfony\Component\Security\Http\Authentication\SimpleFormAuthenticatorInterface` instead * deprecated `Symfony\Component\Security\Core\Util\ClassUtils`, use `Symfony\Component\Security\Acl\Util\ClassUtils` instead + * deprecated `supportsAttribute()` and `supportsClass()` methods of + `Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface` and + `Symfony\Component\Security\Core\Authorization\Voter\VoterInterface`. + * deprecated `getSupportedAttributes()` and `getSupportedClasses()` methods of + `Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter`, use `supports()` instead. 2.7.0 ----- diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php index e021cc73547c8..ef942b852691f 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php @@ -77,6 +77,8 @@ public function decide(TokenInterface $token, array $attributes, $object = null) */ public function supportsAttribute($attribute) { + @trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.'); + foreach ($this->voters as $voter) { if ($voter->supportsAttribute($attribute)) { return true; @@ -91,6 +93,8 @@ public function supportsAttribute($attribute) */ public function supportsClass($class) { + @trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.'); + foreach ($this->voters as $voter) { if ($voter->supportsClass($class)) { return true; diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.php index 16209ba4080f9..d18b5e3466873 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.php +++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.php @@ -37,6 +37,8 @@ public function decide(TokenInterface $token, array $attributes, $object = null) * @param string $attribute An attribute * * @return bool true if this decision manager supports the attribute, false otherwise + * + * @deprecated since version 2.8, to be removed in 3.0. */ public function supportsAttribute($attribute); @@ -46,6 +48,8 @@ public function supportsAttribute($attribute); * @param string $class A class name * * @return true if this decision manager can process the class + * + * @deprecated since version 2.8, to be removed in 3.0. */ public function supportsClass($class); } diff --git a/src/Symfony/Component/Security/Core/Authorization/Voter/AbstractVoter.php b/src/Symfony/Component/Security/Core/Authorization/Voter/AbstractVoter.php index 6bbea361fd098..2cafc5f952bd7 100644 --- a/src/Symfony/Component/Security/Core/Authorization/Voter/AbstractVoter.php +++ b/src/Symfony/Component/Security/Core/Authorization/Voter/AbstractVoter.php @@ -26,6 +26,8 @@ abstract class AbstractVoter implements VoterInterface */ public function supportsAttribute($attribute) { + @trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.'); + return in_array($attribute, $this->getSupportedAttributes()); } @@ -34,6 +36,8 @@ public function supportsAttribute($attribute) */ public function supportsClass($class) { + @trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.'); + foreach ($this->getSupportedClasses() as $supportedClass) { if ($supportedClass === $class || is_subclass_of($class, $supportedClass)) { return true; @@ -58,12 +62,13 @@ public function supportsClass($class) */ public function vote(TokenInterface $token, $object, array $attributes) { - if (!$object || !$this->supportsClass(get_class($object))) { + if (!$object) { return self::ACCESS_ABSTAIN; } // abstain vote by default in case none of the attributes are supported $vote = self::ACCESS_ABSTAIN; + $class = get_class($object); $reflector = new \ReflectionMethod($this, 'voteOnAttribute'); $isNewOverwritten = $reflector->getDeclaringClass()->getName() !== 'Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter'; @@ -72,7 +77,7 @@ public function vote(TokenInterface $token, $object, array $attributes) } foreach ($attributes as $attribute) { - if (!$this->supportsAttribute($attribute)) { + if (!$this->supports($attribute, $class)) { continue; } @@ -95,19 +100,79 @@ public function vote(TokenInterface $token, $object, array $attributes) return $vote; } + /** + * Determines if the attribute and class are supported by this voter. + * + * To determine if the passed class is instance of the supported class, the + * isClassInstanceOf() method can be used. + * + * This method will become abstract in 3.0. + * + * @param string $attribute An attribute + * @param string $class The fully qualified class name of the passed object + * + * @return bool True if the attribute and class is supported, false otherwise + */ + protected function supports($attribute, $class) + { + @trigger_error('The getSupportedClasses and getSupportedAttributes methods are deprecated since version 2.8 and will be removed in version 3.0. Overwrite supports instead.'); + + $classIsSupported = false; + foreach ($this->getSupportedClasses() as $supportedClass) { + if ($this->isClassInstanceOf($class, $supportedClass)) { + $classIsSupported = true; + break; + } + } + + if (!$classIsSupported) { + return false; + } + + if (!in_array($attribute, $this->getSupportedAttributes())) { + return false; + } + + return true; + } + + /** + * A helper method to test if the actual class is instanceof or equal + * to the expected class. + * + * @param string $actualClass The actual class name + * @param string $expectedClass The expected class name + * + * @return bool + */ + protected function isClassInstanceOf($actualClass, $expectedClass) + { + return $expectedClass === $actualClass || is_subclass_of($actualClass, $expectedClass); + } + /** * Return an array of supported classes. This will be called by supportsClass. * * @return array an array of supported classes, i.e. array('Acme\DemoBundle\Model\Product') + * + * @deprecated since version 2.8, to be removed in 3.0. Use supports() instead. */ - abstract protected function getSupportedClasses(); + protected function getSupportedClasses() + { + @trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.'); + } /** * Return an array of supported attributes. This will be called by supportsAttribute. * * @return array an array of supported attributes, i.e. array('CREATE', 'READ') + * + * @deprecated since version 2.8, to be removed in 3.0. Use supports() instead. */ - abstract protected function getSupportedAttributes(); + protected function getSupportedAttributes() + { + @trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.'); + } /** * Perform a single access check operation on a given attribute, object and (optionally) user diff --git a/src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php b/src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php index d00ff1cfaefae..7e243f9fbd9d0 100644 --- a/src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php +++ b/src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php @@ -30,6 +30,8 @@ interface VoterInterface * @param string $attribute An attribute * * @return bool true if this Voter supports the attribute, false otherwise + * + * @deprecated since version 2.8, to be removed in 3.0. */ public function supportsAttribute($attribute); @@ -39,6 +41,8 @@ public function supportsAttribute($attribute); * @param string $class A class name * * @return bool true if this Voter can process the class + * + * @deprecated since version 2.8, to be removed in 3.0. */ public function supportsClass($class); diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php index bd876c729f1d8..08bbc5824518a 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php @@ -16,6 +16,9 @@ class AccessDecisionManagerTest extends \PHPUnit_Framework_TestCase { + /** + * @group legacy + */ public function testSupportsClass() { $manager = new AccessDecisionManager(array( @@ -31,6 +34,9 @@ public function testSupportsClass() $this->assertFalse($manager->supportsClass('FooClass')); } + /** + * @group legacy + */ public function testSupportsAttribute() { $manager = new AccessDecisionManager(array( diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/Voter/AbstractVoterTest.php b/src/Symfony/Component/Security/Core/Tests/Authorization/Voter/AbstractVoterTest.php new file mode 100644 index 0000000000000..23ac6db71aa00 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Tests/Authorization/Voter/AbstractVoterTest.php @@ -0,0 +1,72 @@ +isClassInstanceOf($class, 'AbstractVoterTest_Object') + && in_array($attribute, array('EDIT', 'CREATE')); + } +} + +class AbstractVoterTest extends \PHPUnit_Framework_TestCase +{ + protected $voter; + protected $object; + protected $token; + + protected function setUp() + { + $this->voter = new AbstractVoterTest_Voter(); + $this->object = $this->getMock('AbstractVoterTest_Object'); + $this->token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); + } + + public function testAttributeAndClassSupported() + { + $this->assertEquals(VoterInterface::ACCESS_GRANTED, $this->voter->vote($this->token, $this->object, array('EDIT')), 'ACCESS_GRANTED if attribute grants access'); + $this->assertEquals(VoterInterface::ACCESS_DENIED, $this->voter->vote($this->token, $this->object, array('CREATE')), 'ACESS_DENIED if attribute denies access'); + } + + public function testOneAttributeSupported() + { + $this->assertEquals(VoterInterface::ACCESS_GRANTED, $this->voter->vote($this->token, $this->object, array('DELETE', 'EDIT')), 'ACCESS_GRANTED if supported attribute grants access'); + $this->assertEquals(VoterInterface::ACCESS_DENIED, $this->voter->vote($this->token, $this->object, array('DELETE', 'CREATE')), 'ACCESS_DENIED if supported attribute denies access'); + } + + public function testOneAttributeGrantsAccess() + { + $this->assertEquals(VoterInterface::ACCESS_GRANTED, $this->voter->vote($this->token, $this->object, array('CREATE', 'EDIT')), 'ACCESS_GRANTED'); + } + + public function testNoAttributeSupported() + { + $this->assertEquals(VoterInterface::ACCESS_ABSTAIN, $this->voter->vote($this->token, $this->object, array('DELETE')), 'ACCESS_ABSTAIN'); + } + + public function testClassNotSupported() + { + $this->assertEquals(VoterInterface::ACCESS_ABSTAIN, $this->voter->vote($this->token, $this->getMock('AbstractVoterTest_Object1'), array('EDIT')), 'ACCESS_ABSTAIN'); + } + + public function testNullObject() + { + $this->assertEquals(VoterInterface::ACCESS_ABSTAIN, $this->voter->vote($this->token, null, array('EDIT')), 'ACCESS_ABSTAIN'); + } + + public function testNoAttributes() + { + $this->assertEquals(VoterInterface::ACCESS_ABSTAIN, $this->voter->vote($this->token, $this->object, array()), 'ACCESS_ABSTAIN'); + } +} diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/Voter/LegacyAbstractVoterTest.php b/src/Symfony/Component/Security/Core/Tests/Authorization/Voter/LegacyAbstractVoterTest.php new file mode 100644 index 0000000000000..3a0cf1eb3993f --- /dev/null +++ b/src/Symfony/Component/Security/Core/Tests/Authorization/Voter/LegacyAbstractVoterTest.php @@ -0,0 +1,33 @@ +voter = new LegacyAbstractVoterTest_Voter(); + } +} diff --git a/src/Symfony/Component/Security/Tests/Core/Authentication/Voter/AbstractVoterTest.php b/src/Symfony/Component/Security/Tests/Core/Authentication/Voter/AbstractVoterTest.php deleted file mode 100644 index ecf82fbfe49f1..0000000000000 --- a/src/Symfony/Component/Security/Tests/Core/Authentication/Voter/AbstractVoterTest.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Security\Tests\Core\Authentication\Voter; - -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; -use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter; - -/** - * @author Roman Marintšenko - */ -class AbstractVoterTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var AbstractVoter - */ - private $voter; - - private $token; - - protected function setUp() - { - $this->voter = new VoterFixture(); - - $tokenMock = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); - $tokenMock - ->expects($this->any()) - ->method('getUser') - ->will($this->returnValue('user')); - - $this->token = $tokenMock; - } - - /** - * @dataProvider getData - */ - public function testVote($expectedVote, $object, $attributes, $message) - { - $this->assertEquals($expectedVote, $this->voter->vote($this->token, $object, $attributes), $message); - } - - /** - * @dataProvider getData - * @group legacy - */ - public function testVoteUsingDeprecatedIsGranted($expectedVote, $object, $attributes, $message) - { - $voter = new DeprecatedVoterFixture(); - - $this->assertEquals($expectedVote, $voter->vote($this->token, $object, $attributes), $message); - } - - public function getData() - { - return array( - array(AbstractVoter::ACCESS_ABSTAIN, null, array(), 'ACCESS_ABSTAIN for null objects'), - array(AbstractVoter::ACCESS_ABSTAIN, new UnsupportedObjectFixture(), array(), 'ACCESS_ABSTAIN for objects with unsupported class'), - array(AbstractVoter::ACCESS_ABSTAIN, new ObjectFixture(), array(), 'ACCESS_ABSTAIN for no attributes'), - array(AbstractVoter::ACCESS_ABSTAIN, new ObjectFixture(), array('foobar'), 'ACCESS_ABSTAIN for unsupported attributes'), - array(AbstractVoter::ACCESS_GRANTED, new ObjectFixture(), array('foo'), 'ACCESS_GRANTED if attribute grants access'), - array(AbstractVoter::ACCESS_GRANTED, new ObjectFixture(), array('bar', 'foo'), 'ACCESS_GRANTED if *at least one* attribute grants access'), - array(AbstractVoter::ACCESS_GRANTED, new ObjectFixture(), array('foobar', 'foo'), 'ACCESS_GRANTED if *at least one* attribute grants access'), - array(AbstractVoter::ACCESS_DENIED, new ObjectFixture(), array('bar', 'baz'), 'ACCESS_DENIED for if no attribute grants access'), - ); - } -} - -class VoterFixture extends AbstractVoter -{ - protected function getSupportedClasses() - { - return array( - 'Symfony\Component\Security\Tests\Core\Authentication\Voter\ObjectFixture', - ); - } - - protected function getSupportedAttributes() - { - return array('foo', 'bar', 'baz'); - } - - protected function voteOnAttribute($attribute, $object, TokenInterface $token) - { - return $attribute === 'foo'; - } -} - -class DeprecatedVoterFixture extends AbstractVoter -{ - protected function getSupportedClasses() - { - return array( - 'Symfony\Component\Security\Tests\Core\Authentication\Voter\ObjectFixture', - ); - } - - protected function getSupportedAttributes() - { - return array('foo', 'bar', 'baz'); - } - - protected function isGranted($attribute, $object, $user = null) - { - return $attribute === 'foo'; - } -} - -class ObjectFixture -{ -} - -class UnsupportedObjectFixture -{ -} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy