summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabien Potencier <fabien.potencier@gmail.com>2015-09-25 13:44:05 +0200
committerFabien Potencier <fabien.potencier@gmail.com>2015-09-25 13:44:05 +0200
commitd250979823c59287ae69988bc9898632a2eea201 (patch)
treea1a61c102a8bf72d623ebbc0dc37004f999e06ad
parenta99b4984c7212fa88858e26526e4d8e6d4af7a39 (diff)
parent0189f2b2191ba9cec13b7e53265824943d12700f (diff)
downloadsymfony-security-d250979823c59287ae69988bc9898632a2eea201.zip
symfony-security-d250979823c59287ae69988bc9898632a2eea201.tar.gz
symfony-security-d250979823c59287ae69988bc9898632a2eea201.tar.bz2
feature #15151 [Security] Deprecated supportsAttribute and supportsClass methods (WouterJ)
This PR was squashed before being merged into the 2.8 branch (closes #15151). Discussion ---------- [Security] Deprecated supportsAttribute and supportsClass methods These methods aren't used at all in a Symfony application and don't make sense to use in the application. They are only used internally in the voters. This means the voter interface can be made much easier. I'm not sure how we do these deprecations, should we remove the methods from the interface now already? Also, I don't think it's possible to trigger deprecation notices for the voter methods? | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | one of #11742 | License | MIT | Doc PR | - Abstract Voter --- There is one remaining question about the abstract voter. This currently has abstract `getSupportedAttributes()` and `getSupportedClass()` methods. One of the reasons to remove the methods for the interface was that these methods are not flexible. Does it make sense to deprecate these methods as well and replace them by an abstract `protected vote(array $attributes, $class)` method in the `AbstractVoter` (which is called from `AbstractVoter#vote()`) ? Commits ------- 6588708 [Security] Deprecated supportsAttribute and supportsClass methods
-rw-r--r--CHANGELOG.md5
-rw-r--r--Core/Authorization/AccessDecisionManager.php4
-rw-r--r--Core/Authorization/AccessDecisionManagerInterface.php4
-rw-r--r--Core/Authorization/Voter/AbstractVoter.php73
-rw-r--r--Core/Authorization/Voter/VoterInterface.php4
-rw-r--r--Core/Tests/Authorization/AccessDecisionManagerTest.php6
-rw-r--r--Core/Tests/Authorization/Voter/AbstractVoterTest.php2
-rw-r--r--Core/Tests/Authorization/Voter/LegacyAbstractVoterTest.php33
8 files changed, 126 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0728da9..5e89a92 100644
--- a/CHANGELOG.md
+++ b/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/Core/Authorization/AccessDecisionManager.php b/Core/Authorization/AccessDecisionManager.php
index e021cc7..ef942b8 100644
--- a/Core/Authorization/AccessDecisionManager.php
+++ b/Core/Authorization/AccessDecisionManager.php
@@ -77,6 +77,8 @@ class AccessDecisionManager implements AccessDecisionManagerInterface
*/
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 @@ class AccessDecisionManager implements AccessDecisionManagerInterface
*/
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/Core/Authorization/AccessDecisionManagerInterface.php b/Core/Authorization/AccessDecisionManagerInterface.php
index 16209ba..d18b5e3 100644
--- a/Core/Authorization/AccessDecisionManagerInterface.php
+++ b/Core/Authorization/AccessDecisionManagerInterface.php
@@ -37,6 +37,8 @@ interface AccessDecisionManagerInterface
* @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 @@ interface AccessDecisionManagerInterface
* @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/Core/Authorization/Voter/AbstractVoter.php b/Core/Authorization/Voter/AbstractVoter.php
index 6bbea36..2cafc5f 100644
--- a/Core/Authorization/Voter/AbstractVoter.php
+++ b/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 @@ abstract class AbstractVoter implements VoterInterface
*/
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 @@ abstract class AbstractVoter implements VoterInterface
*/
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 @@ abstract class AbstractVoter implements VoterInterface
}
foreach ($attributes as $attribute) {
- if (!$this->supportsAttribute($attribute)) {
+ if (!$this->supports($attribute, $class)) {
continue;
}
@@ -96,18 +101,78 @@ abstract class AbstractVoter implements VoterInterface
}
/**
+ * 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/Core/Authorization/Voter/VoterInterface.php b/Core/Authorization/Voter/VoterInterface.php
index d00ff1c..7e243f9 100644
--- a/Core/Authorization/Voter/VoterInterface.php
+++ b/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 @@ interface VoterInterface
* @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/Core/Tests/Authorization/AccessDecisionManagerTest.php b/Core/Tests/Authorization/AccessDecisionManagerTest.php
index bd876c7..08bbc58 100644
--- a/Core/Tests/Authorization/AccessDecisionManagerTest.php
+++ b/Core/Tests/Authorization/AccessDecisionManagerTest.php
@@ -16,6 +16,9 @@ use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
class AccessDecisionManagerTest extends \PHPUnit_Framework_TestCase
{
+ /**
+ * @group legacy
+ */
public function testSupportsClass()
{
$manager = new AccessDecisionManager(array(
@@ -31,6 +34,9 @@ class AccessDecisionManagerTest extends \PHPUnit_Framework_TestCase
$this->assertFalse($manager->supportsClass('FooClass'));
}
+ /**
+ * @group legacy
+ */
public function testSupportsAttribute()
{
$manager = new AccessDecisionManager(array(
diff --git a/Core/Tests/Authorization/Voter/AbstractVoterTest.php b/Core/Tests/Authorization/Voter/AbstractVoterTest.php
index 4e38fd6..44da147 100644
--- a/Core/Tests/Authorization/Voter/AbstractVoterTest.php
+++ b/Core/Tests/Authorization/Voter/AbstractVoterTest.php
@@ -98,7 +98,7 @@ class DeprecatedVoterFixture extends AbstractVoter
protected function getSupportedClasses()
{
return array(
- 'Symfony\Component\Security\Tests\Core\Authentication\Voter\ObjectFixture',
+ 'Symfony\Component\Security\Core\Tests\Authorization\Voter\ObjectFixture',
);
}
diff --git a/Core/Tests/Authorization/Voter/LegacyAbstractVoterTest.php b/Core/Tests/Authorization/Voter/LegacyAbstractVoterTest.php
new file mode 100644
index 0000000..3a0cf1e
--- /dev/null
+++ b/Core/Tests/Authorization/Voter/LegacyAbstractVoterTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Symfony\Component\Security\Core\Tests\Authorization\Voter;
+
+use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter;
+
+class LegacyAbstractVoterTest_Voter extends AbstractVoter
+{
+ protected function getSupportedClasses()
+ {
+ return array('AbstractVoterTest_Object');
+ }
+
+ protected function getSupportedAttributes()
+ {
+ return array('EDIT', 'CREATE');
+ }
+
+ protected function isGranted($attribute, $object, $user = null)
+ {
+ return 'EDIT' === $attribute;
+ }
+}
+
+class LegacyAbstractVoterTest extends AbstractVoterTest
+{
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->voter = new LegacyAbstractVoterTest_Voter();
+ }
+}