From 28c6536cfae7f995bd65d08725dabafe03b9dd76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Marint=C5=A1enko?= Date: Tue, 23 Sep 2014 07:53:08 +0300 Subject: [PATCH 1/4] add & update doc entries on AbstractVoter implementation --- cookbook/security/abstract_voter.rst.inc | 31 ++++++++ cookbook/security/voters.rst | 7 ++ cookbook/security/voters_data_permission.rst | 84 ++++++-------------- 3 files changed, 61 insertions(+), 61 deletions(-) create mode 100644 cookbook/security/abstract_voter.rst.inc diff --git a/cookbook/security/abstract_voter.rst.inc b/cookbook/security/abstract_voter.rst.inc new file mode 100644 index 00000000000..f12d1d9619a --- /dev/null +++ b/cookbook/security/abstract_voter.rst.inc @@ -0,0 +1,31 @@ +.. code-block:: php + + abstract class AbstractVoter implements VoterInterface + { + public function supportsAttribute($attribute); + public function supportsClass($class); + public function vote(TokenInterface $token, $object, array $attributes); + + abstract protected function getSupportedClasses(); + abstract protected function getSupportedAttributes(); + abstract protected function isGranted($attribute, $object, $user = null); + } + +Behind the scenes this class implements the +:class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface`, +which has this structure: + +.. include:: /cookbook/security/voter_interface.rst.inc + +The basic functionality covering common use cases is provided +and end developer is expected to implement the abstract methods. + +The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::getSupportedClasses` +method is used to provide an array of supported classes, i.e. ['\Acme\DemoBundle\Model\Product'] + +The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::getSupportedAttributes` +method is used to provide an array of supported attributes, i.e. ['CREATE', 'READ'] + +The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::isGranted` +method must implement the business logic that verifies whether or not a given +user is allowed a given attribute on a given object. This method must return a boolean. \ No newline at end of file diff --git a/cookbook/security/voters.rst b/cookbook/security/voters.rst index 6d39cee8ec3..289d85411bd 100644 --- a/cookbook/security/voters.rst +++ b/cookbook/security/voters.rst @@ -92,6 +92,13 @@ the security layer. This can be done easily through the service container. methods in your implementation of the ``vote()`` method and return ``ACCESS_ABSTAIN`` if your voter does not support the class or attribute. + +.. tip:: + + An + :class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter` + is provided to cover the common use cases when implementing security voters. + Declaring the Voter as a Service -------------------------------- diff --git a/cookbook/security/voters_data_permission.rst b/cookbook/security/voters_data_permission.rst index 35442dd5afb..566d53fad16 100644 --- a/cookbook/security/voters_data_permission.rst +++ b/cookbook/security/voters_data_permission.rst @@ -38,10 +38,11 @@ The Voter Interface ------------------- A custom voter must implement -:class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface`, -which has this structure: +:class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface` +and an :class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter` +class is provided with following structure: -.. include:: /cookbook/security/voter_interface.rst.inc +.. include:: /cookbook/security/abstract_voter.rst.inc In this example, the voter will check if the user has access to a specific object according to your custom conditions (e.g. they must be the owner of @@ -61,84 +62,45 @@ edit a particular object. Here's an example implementation: // src/Acme/DemoBundle/Security/Authorization/Voter/PostVoter.php namespace Acme\DemoBundle\Security\Authorization\Voter; - use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; + use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserInterface; - class PostVoter implements VoterInterface + class PostVoter extends AbstractVoter { const VIEW = 'view'; const EDIT = 'edit'; - public function supportsAttribute($attribute) + protected function getSupportedAttributes() { - return in_array($attribute, array( - self::VIEW, - self::EDIT, - )); + return array(self::VIEW, self::EDIT); } - public function supportsClass($class) + protected function getSupportedClasses() { - $supportedClass = 'Acme\DemoBundle\Entity\Post'; - - return $supportedClass === $class || is_subclass_of($class, $supportedClass); + return array('Acme\DemoBundle\Entity\Post'); } - /** - * @var \Acme\DemoBundle\Entity\Post $post - */ - public function vote(TokenInterface $token, $post, array $attributes) + protected function isGranted($attribute, $post, $user = null) { - // check if class of this object is supported by this voter - if (!$this->supportsClass(get_class($post))) { - return VoterInterface::ACCESS_ABSTAIN; - } - - // check if the voter is used correct, only allow one attribute - // this isn't a requirement, it's just one easy way for you to - // design your voter - if(1 !== count($attributes)) { - throw new \InvalidArgumentException( - 'Only one attribute is allowed for VIEW or EDIT' - ); - } - - // set the attribute to check against - $attribute = $attributes[0]; - - // check if the given attribute is covered by this voter - if (!$this->supportsAttribute($attribute)) { - return VoterInterface::ACCESS_ABSTAIN; - } - - // get current logged in user - $user = $token->getUser(); - // make sure there is a user object (i.e. that the user is logged in) if (!$user instanceof UserInterface) { - return VoterInterface::ACCESS_DENIED; + return false; + } + + // the data object could have for example a method isPrivate() + // which checks the Boolean attribute $private + if ($attribute == self::VIEW && !$post->isPrivate()) { + return true; } - switch($attribute) { - case self::VIEW: - // the data object could have for example a method isPrivate() - // which checks the Boolean attribute $private - if (!$post->isPrivate()) { - return VoterInterface::ACCESS_GRANTED; - } - break; - - case self::EDIT: - // we assume that our data object has a method getOwner() to - // get the current owner user entity for this data object - if ($user->getId() === $post->getOwner()->getId()) { - return VoterInterface::ACCESS_GRANTED; - } - break; + // we assume that our data object has a method getOwner() to + // get the current owner user entity for this data object + if ($attribute == self::EDIT && $user->getId() === $post->getOwner()->getId()) { + return true; } - return VoterInterface::ACCESS_DENIED; + return false; } } From da32a5e6c1ad32b55a755d6447913308026c84b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Marint=C5=A1enko?= Date: Tue, 30 Sep 2014 07:54:27 +0300 Subject: [PATCH 2/4] fix problems pointed out by @javiereguiluz and @cordoval --- cookbook/security/abstract_voter.rst.inc | 4 ++-- cookbook/security/voters_data_permission.rst | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cookbook/security/abstract_voter.rst.inc b/cookbook/security/abstract_voter.rst.inc index f12d1d9619a..dffd90b4a00 100644 --- a/cookbook/security/abstract_voter.rst.inc +++ b/cookbook/security/abstract_voter.rst.inc @@ -18,7 +18,7 @@ which has this structure: .. include:: /cookbook/security/voter_interface.rst.inc The basic functionality covering common use cases is provided -and end developer is expected to implement the abstract methods. +and developer is expected to implement the abstract methods. The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::getSupportedClasses` method is used to provide an array of supported classes, i.e. ['\Acme\DemoBundle\Model\Product'] @@ -28,4 +28,4 @@ method is used to provide an array of supported attributes, i.e. ['CREATE', 'REA The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::isGranted` method must implement the business logic that verifies whether or not a given -user is allowed a given attribute on a given object. This method must return a boolean. \ No newline at end of file +user is allowed access to a given attribute on a given object. This method must return a boolean. diff --git a/cookbook/security/voters_data_permission.rst b/cookbook/security/voters_data_permission.rst index 566d53fad16..c574f00ea77 100644 --- a/cookbook/security/voters_data_permission.rst +++ b/cookbook/security/voters_data_permission.rst @@ -63,7 +63,6 @@ edit a particular object. Here's an example implementation: namespace Acme\DemoBundle\Security\Authorization\Voter; use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter; - use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserInterface; class PostVoter extends AbstractVoter From b1a90ba63409f113f5fbfe75cb5c7e7185264025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Marint=C5=A1enko?= Date: Sat, 31 Jan 2015 11:11:56 +0200 Subject: [PATCH 3/4] add fixes to data_permission cookbook --- cookbook/security/voters_data_permission.rst | 31 +++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/cookbook/security/voters_data_permission.rst b/cookbook/security/voters_data_permission.rst index a23a18c9b40..2f101b1dc1d 100644 --- a/cookbook/security/voters_data_permission.rst +++ b/cookbook/security/voters_data_permission.rst @@ -37,12 +37,19 @@ For more information take a look at The Voter Interface ------------------- -A custom voter must implement +A custom voter needs to implement :class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\VoterInterface` -and an :class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter` -class is provided with following structure: +or extend :class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter`, +which makes creating a voter even easier. -.. include:: /cookbook/security/abstract_voter.rst.inc +.. code-block:: php + + abstract class AbstractVoter implements VoterInterface + { + abstract protected function getSupportedClasses(); + abstract protected function getSupportedAttributes(); + abstract protected function isGranted($attribute, $object, $user = null); + } In this example, the voter will check if the user has access to a specific object according to your custom conditions (e.g. they must be the owner of @@ -106,6 +113,22 @@ edit a particular object. Here's an example implementation: That's it! The voter is done. The next step is to inject the voter into the security layer. +To recap, here's what's expected from the three abstract methods: + +The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::getSupportedClasses` +method tells Symfony that your voter should be called whenever an object of one of the given classes +is passed to `isGranted` For example, if you return ['\Acme\DemoBundle\Model\Product'], +Symfony will call your voter when a `Product` object is passed to `isGranted`. + +The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::getSupportedAttributes` +method tells Symfony that your voter should be called whenever one of these strings is passes as the +first argument to `isGranted`. For example, if you return `array('CREATE', 'READ')`, then +Symfony will call your voter when one of these is passed to `isGranted`. + +The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::isGranted` +method must implement the business logic that verifies whether or not a given +user is allowed access to a given attribute on a given object. This method must return a boolean. + Declaring the Voter as a Service -------------------------------- From 36eabcaaeae4f9bee721cbbc71834195fd4ae2bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Marint=C5=A1enko?= Date: Sat, 31 Jan 2015 11:13:35 +0200 Subject: [PATCH 4/4] add fixes to abstract_voter include file --- cookbook/security/abstract_voter.rst.inc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cookbook/security/abstract_voter.rst.inc b/cookbook/security/abstract_voter.rst.inc index dffd90b4a00..3f1319bd01b 100644 --- a/cookbook/security/abstract_voter.rst.inc +++ b/cookbook/security/abstract_voter.rst.inc @@ -21,10 +21,14 @@ The basic functionality covering common use cases is provided and developer is expected to implement the abstract methods. The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::getSupportedClasses` -method is used to provide an array of supported classes, i.e. ['\Acme\DemoBundle\Model\Product'] +method tells Symfony that your voter should be called whenever an object of one of the given classes +is passed to `isGranted` For example, if you return ['\Acme\DemoBundle\Model\Product'], +Symfony will call your voter when a `Product` object is passed to `isGranted`. The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::getSupportedAttributes` -method is used to provide an array of supported attributes, i.e. ['CREATE', 'READ'] +method tells Symfony that your voter should be called whenever one of these strings is passes as the +first argument to `isGranted`. For example, if you return `array('CREATE', 'READ')`, then +Symfony will call your voter when one of these is passed to `isGranted`. The :method:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AbstractVoter::isGranted` method must implement the business logic that verifies whether or not a given pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy