summaryrefslogtreecommitdiffstats
path: root/Authorization/AccessDecisionManager.php
diff options
context:
space:
mode:
Diffstat (limited to 'Authorization/AccessDecisionManager.php')
-rw-r--r--Authorization/AccessDecisionManager.php237
1 files changed, 237 insertions, 0 deletions
diff --git a/Authorization/AccessDecisionManager.php b/Authorization/AccessDecisionManager.php
new file mode 100644
index 0000000..d458b89
--- /dev/null
+++ b/Authorization/AccessDecisionManager.php
@@ -0,0 +1,237 @@
+<?php
+
+namespace Symfony\Component\Security\Authorization;
+
+use Symfony\Component\Security\Authorization\Voter\VoterInterface;
+use Symfony\Component\Security\Authentication\Token\TokenInterface;
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * AccessDecisionManager is the base class for all access decision managers
+ * that use decision voters.
+ *
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ */
+class AccessDecisionManager implements AccessDecisionManagerInterface
+{
+ protected $voters;
+ protected $allowIfAllAbstainDecisions;
+ protected $allowIfEqualGrantedDeniedDecisions;
+ protected $strategy;
+
+ /**
+ * Constructor.
+ *
+ * @param VoterInterface[] $voters An array of VoterInterface instances
+ * @param string $strategy The vote strategy
+ * @param Boolean $allowIfAllAbstainDecisions Whether to grant access if all voters abstained or not
+ */
+ public function __construct(array $voters = array(), $strategy = 'affirmative', $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true)
+ {
+ $this->voters = $voters;
+ $this->strategy = 'decide'.ucfirst($strategy);
+ $this->allowIfAllAbstainDecisions = (Boolean) $allowIfAllAbstainDecisions;
+ $this->allowIfEqualGrantedDeniedDecisions = (Boolean) $allowIfEqualGrantedDeniedDecisions;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function decide(TokenInterface $token, array $attributes, $object = null)
+ {
+ return $this->{$this->strategy}($token, $attributes, $object);
+ }
+
+ /**
+ * Returns all voters.
+ *
+ * @return VoterInterface[] $voters An array of VoterInterface instances
+ */
+ public function getVoters()
+ {
+ return $this->voters;
+ }
+
+ /**
+ * Sets voters.
+ *
+ * @param VoterInterface[] $voters An array of VoterInterface instances
+ */
+ public function setVoters(array $voters)
+ {
+ if (!count($voters)) {
+ throw new \LogicException('You must have at least one voter.');
+ }
+
+ $this->voters = array();
+ foreach ($voters as $voter) {
+ $this->addVoter($voter);
+ }
+ }
+
+ /**
+ * Adds a voter.
+ *
+ * @param VoterInterface $voter A VoterInterface instance
+ */
+ public function addVoter(VoterInterface $voter)
+ {
+ $this->voters[] = $voter;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function supportsAttribute($attribute)
+ {
+ foreach ($this->voters as $voter) {
+ if ($voter->supportsAttribute($attribute)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function supportsClass($class) {
+ 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
+ * allowIfAllAbstainDecisions property value (defaults to false).
+ */
+ protected function decideAffirmative(TokenInterface $token, array $attributes, $object = null)
+ {
+ $deny = 0;
+ foreach ($this->voters as $voter) {
+ $result = $voter->vote($token, $object, $attributes);
+ switch ($result) {
+ case VoterInterface::ACCESS_GRANTED:
+ return true;
+
+ case VoterInterface::ACCESS_DENIED:
+ ++$deny;
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ($deny > 0) {
+ return false;
+ }
+
+ return $this->allowIfAllAbstainDecisions;
+ }
+
+ /**
+ * Grants access if there is consensus of granted against denied responses.
+ *
+ * Consensus means majority-rule (ignoring abstains) rather than unanimous agreement (ignoring abstains).
+ * If you require unanimity, see UnanimousBased.
+ *
+ * If there were an equal number of grant and deny votes, the decision will be based on the
+ * allowIfEqualGrantedDeniedDecisions property value (defaults to true).
+ *
+ * If all voters abstained from voting, the decision will be based on the
+ * allowIfAllAbstainDecisions property value (defaults to false).
+ */
+ public function decideConsensus(TokenInterface $token, array $attributes, $object = null)
+ {
+ $grant = 0;
+ $deny = 0;
+ $abstain = 0;
+ foreach ($this->voters as $voter) {
+ $result = $voter->vote($token, $object, $attributes);
+
+ switch ($result) {
+ case VoterInterface::ACCESS_GRANTED:
+ ++$grant;
+
+ break;
+
+ case VoterInterface::ACCESS_DENIED:
+ ++$deny;
+
+ break;
+
+ default:
+ ++$abstain;
+
+ break;
+ }
+ }
+
+ if ($grant > $deny) {
+ return;
+ }
+
+ if ($deny > $grant) {
+ return false;
+ }
+
+ if ($grant == $deny && $grant != 0) {
+ return $this->allowIfEqualGrantedDeniedDecisions;
+ }
+
+ return $this->allowIfAllAbstainDecisions;
+ }
+
+ /**
+ * Grants access if only grant (or abstain) votes were received.
+ *
+ * If all voters abstained from voting, the decision will be based on the
+ * allowIfAllAbstainDecisions property value (defaults to false).
+ */
+ public function decideUnanimous(TokenInterface $token, array $attributes, $object = null)
+ {
+ $grant = 0;
+ foreach ($attributes as $attribute) {
+ foreach ($this->voters as $voter) {
+ $result = $voter->vote($token, $object, array($attribute));
+
+ switch ($result) {
+ case VoterInterface::ACCESS_GRANTED:
+ ++$grant;
+
+ break;
+
+ case VoterInterface::ACCESS_DENIED:
+ return false;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ // no deny votes
+ if ($grant > 0) {
+ return true;
+ }
+
+ return $this->allowIfAllAbstainDecisions;
+ }
+}