diff options
Diffstat (limited to 'Core/Authorization')
-rw-r--r-- | Core/Authorization/AccessDecisionManager.php | 32 | ||||
-rw-r--r-- | Core/Authorization/AccessDecisionManagerInterface.php | 22 | ||||
-rw-r--r-- | Core/Authorization/DebugAccessDecisionManager.php | 134 | ||||
-rw-r--r-- | Core/Authorization/Voter/AbstractVoter.php | 117 | ||||
-rw-r--r-- | Core/Authorization/Voter/AuthenticatedVoter.php | 22 | ||||
-rw-r--r-- | Core/Authorization/Voter/ExpressionVoter.php | 32 | ||||
-rw-r--r-- | Core/Authorization/Voter/RoleVoter.php | 20 | ||||
-rw-r--r-- | Core/Authorization/Voter/Voter.php | 22 | ||||
-rw-r--r-- | Core/Authorization/Voter/VoterInterface.php | 26 |
9 files changed, 153 insertions, 274 deletions
diff --git a/Core/Authorization/AccessDecisionManager.php b/Core/Authorization/AccessDecisionManager.php index 7cefef1..e40d906 100644 --- a/Core/Authorization/AccessDecisionManager.php +++ b/Core/Authorization/AccessDecisionManager.php @@ -73,38 +73,6 @@ class AccessDecisionManager implements AccessDecisionManagerInterface } /** - * {@inheritdoc} - */ - public function supportsAttribute($attribute) - { - @trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.', E_USER_DEPRECATED); - - foreach ($this->voters as $voter) { - if ($voter->supportsAttribute($attribute)) { - return true; - } - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function supportsClass($class) - { - @trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.', E_USER_DEPRECATED); - - foreach ($this->voters as $voter) { - if ($voter->supportsClass($class)) { - return true; - } - } - - return false; - } - - /** * Grants access if any voter returns an affirmative response. * * If all voters abstained from voting, the decision will be based on the diff --git a/Core/Authorization/AccessDecisionManagerInterface.php b/Core/Authorization/AccessDecisionManagerInterface.php index d18b5e3..723ef19 100644 --- a/Core/Authorization/AccessDecisionManagerInterface.php +++ b/Core/Authorization/AccessDecisionManagerInterface.php @@ -30,26 +30,4 @@ interface AccessDecisionManagerInterface * @return bool true if the access is granted, false otherwise */ public function decide(TokenInterface $token, array $attributes, $object = null); - - /** - * Checks if the access decision manager supports the given attribute. - * - * @param string $attribute An attribute - * - * @return bool true if this decision manager supports the attribute, false otherwise - * - * @deprecated since version 2.8, to be removed in 3.0. - */ - public function supportsAttribute($attribute); - - /** - * Checks if the access decision manager supports the given class. - * - * @param string $class A class name - * - * @return true if this decision manager can process the class - * - * @deprecated since version 2.8, to be removed in 3.0. - */ - public function supportsClass($class); } diff --git a/Core/Authorization/DebugAccessDecisionManager.php b/Core/Authorization/DebugAccessDecisionManager.php new file mode 100644 index 0000000..aa15443 --- /dev/null +++ b/Core/Authorization/DebugAccessDecisionManager.php @@ -0,0 +1,134 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Authorization; + +use Doctrine\Common\Util\ClassUtils; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; + +/** + * Decorates the original AccessDecisionManager class to log information + * about the security voters and the decisions made by them. + * + * @author Javier Eguiluz <javier.eguiluz@gmail.com> + * + * @internal + */ +class DebugAccessDecisionManager implements AccessDecisionManagerInterface +{ + private $manager; + private $strategy; + private $voters = array(); + private $decisionLog = array(); + + public function __construct(AccessDecisionManagerInterface $manager) + { + $this->manager = $manager; + + if ($this->manager instanceof AccessDecisionManager) { + // The strategy is stored in a private property of the decorated service + $reflection = new \ReflectionProperty(AccessDecisionManager::class, 'strategy'); + $reflection->setAccessible(true); + $this->strategy = $reflection->getValue($manager); + } + } + + /** + * {@inheritdoc} + */ + public function decide(TokenInterface $token, array $attributes, $object = null) + { + $result = $this->manager->decide($token, $attributes, $object); + + $this->decisionLog[] = array( + 'attributes' => $attributes, + 'object' => $this->getStringRepresentation($object), + 'result' => $result, + ); + + return $result; + } + + /** + * {@inheritdoc} + */ + public function setVoters(array $voters) + { + if (!method_exists($this->manager, 'setVoters')) { + return; + } + + $this->voters = $voters; + $this->manager->setVoters($voters); + } + + /** + * @return string + */ + public function getStrategy() + { + // The $strategy property is misleading because it stores the name of its + // method (e.g. 'decideAffirmative') instead of the original strategy name + // (e.g. 'affirmative') + return null === $this->strategy ? '-' : strtolower(substr($this->strategy, 6)); + } + + /** + * @return array + */ + public function getVoters() + { + return $this->voters; + } + + /** + * @return array + */ + public function getDecisionLog() + { + return $this->decisionLog; + } + + /** + * @param mixed $object + * + * @return string + */ + private function getStringRepresentation($object) + { + if (null === $object) { + return 'NULL'; + } + + if (!is_object($object)) { + if (is_bool($object)) { + return sprintf('%s (%s)', gettype($object), $object ? 'true' : 'false'); + } + if (is_scalar($object)) { + return sprintf('%s (%s)', gettype($object), $object); + } + + return gettype($object); + } + + $objectClass = class_exists('Doctrine\Common\Util\ClassUtils') ? ClassUtils::getClass($object) : get_class($object); + + if (method_exists($object, 'getId')) { + $objectAsString = sprintf('ID: %s', $object->getId()); + } elseif (method_exists($object, '__toString')) { + $objectAsString = (string) $object; + } else { + $objectAsString = sprintf('object hash: %s', spl_object_hash($object)); + } + + return sprintf('%s (%s)', $objectClass, $objectAsString); + } +} diff --git a/Core/Authorization/Voter/AbstractVoter.php b/Core/Authorization/Voter/AbstractVoter.php deleted file mode 100644 index 5dcf787..0000000 --- a/Core/Authorization/Voter/AbstractVoter.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Security\Core\Authorization\Voter; - -@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); - -use Symfony\Component\Security\Core\User\UserInterface; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; - -/** - * Abstract Voter implementation that reduces boilerplate code required to create a custom Voter. - * - * @author Roman Marintšenko <inoryy@gmail.com> - * - * @deprecated since version 2.8, to be removed in 3.0. Upgrade to Symfony\Component\Security\Core\Authorization\Voter\Voter instead. - */ -abstract class AbstractVoter implements VoterInterface -{ - /** - * {@inheritdoc} - */ - public function supportsAttribute($attribute) - { - return in_array($attribute, $this->getSupportedAttributes()); - } - - /** - * {@inheritdoc} - */ - public function supportsClass($class) - { - foreach ($this->getSupportedClasses() as $supportedClass) { - if ($supportedClass === $class || is_subclass_of($class, $supportedClass)) { - return true; - } - } - - return false; - } - - /** - * Iteratively check all given attributes by calling isGranted. - * - * This method terminates as soon as it is able to return ACCESS_GRANTED - * If at least one attribute is supported, but access not granted, then ACCESS_DENIED is returned - * Otherwise it will return ACCESS_ABSTAIN - * - * @param TokenInterface $token A TokenInterface instance - * @param object $object The object to secure - * @param array $attributes An array of attributes associated with the method being invoked - * - * @return int either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED - */ - public function vote(TokenInterface $token, $object, array $attributes) - { - if (!$object || !$this->supportsClass(get_class($object))) { - return self::ACCESS_ABSTAIN; - } - - // abstain vote by default in case none of the attributes are supported - $vote = self::ACCESS_ABSTAIN; - - foreach ($attributes as $attribute) { - if (!$this->supportsAttribute($attribute)) { - continue; - } - - // as soon as at least one attribute is supported, default is to deny access - $vote = self::ACCESS_DENIED; - - if ($this->isGranted($attribute, $object, $token->getUser())) { - // grant access as soon as at least one voter returns a positive response - return self::ACCESS_GRANTED; - } - } - - return $vote; - } - - /** - * Return an array of supported classes. This will be called by supportsClass. - * - * @return array an array of supported classes, i.e. array('Acme\DemoBundle\Model\Product') - */ - abstract protected function getSupportedClasses(); - - /** - * Return an array of supported attributes. This will be called by supportsAttribute. - * - * @return array an array of supported attributes, i.e. array('CREATE', 'READ') - */ - abstract protected function getSupportedAttributes(); - - /** - * Perform a single access check operation on a given attribute, object and (optionally) user - * It is safe to assume that $attribute and $object's class pass supportsAttribute/supportsClass - * $user can be one of the following: - * a UserInterface object (fully authenticated user) - * a string (anonymously authenticated user). - * - * @param string $attribute - * @param object $object - * @param UserInterface|string $user - * - * @return bool - */ - abstract protected function isGranted($attribute, $object, $user = null); -} diff --git a/Core/Authorization/Voter/AuthenticatedVoter.php b/Core/Authorization/Voter/AuthenticatedVoter.php index 5847e0d..dc1407b 100644 --- a/Core/Authorization/Voter/AuthenticatedVoter.php +++ b/Core/Authorization/Voter/AuthenticatedVoter.php @@ -44,27 +44,13 @@ class AuthenticatedVoter implements VoterInterface /** * {@inheritdoc} */ - public function supportsAttribute($attribute) - { - return null !== $attribute && (self::IS_AUTHENTICATED_FULLY === $attribute || self::IS_AUTHENTICATED_REMEMBERED === $attribute || self::IS_AUTHENTICATED_ANONYMOUSLY === $attribute); - } - - /** - * {@inheritdoc} - */ - public function supportsClass($class) - { - return true; - } - - /** - * {@inheritdoc} - */ - public function vote(TokenInterface $token, $object, array $attributes) + public function vote(TokenInterface $token, $subject, array $attributes) { $result = VoterInterface::ACCESS_ABSTAIN; foreach ($attributes as $attribute) { - if (!$this->supportsAttribute($attribute)) { + if (null === $attribute || (self::IS_AUTHENTICATED_FULLY !== $attribute + && self::IS_AUTHENTICATED_REMEMBERED !== $attribute + && self::IS_AUTHENTICATED_ANONYMOUSLY !== $attribute)) { continue; } diff --git a/Core/Authorization/Voter/ExpressionVoter.php b/Core/Authorization/Voter/ExpressionVoter.php index 96a7ece..5fd8b83 100644 --- a/Core/Authorization/Voter/ExpressionVoter.php +++ b/Core/Authorization/Voter/ExpressionVoter.php @@ -52,33 +52,17 @@ class ExpressionVoter implements VoterInterface /** * {@inheritdoc} */ - public function supportsAttribute($attribute) - { - return $attribute instanceof Expression; - } - - /** - * {@inheritdoc} - */ - public function supportsClass($class) - { - return true; - } - - /** - * {@inheritdoc} - */ - public function vote(TokenInterface $token, $object, array $attributes) + public function vote(TokenInterface $token, $subject, array $attributes) { $result = VoterInterface::ACCESS_ABSTAIN; $variables = null; foreach ($attributes as $attribute) { - if (!$this->supportsAttribute($attribute)) { + if (!$attribute instanceof Expression) { continue; } if (null === $variables) { - $variables = $this->getVariables($token, $object); + $variables = $this->getVariables($token, $subject); } $result = VoterInterface::ACCESS_DENIED; @@ -90,7 +74,7 @@ class ExpressionVoter implements VoterInterface return $result; } - private function getVariables(TokenInterface $token, $object) + private function getVariables(TokenInterface $token, $subject) { if (null !== $this->roleHierarchy) { $roles = $this->roleHierarchy->getReachableRoles($token->getRoles()); @@ -101,8 +85,8 @@ class ExpressionVoter implements VoterInterface $variables = array( 'token' => $token, 'user' => $token->getUser(), - 'object' => $object, - 'subject' => $object, + 'object' => $subject, + 'subject' => $subject, 'roles' => array_map(function ($role) { return $role->getRole(); }, $roles), 'trust_resolver' => $this->trustResolver, ); @@ -110,8 +94,8 @@ class ExpressionVoter implements VoterInterface // this is mainly to propose a better experience when the expression is used // in an access control rule, as the developer does not know that it's going // to be handled by this voter - if ($object instanceof Request) { - $variables['request'] = $object; + if ($subject instanceof Request) { + $variables['request'] = $subject; } return $variables; diff --git a/Core/Authorization/Voter/RoleVoter.php b/Core/Authorization/Voter/RoleVoter.php index 539dcda..d5f3176 100644 --- a/Core/Authorization/Voter/RoleVoter.php +++ b/Core/Authorization/Voter/RoleVoter.php @@ -36,23 +36,7 @@ class RoleVoter implements VoterInterface /** * {@inheritdoc} */ - public function supportsAttribute($attribute) - { - return is_string($attribute) && 0 === strpos($attribute, $this->prefix); - } - - /** - * {@inheritdoc} - */ - public function supportsClass($class) - { - return true; - } - - /** - * {@inheritdoc} - */ - public function vote(TokenInterface $token, $object, array $attributes) + public function vote(TokenInterface $token, $subject, array $attributes) { $result = VoterInterface::ACCESS_ABSTAIN; $roles = $this->extractRoles($token); @@ -62,7 +46,7 @@ class RoleVoter implements VoterInterface $attribute = $attribute->getRole(); } - if (!$this->supportsAttribute($attribute)) { + if (!is_string($attribute) || 0 !== strpos($attribute, $this->prefix)) { continue; } diff --git a/Core/Authorization/Voter/Voter.php b/Core/Authorization/Voter/Voter.php index 2396b1e..0641486 100644 --- a/Core/Authorization/Voter/Voter.php +++ b/Core/Authorization/Voter/Voter.php @@ -24,36 +24,20 @@ abstract class Voter implements VoterInterface /** * {@inheritdoc} */ - public function supportsAttribute($attribute) - { - throw new \BadMethodCallException('supportsAttribute method is deprecated since version 2.8, to be removed in 3.0'); - } - - /** - * {@inheritdoc} - */ - public function supportsClass($class) - { - throw new \BadMethodCallException('supportsClass method is deprecated since version 2.8, to be removed in 3.0'); - } - - /** - * {@inheritdoc} - */ - public function vote(TokenInterface $token, $object, array $attributes) + public function vote(TokenInterface $token, $subject, array $attributes) { // abstain vote by default in case none of the attributes are supported $vote = self::ACCESS_ABSTAIN; foreach ($attributes as $attribute) { - if (!$this->supports($attribute, $object)) { + if (!$this->supports($attribute, $subject)) { continue; } // as soon as at least one attribute is supported, default is to deny access $vote = self::ACCESS_DENIED; - if ($this->voteOnAttribute($attribute, $object, $token)) { + if ($this->voteOnAttribute($attribute, $subject, $token)) { // grant access as soon as at least one attribute returns a positive response return self::ACCESS_GRANTED; } diff --git a/Core/Authorization/Voter/VoterInterface.php b/Core/Authorization/Voter/VoterInterface.php index 91ddc1f..4bb7367 100644 --- a/Core/Authorization/Voter/VoterInterface.php +++ b/Core/Authorization/Voter/VoterInterface.php @@ -25,38 +25,16 @@ interface VoterInterface const ACCESS_DENIED = -1; /** - * Checks if the voter supports the given attribute. - * - * @param mixed $attribute An attribute (usually the attribute name string) - * - * @return bool true if this Voter supports the attribute, false otherwise - * - * @deprecated since version 2.8, to be removed in 3.0. - */ - public function supportsAttribute($attribute); - - /** - * Checks if the voter supports the given class. - * - * @param string $class A class name - * - * @return bool true if this Voter can process the class - * - * @deprecated since version 2.8, to be removed in 3.0. - */ - public function supportsClass($class); - - /** * Returns the vote for the given parameters. * * This method must return one of the following constants: * ACCESS_GRANTED, ACCESS_DENIED, or ACCESS_ABSTAIN. * * @param TokenInterface $token A TokenInterface instance - * @param object|null $object The object to secure + * @param mixed $subject The subject to secure * @param array $attributes An array of attributes associated with the method being invoked * * @return int either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED */ - public function vote(TokenInterface $token, $object, array $attributes); + public function vote(TokenInterface $token, $subject, array $attributes); } |