Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2fb4f3d

Browse filesBrowse files
committed
[Security] Add an abstract voter
1 parent a22a436 commit 2fb4f3d
Copy full SHA for 2fb4f3d

File tree

Expand file treeCollapse file tree

5 files changed

+166
-4
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+166
-4
lines changed

‎UPGRADE-2.8.md

Copy file name to clipboardExpand all lines: UPGRADE-2.8.md
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ FrameworkBundle
442442
Security
443443
--------
444444
445-
* The AbstractToken::isGranted() method was deprecated. Instead,
445+
* The `AbstractVoter::isGranted()` method was deprecated. Instead,
446446
override the voteOnAttribute() method. This method has one small
447447
difference: it's passed the TokenInterface instead of the user:
448448

@@ -475,6 +475,8 @@ Security
475475
}
476476
```
477477

478+
* The `AbstractVoter` is deprecated. Use `Voter` instead.
479+
478480
Config
479481
------
480482

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Core/Authorization/Voter/AbstractVoter.php
+6-1Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,18 @@
1111

1212
namespace Symfony\Component\Security\Core\Authorization\Voter;
1313

14+
@trigger_error('The '.__NAMESPACE__.'\AbstractVoter class is deprecated since version 2.8, to be removed in 3.0. Upgrade to Symfony\Component\Security\Core\Authorization\Voter\Voter instead.', E_USER_DEPRECATED);
15+
16+
1417
use Symfony\Component\Security\Core\User\UserInterface;
1518
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
1619

1720
/**
1821
* Abstract Voter implementation that reduces boilerplate code required to create a custom Voter.
1922
*
2023
* @author Roman Marintšenko <inoryy@gmail.com>
24+
*
25+
* @deprecated since version 2.8, to be removed in 3.0. Upgrade to Symfony\Component\Security\Core\Authorization\Voter\Voter instead
2126
*/
2227
abstract class AbstractVoter implements VoterInterface
2328
{
@@ -92,7 +97,7 @@ public function vote(TokenInterface $token, $object, array $attributes)
9297
* This method will become abstract in 3.0.
9398
*
9499
* @param string $attribute An attribute
95-
* @param string $object The object to secure
100+
* @param object $object The object to secure
96101
*
97102
* @return bool True if the attribute and object is supported, false otherwise
98103
*/
+85Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Security\Core\Authorization\Voter;
13+
14+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
15+
16+
/**
17+
* Voter is an abstract default implementation of a voter.
18+
*
19+
* @author Grégoire Pineau <lyrixx@lyrixx.info>
20+
*/
21+
abstract class Voter implements VoterInterface
22+
{
23+
/**
24+
* {@inheritdoc}
25+
*/
26+
public function supportsAttribute($attribute)
27+
{
28+
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function supportsClass($class)
34+
{
35+
}
36+
37+
/**
38+
* {@inheritdoc}
39+
*/
40+
public function vote(TokenInterface $token, $subject, array $attributes)
41+
{
42+
// abstain vote by default in case none of the attributes are supported
43+
$vote = self::ACCESS_ABSTAIN;
44+
45+
foreach ($attributes as $attribute) {
46+
if (!$this->supports($attribute, $subject)) {
47+
continue;
48+
}
49+
50+
// as soon as at least one attribute is supported, default is to
51+
// deny access
52+
$vote = self::ACCESS_DENIED;
53+
54+
if ($this->voteOnAttribute($attribute, $subject, $token)) {
55+
// grant access as soon as at least one voter returns a positive
56+
// response
57+
return self::ACCESS_GRANTED;
58+
}
59+
}
60+
61+
return $vote;
62+
}
63+
64+
/**
65+
* Determines if the attribute and subject are supported by this voter.
66+
*
67+
* @param string $attribute An attribute
68+
* @param string $subject The subject to secure
69+
*
70+
* @return bool True if the attribute and subject is supported, false otherwise
71+
*/
72+
abstract protected function supports($attribute, $subject);
73+
74+
/**
75+
* Perform a single access check operation on a given attribute, subject and
76+
* token.
77+
*
78+
* @param string $attribute
79+
* @param mixed $subject
80+
* @param TokenInterface $token
81+
*
82+
* @return bool
83+
*/
84+
abstract protected function voteOnAttribute($attribute, $subject, TokenInterface $token);
85+
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ public function supportsClass($class);
5353
* ACCESS_GRANTED, ACCESS_DENIED, or ACCESS_ABSTAIN.
5454
*
5555
* @param TokenInterface $token A TokenInterface instance
56-
* @param object|null $object The object to secure
56+
* @param mixed $subject The subject to secure
5757
* @param array $attributes An array of attributes associated with the method being invoked
5858
*
5959
* @return int either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED
6060
*/
61-
public function vote(TokenInterface $token, $object, array $attributes);
61+
public function vote(TokenInterface $token, $subject, array $attributes);
6262
}
+70Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Security\Core\Tests\Authorization\Voter;
13+
14+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
15+
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
16+
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
17+
18+
class VoterTest extends \PHPUnit_Framework_TestCase
19+
{
20+
protected $token;
21+
22+
protected function setUp()
23+
{
24+
$this->token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
25+
}
26+
27+
public function getTests()
28+
{
29+
return array(
30+
array(array('EDIT'), VoterInterface::ACCESS_GRANTED, new \stdClass(), 'ACCESS_GRANTED if attribute and class are supported and attribute grants access'),
31+
array(array('CREATE'), VoterInterface::ACCESS_DENIED, new \stdClass(), 'ACCESS_DENIED if attribute and class are supported and attribute does not grant access'),
32+
33+
array(array('DELETE', 'EDIT'), VoterInterface::ACCESS_GRANTED, new \stdClass(), 'ACCESS_GRANTED if one attribute is supported and grants access'),
34+
array(array('DELETE', 'CREATE'), VoterInterface::ACCESS_DENIED, new \stdClass(), 'ACCESS_DENIED if one attribute is supported and denies access'),
35+
36+
array(array('CREATE', 'EDIT'), VoterInterface::ACCESS_GRANTED, new \stdClass(), 'ACCESS_GRANTED if one attribute grants access'),
37+
38+
array(array('DELETE'), VoterInterface::ACCESS_ABSTAIN, new \stdClass(), 'ACCESS_ABSTAIN if no attribute is supported'),
39+
40+
array(array('EDIT'), VoterInterface::ACCESS_ABSTAIN, $this, 'ACCESS_ABSTAIN if class is not supported'),
41+
42+
array(array('EDIT'), VoterInterface::ACCESS_ABSTAIN, null, 'ACCESS_ABSTAIN if object is null'),
43+
44+
array(array(), VoterInterface::ACCESS_ABSTAIN, new \stdClass(), 'ACCESS_ABSTAIN if no attributes were provided'),
45+
);
46+
}
47+
48+
/**
49+
* @dataProvider getTests
50+
*/
51+
public function testVote(array $attributes, $expectedVote, $object, $message)
52+
{
53+
$voter = new AbstractVoterTest_Voter();
54+
55+
$this->assertEquals($expectedVote, $voter->vote($this->token, $object, $attributes), $message);
56+
}
57+
}
58+
59+
class AbstractVoterTest_Voter extends Voter
60+
{
61+
protected function voteOnAttribute($attribute, $object, TokenInterface $token)
62+
{
63+
return 'EDIT' === $attribute;
64+
}
65+
66+
protected function supports($attribute, $object)
67+
{
68+
return $object instanceof \stdClass && in_array($attribute, array('EDIT', 'CREATE'));
69+
}
70+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.