Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to give security voter access to current object
    primarykey
    data
    text
    <p>I want to use a Voter to only allow owners to edit a project object in my application. </p> <p>I have a route /project/42/edit that invokes my action ProjectController.editAction(Project $project). I use a type hint (Project $project) to automatically invoke the ParamConverter to convert the ID 42 from the URI into a project object. This works nicely for the controller action, however it seems to be invoked too late for the voter. Its vote() method gets called with the request as 2nd parameter, not my project.</p> <p>Is there a way to pass the project to the voter without having to retrieve it from the database again?</p> <p><em>UPDATE:</em> I <a href="https://stackoverflow.com/questions/17085130/symfony2-how-to-hide-link-in-twig-based-on-permissions/17085535#answer-17085535">learned</a> that I have to manually call isGranted() on the security context in the edit method. This is very similar in approach to <a href="https://stackoverflow.com/a/17035423/1832745">this answer</a>.</p> <p>Here is my Voter:</p> <pre class="lang-php prettyprint-override"><code>namespace FUxCon2013\ProjectsBundle\Security; use FUxCon2013\ProjectsBundle\Entity\Project; use Symfony\Component\BrowserKit\Request; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; class OwnerVoter implements VoterInterface { public function __construct(ContainerInterface $container) { $this-&gt;container = $container; } public function supportsAttribute($attribute) { return $attribute == 'MAY_EDIT'; } public function supportsClass($class) { // your voter supports all type of token classes, so return true return true; } function vote(TokenInterface $token, $object, array $attributes) { if (!in_array('MAY_EDIT', $attributes)) { return self::ACCESS_ABSTAIN; } if (!($object instanceof Project)) { return self::ACCESS_ABSTAIN; } $user = $token-&gt;getUser(); $securityContext = $this-&gt;container-&gt;get('security.context'); return $securityContext-&gt;isGranted('IS_AUTHENTICATED_FULLY') &amp;&amp; $user-&gt;getId() == $object-&gt;getUser()-&gt;getId() ? self::ACCESS_GRANTED : self::ACCESS_DENIED; } } </code></pre> <p>I register this in configure.yml so that it gets the service container as parameter:</p> <pre><code>services: fuxcon2013.security.owner_voter: class: FUxCon2013\ProjectsBundle\Security\OwnerVoter public: false arguments: [ @service_container ] tags: - { name: security.voter } </code></pre> <p>The last block is to configure the access decision manager in security.yml to unanimous:</p> <pre><code>security: access_decision_manager: # strategy can be: affirmative, unanimous or consensus strategy: unanimous allow_if_all_abstain: true </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload