8000 feature #15151 [Security] Deprecated supportsAttribute and supportsCl… · symfony/symfony@6f7aae9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6f7aae9

Browse files
committed
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
2 parents 6200eb5 + 6588708 commit 6f7aae9

File tree

9 files changed

+163
-5
lines changed

9 files changed

+163
-5
lines changed

UPGRADE-3.0.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,43 @@ UPGRADE FROM 2.x to 3.0
680680
));
681681
```
682682

683+
* The `AbstractVoter::getSupportedAttributes()` and `AbstractVoter::getSupportedClasses()`
684+
methods have been removed in favor of `AbstractVoter::supports()`.
685+
686+
Before:
687+
688+
```php
689+
class MyVoter extends AbstractVoter
690+
{
691+
protected function getSupportedAttributes()
692+
{
693+
return array('CREATE', 'EDIT');
694+
}
695+
696+
protected function getSupportedClasses()
697+
{
698+
return array('AppBundle\Entity\Post');
699+
}
700+
701+
// ...
702+
}
703+
```
704+
705+
After:
706+
707+
```php
708+
class MyVoter extends AbstractVoter
709+
{
710+
protected function supports($attribute, $class)
711+
{
712+
return $this->isClassInstanceOf($class, 'AppBundle\Entity\Post')
713+
&& in_array($attribute, array('CREATE', 'EDIT'));
714+
}
715+
716+
// ...
717+
}
718+
```
719+
683720
### Translator
684721

685722
* The `Translator::setFallbackLocale()` method has been removed in favor of

src/Symfony/Comp 6D40 onent/Security/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ CHANGELOG
1212
`Symfony\Component\Security\Http\Authentication\SimpleFormAuthenticatorInterface` instead
1313
* deprecated `Symfony\Component\Security\Core\Util\ClassUtils`, use
1414
`Symfony\Component\Security\Acl\Util\ClassUtils` instead
15+
* deprecated `supportsAttribute()` and `supportsClass()` methods of
16+
`Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface` and
17+
`Symfony\Component\Security\Core\Authorization\Voter\VoterInterface`.
18+
* deprecated `getSupportedAttributes()` and `getSupportedClasses()` methods of
19+
`Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter`, use `supports()` instead.
1520

1621
2.7.0
1722
-----

src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ public function decide(TokenInterface $token, array $attributes, $object = null)
7777
*/
7878
public function supportsAttribute($attribute)
7979
{
80+
@trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.');
81+
8082
foreach ($this->voters as $voter) {
8183
if ($voter->supportsAttribute($attribute)) {
8284
return true;
@@ -91,6 +93,8 @@ public function supportsAttribute($attribute)
9193
*/
9294
public function supportsClass($class)
9395
{
96+
@trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.');
97+
9498
foreach ($this->voters as $voter) {
9599
if ($voter->supportsClass($class)) {
96100
return true;

src/Symfony/Component/Security/Core/Authorization/AccessDecisionManagerInterface.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public function decide(TokenInterface $token, array $attributes, $object = null)
3737
* @param string $attribute An attribute
3838
*
3939
* @return bool true if this decision manager supports the attribute, false otherwise
40+
*
41+
* @deprecated since version 2.8, to be removed in 3.0.
4042
*/
4143
public function supportsAttribute($attribute);
4244

@@ -46,6 +48,8 @@ public function supportsAttribute($attribute);
4648
* @param string $class A class name
4749
*
4850
* @return true if this decision manager can process the class
51+
*
52+
* @deprecated since version 2.8, to be removed in 3.0.
4953
*/
5054
public function supportsClass($class);
5155
}

src/Symfony/Component/Security/Core/Authorization/Voter/AbstractVoter.php

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ abstract class AbstractVoter implements VoterInterface
2626
*/
2727
public function supportsAttribute($attribute)
2828
{
29+
@trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.');
30+
2931
return in_array($attribute, $this->getSupportedAttributes());
3032
}
3133

@@ -34,6 +36,8 @@ public function supportsAttribute($attribute)
3436
*/
3537
public function supportsClass($class)
3638
{
39+
@trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.');
40+
3741
foreach ($this->getSupportedClasses() as $supportedClass) {
3842
if ($supportedClass === $class || is_subclass_of($class, $supportedClass)) {
3943
return true;
@@ -58,12 +62,13 @@ public function supportsClass($class)
5862
*/
5963
public function vote(TokenInterface $token, $object, array $attributes)
6064
{
61-
if (!$object || !$this->supportsClass(get_class($object))) {
65+
if (!$object) {
62< 10000 code>66
return self::ACCESS_ABSTAIN;
6367
}
6468

6569
// abstain vote by default in case none of the attributes are supported
6670
$vote = self::ACCESS_ABSTAIN;
71+
$class = get_class($object);
6772

6873
$reflector = new \ReflectionMethod($this, 'voteOnAttribute');
6974
$isNewOverwritten = $reflector->getDeclaringClass()->getName() !== 'Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter';
@@ -72,7 +77,7 @@ public function vote(TokenInterface $token, $object, array $attributes)
7277
}
7378

7479
foreach ($attributes as $attribute) {
75-
if (!$this->supportsAttribute($attribute)) {
80+
if (!$this->supports($attribute, $class)) {
7681
continue;
7782
}
7883

@@ -95,19 +100,79 @@ public function vote(TokenInterface $token, $object, array $attributes)
95100
return $vote;
96101
}
97102

103+
/**
104+
* Determines if the attribute and class are supported by this voter.
105+
*
106+
* To determine if the passed class is instance of the supported class, the
107+
* isClassInstanceOf() method can be used.
108+
*
109+
* This method will become abstract in 3.0.
110+
*
111+
* @param string $attribute An attribute
112+
* @param string $class The fully qualified class name of the passed object
113+
*
114+
* @return bool True if the attribute and class is supported, false otherwise
115+
*/
116+
protected function supports($attribute, $class)
117+
{
118+
@trigger_error('The getSupportedClasses and getSupportedAttributes methods are deprecated since version 2.8 and will be removed in version 3.0. Overwrite supports instead.');
119+
120+
$classIsSupported = false;
121+
foreach ($this->getSupportedClasses() as $supportedClass) {
122+
if ($this->isClassInstanceOf($class, $supportedClass)) {
123+
$classIsSupported = true;
124+
break;
125+
}
126+
}
127+
128+
if (!$classIsSupported) {
129+
return false;
130+
}
131+
132+
if (!in_array($attribute, $this->getSupportedAttributes())) {
133+
return false;
134+
}
135+
136+
return true;
137+
}
138+
139+
/**
140+
* A helper method to test if the actual class is instanceof or equal
141+
* to the expected class.
142+
*
143+
* @param string $actualClass The actual class name
144+
* @param string $expectedClass The expected class name
145+
*
146+
* @return bool
147+
*/
148+
protected function isClassInstanceOf($actualClass, $expectedClass)
149+
{
150+
return $expectedClass === $actualClass || is_subclass_of($actualClass, $expectedClass);
151+
}
152+
98153
/**
99154
* Return an array of supported classes. This will be called by supportsClass.
100155
*
101156
* @return array an array of supported classes, i.e. array('Acme\DemoBundle\Model\Product')
157+
*
158+
* @deprecated since version 2.8, to be removed in 3.0. Use supports() instead.
102159
*/
103-
abstract protected function getSupportedClasses();
160+
protected function getSupportedClasses()
161+
{
162+
@trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.');
163+
}
104164

105165
/**
106166
* Return an array of supported attributes. This will be called by supportsAttribute.
107167
*
108168
* @return array an array of supported attributes, i.e. array('CREATE', 'READ')
169+
*
170+
* @deprecated since version 2.8, to be removed in 3.0. Use supports() instead.
109171
*/
110-
abstract protected function getSupportedAttributes();
172+
protected function getSupportedAttributes()
173+
{
174+
@trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.');
175+
}
111176

112177
/**
113178
* Perform a single access check operation on a given attribute, object and (optionally) user

src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ interface VoterInterface
3030
* @param string $attribute An attribute
3131
*
3232
* @return bool true if this Voter supports the attribute, false otherwise
33+
*
34+
* @deprecated since version 2.8, to be removed in 3.0.
3335
*/
3436
public function supportsAttribute($attribute);
3537

@@ -39,6 +41,8 @@ public function supportsAttribute($attribute);
3941
* @param string $class A class name
4042
*
4143
* @return bool true if this Voter can process the class
44+
*
45+
* @deprecated since version 2.8, to be removed in 3.0.
4246
*/
4347
public function supportsClass($class);
4448

src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
class AccessDecisionManagerTest extends \PHPUnit_Framework_TestCase
1818
{
19+
/**
20+
* @group legacy
21+
*/
1922
public function testSupportsClass()
2023
{
2124
$manager = new AccessDecisionManager(array(
@@ -31,6 +34,9 @@ public function testSupportsClass()
3134
$this->assertFalse($manager->supportsClass('FooClass'));
3235
}
3336

37+
/**
38+
* @group legacy
39+
*/
3440
public function testSupportsAttribute()
3541
{
3642
$manager = new AccessDecisionManager(array(

src/Symfony/Component/Security/Core/Tests/Authorization/Voter/AbstractVoterTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class DeprecatedVoterFixture extends AbstractVoter
9898
protected function getSupportedClasses()
9999
{
100100
return array(
101-
'Symfony\Component\Security\Tests\Core\Authentication\Voter\ObjectFixture',
101+
'Symfony\Component\Security\Core\Tests\Authorization\Voter\ObjectFixture',
102102
);
103103
}
104104

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Symfony\Component\Security\Core\Tests\Authorization\Voter;
4+
5+
use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter;
6+
7+
class LegacyAbstractVoterTest_Voter extends AbstractVoter
8+
{
9+
protected function getSupportedClasses()
10+
{
11+
return array('AbstractVoterTest_Object');
12+
}
13+
14+
protected function getSupportedAttributes()
15+
{
16+
return array('EDIT', 'CREATE');
17+
}
18+
19+
protected function isGranted($attribute, $object, $user = null)
20+
{
21+
return 'EDIT' === $attribute;
22+
}
23+
}
24+
25+
class LegacyAbstractVoterTest extends AbstractVoterTest
26+
{
27+
protected function setUp()
28+
{
29+
parent::setUp();
30+
31+
$this->voter = new LegacyAbstractVoterTest_Voter();
32+
}
33+
}

0 commit comments

Comments
 (0)
0