Added access decision strategy to respect voter priority

This commit is contained in:
Andreas Schempp 2019-11-23 13:28:53 +01:00 committed by Robin Chalas
parent dab6732f39
commit 0b8028a0ec
5 changed files with 76 additions and 1 deletions

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
5.1.0
-----
* Added security configuration for priority-based access decision strategy
5.0.0
-----

View File

@ -76,7 +76,7 @@ class MainConfiguration implements ConfigurationInterface
->addDefaultsIfNotSet()
->children()
->enumNode('strategy')
->values([AccessDecisionManager::STRATEGY_AFFIRMATIVE, AccessDecisionManager::STRATEGY_CONSENSUS, AccessDecisionManager::STRATEGY_UNANIMOUS])
->values($this->getAccessDecisionStrategies())
->end()
->scalarNode('service')->end()
->booleanNode('allow_if_all_abstain')->defaultFalse()->end()
@ -386,4 +386,19 @@ class MainConfiguration implements ConfigurationInterface
->end()
;
}
private function getAccessDecisionStrategies()
{
$strategies = [
AccessDecisionManager::STRATEGY_AFFIRMATIVE,
AccessDecisionManager::STRATEGY_CONSENSUS,
AccessDecisionManager::STRATEGY_UNANIMOUS,
];
if (\defined(AccessDecisionManager::class.'::STRATEGY_PRIORITY')) {
$strategies[] = AccessDecisionManager::STRATEGY_PRIORITY;
}
return $strategies;
}
}

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
5.1.0
-----
* Added access decision strategy to override access decisions by voter service priority
5.0.0
-----

View File

@ -26,6 +26,7 @@ class AccessDecisionManager implements AccessDecisionManagerInterface
const STRATEGY_AFFIRMATIVE = 'affirmative';
const STRATEGY_CONSENSUS = 'consensus';
const STRATEGY_UNANIMOUS = 'unanimous';
const STRATEGY_PRIORITY = 'priority';
private $voters;
private $strategy;
@ -181,4 +182,28 @@ class AccessDecisionManager implements AccessDecisionManagerInterface
return $this->allowIfAllAbstainDecisions;
}
/**
* Grant or deny access depending on the first voter that does not abstain.
* The priority of voters can be used to overrule a decision.
*
* If all voters abstained from voting, the decision will be based on the
* allowIfAllAbstainDecisions property value (defaults to false).
*/
private function decidePriority(TokenInterface $token, array $attributes, $object = null)
{
foreach ($this->voters as $voter) {
$result = $voter->vote($token, $object, $attributes);
if (VoterInterface::ACCESS_GRANTED === $result) {
return true;
}
if (VoterInterface::ACCESS_DENIED === $result) {
return false;
}
}
return $this->allowIfAllAbstainDecisions;
}
}

View File

@ -66,6 +66,31 @@ class AccessDecisionManagerTest extends TestCase
[AccessDecisionManager::STRATEGY_UNANIMOUS, $this->getVoters(0, 0, 2), false, true, false],
[AccessDecisionManager::STRATEGY_UNANIMOUS, $this->getVoters(0, 0, 2), true, true, true],
// priority
[AccessDecisionManager::STRATEGY_PRIORITY, [
$this->getVoter(VoterInterface::ACCESS_ABSTAIN),
$this->getVoter(VoterInterface::ACCESS_GRANTED),
$this->getVoter(VoterInterface::ACCESS_DENIED),
$this->getVoter(VoterInterface::ACCESS_DENIED),
], true, true, true],
[AccessDecisionManager::STRATEGY_PRIORITY, [
$this->getVoter(VoterInterface::ACCESS_ABSTAIN),
$this->getVoter(VoterInterface::ACCESS_DENIED),
$this->getVoter(VoterInterface::ACCESS_GRANTED),
$this->getVoter(VoterInterface::ACCESS_GRANTED),
], true, true, false],
[AccessDecisionManager::STRATEGY_PRIORITY, [
$this->getVoter(VoterInterface::ACCESS_ABSTAIN),
$this->getVoter(VoterInterface::ACCESS_ABSTAIN),
], false, true, false],
[AccessDecisionManager::STRATEGY_PRIORITY, [
$this->getVoter(VoterInterface::ACCESS_ABSTAIN),
$this->getVoter(VoterInterface::ACCESS_ABSTAIN),
], true, true, true],
];
}