diff --git a/security/voters.rst b/security/voters.rst index d73cdc8d210..5ff991a4a7f 100644 --- a/security/voters.rst +++ b/security/voters.rst @@ -105,7 +105,7 @@ decides this using whatever logic you want.   the ``security.authorization_checker`` service. The main difference is that when access is not granted, ``denyAccessUnlessGranted()`` throws an    ``AccessDeniedException``, whereas ``isGranted()`` returns ``false``. - + Creating the custom Voter ------------------------- @@ -263,106 +263,16 @@ your voter will be executed and you can control access. Checking for Roles inside a Voter --------------------------------- -.. versionadded:: 2.8 - The ability to inject the ``AccessDecisionManager`` is new in 2.8: it caused - a CircularReferenceException before. In earlier versions, you must inject the - ``service_container`` itself and fetch out the ``security.authorization_checker`` - to use ``isGranted()``. - What if you want to call ``isGranted()`` from *inside* your voter - e.g. you want -to see if the current user has ``ROLE_SUPER_ADMIN``. That's possible by injecting -the :class:`Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager` -into your voter. You can use this to, for example, *always* allow access to a user -with ``ROLE_SUPER_ADMIN``:: - - // src/AppBundle/Security/PostVoter.php - - // ... - use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; - - class PostVoter extends Voter - { - // ... - - private $decisionManager; - - public function __construct(AccessDecisionManagerInterface $decisionManager) - { - $this->decisionManager = $decisionManager; - } - - protected function voteOnAttribute($attribute, $subject, TokenInterface $token) - { - // ... - - // ROLE_SUPER_ADMIN can do anything! The power! - if ($this->decisionManager->decide($token, array('ROLE_SUPER_ADMIN'))) { - return true; - } - - // ... all the normal voter logic - } - } - -Next, update ``services.yml`` to inject the ``security.access.decision_manager`` -service: - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/services.yml - services: - app.post_voter: - class: AppBundle\Security\PostVoter - arguments: ['@security.access.decision_manager'] - public: false - tags: - - { name: security.voter } - - .. code-block:: xml - - - - - - - - - - - - - - - .. code-block:: php - - // app/config/services.php - use AppBundle\Security\PostVoter; - use Symfony\Component\DependencyInjection\Definition; - use Symfony\Component\DependencyInjection\Reference; - - $container->register('app.post_voter', PostVoter::class) - ->addArgument(new Reference('security.access.decision_manager')) - ->setPublic(false) - ->addTag('security.voter') - ; - -That's it! Calling ``decide()`` on the ``AccessDecisionManager`` is essentially -the same as calling ``isGranted()`` from a controller or other places -(it's just a little lower-level, which is necessary for a voter). - -.. note:: - - The ``security.access.decision_manager`` is private. This means you can't access - it directly from a controller: you can only inject it into other services. That's - ok: use ``security.authorization_checker`` instead in all cases except for voters. +to see if the current user has ``ROLE_SUPER_ADMIN``. The ``isGranted()`` method +is provided by the ``security.authorization_checker`` service via the +:class:`Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager` +class. However, you can't inject that service because it causes a +``CircularReferenceException``. + +The solution is to inject the ``service_container`` service and use it to get +the ``security.authorization_checker`` service and call to the ``isGranted()`` +method. .. _security-voters-change-strategy: