Skip to content

Commit

Permalink
feature symfony#5926 Update voter section of best practices (WouterJ)
Browse files Browse the repository at this point in the history
This PR was merged into the 2.8 branch.

Discussion
----------

Update voter section of best practices

| Q | A
| --- | ---
| Doc fix? | yes
| New docs? | yes
| Applies to | 2.8+
| Fixed tickets | symfony#4389, symfony#5728

Commits
-------

68da041 Update voter section of best practices
  • Loading branch information
weaverryan committed Nov 30, 2015
2 parents bb1a9b7 + 68da041 commit 757e159
Showing 1 changed file with 45 additions and 15 deletions.
60 changes: 45 additions & 15 deletions best_practices/security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -264,37 +264,66 @@ the same ``getAuthorEmail`` logic you used above:
namespace AppBundle\Security;
use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\User\UserInterface;
use AppBundle\Entity\Post;
// AbstractVoter class requires Symfony 2.6 or higher version
class PostVoter extends AbstractVoter
// Voter class requires Symfony 2.8 or higher version
class PostVoter extends Voter
{
const CREATE = 'create';
const EDIT = 'edit';
protected function getSupportedAttributes()
/**
* @var AccessDecisionManagerInterface
*/
private $decisionManager;
public function __construct(AccessDecisionManagerInterface $decisionManager)
{
return array(self::CREATE, self::EDIT);
$this->decisionManager = $decisionManager;
}
protected function getSupportedClasses()
protected function supports($attribute, $subject)
{
return array('AppBundle\Entity\Post');
if (!in_array($attribute, array(self::CREATE, self::EDIT))) {
return false;
}
if (!$subject instanceof Post) {
return false;
}
return true;
}
protected function isGranted($attribute, $post, $user = null)
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
$user = $token->getUser();
/** @var Post */
$post = $subject; // $subject must be a Post instance, thanks to the supports method
if (!$user instanceof UserInterface) {
return false;
}
if ($attribute === self::CREATE && in_array('ROLE_ADMIN', $user->getRoles(), true)) {
return true;
}
if ($attribute === self::EDIT && $user->getEmail() === $post->getAuthorEmail()) {
return true;
switch ($attribute) {
case self::CREATE:
// if the user is an admin, allow them to create new posts
if ($this->decisionManager->decide($token, array('ROLE_ADMIN'))) {
return true;
}
break;
case self::EDIT:
// if the user is the author of the post, allow them to edit the posts
if ($user->getEmail() === $post->getAuthorEmail()) {
return true;
}
break;
}
return false;
Expand All @@ -310,6 +339,7 @@ To enable the security voter in the application, define a new service:
# ...
post_voter:
class: AppBundle\Security\PostVoter
arguments: ['@security.access.decision_manager']
public: false
tags:
- { name: security.voter }
Expand Down Expand Up @@ -337,7 +367,7 @@ via the even easier shortcut in a controller:
*/
public function editAction($id)
{
$post = // query for the post ...
$post = ...; // query for the post
$this->denyAccessUnlessGranted('edit', $post);
Expand Down

0 comments on commit 757e159

Please sign in to comment.