Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 5733fa5

Browse filesBrowse files
committed
Implement ADM strategies as dedicated classes
1 parent 44042f6 commit 5733fa5
Copy full SHA for 5733fa5

24 files changed

+784
-169
lines changed

‎UPGRADE-5.4.md

Copy file name to clipboardExpand all lines: UPGRADE-5.4.md
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,6 @@ Security
141141
}
142142
}
143143
```
144+
* Deprecate passing the strategy as string to `AccessDecisionManager`,
145+
pass an instance of `AccessDecisionStrategyInterface` instead
146+
* Flag `AccessDecisionManager` as `@final`

‎UPGRADE-6.0.md

Copy file name to clipboardExpand all lines: UPGRADE-6.0.md
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,8 @@ Security
388388
}
389389
}
390390
```
391+
* `AccessDecisionManager` does not accept strings as strategy anymore,
392+
pass an instance of `AccessDecisionStrategyInterface` instead
391393

392394
SecurityBundle
393395
--------------

‎src/Symfony/Bundle/SecurityBundle/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ CHANGELOG
1515
factories instead.
1616
* Deprecate the `always_authenticate_before_granting` option
1717
* Display the roles of the logged-in user in the Web Debug Toolbar
18+
* Add the `security.access_decision_manager.strategy_service` option
1819

1920
5.3
2021
---

‎src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php
+31-15Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
1919
use Symfony\Component\Config\Definition\ConfigurationInterface;
2020
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
21-
use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
2221
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
2322
use Symfony\Component\Security\Http\Event\LogoutEvent;
2423
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
@@ -30,6 +29,15 @@
3029
*/
3130
class MainConfiguration implements ConfigurationInterface
3231
{
32+
/** @internal */
33+
public const STRATEGY_AFFIRMATIVE = 'affirmative';
34+
/** @internal */
35+
public const STRATEGY_CONSENSUS = 'consensus';
36+
/** @internal */
37+
public const STRATEGY_UNANIMOUS = 'unanimous';
38+
/** @internal */
39+
public const STRATEGY_PRIORITY = 'priority';
40+
3341
private $factories;
3442
private $userProviderFactories;
3543

@@ -65,14 +73,18 @@ public function getConfigTreeBuilder()
6573
return true;
6674
}
6775

68-
if (!isset($v['access_decision_manager']['strategy']) && !isset($v['access_decision_manager']['service'])) {
76+
if (!isset($v['access_decision_manager']['strategy'])
77+
&& !isset($v['access_decision_manager']['service'])
78+
&& !isset($v['access_decision_manager']['strategy_service'])
79+
&& !isset($v['access_decision_manager']['strategy-service'])
80+
) {
6981
return true;
7082
}
7183

7284
return false;
7385
})
7486
->then(function ($v) {
75-
$v['access_decision_manager']['strategy'] = AccessDecisionManager::STRATEGY_AFFIRMATIVE;
87+
$v['access_decision_manager']['strategy'] = self::STRATEGY_AFFIRMATIVE;
7688

7789
return $v;
7890
})
@@ -114,13 +126,22 @@ public function getConfigTreeBuilder()
114126
->values($this->getAccessDecisionStrategies())
115127
->end()
116128
->scalarNode('service')->end()
129+
->scalarNode('strategy_service')->end()
117130
->booleanNode('allow_if_all_abstain')->defaultFalse()->end()
118131
->booleanNode('allow_if_equal_granted_denied')->defaultTrue()->end()
119132
->end()
120133
->validate()
121-
->ifTrue(function ($v) { return isset($v['strategy']) && isset($v['service']); })
134+
->ifTrue(function ($v) { return isset($v['strategy'], $v['service']); })
122135
->thenInvalid('"strategy" and "service" cannot be used together.')
123136
->end()
137+
->validate()
138+
->ifTrue(function ($v) { return isset($v['strategy'], $v['strategy_service']); })
139+
->thenInvalid('"strategy" and "strategy_service" cannot be used together.')
140+
->end()
141+
->validate()
142+
->ifTrue(function ($v) { return isset($v['service'], $v['strategy_service']); })
143+
->thenInvalid('"service" and "strategy_service" cannot be used together.')
144+
->end()
124145
->end()
125146
->end()
126147
;
@@ -507,18 +528,13 @@ private function addPasswordHashersSection(ArrayNodeDefinition $rootNode)
507528
->end();
508529
}
509530

510-
private function getAccessDecisionStrategies()
531+
private function getAccessDecisionStrategies(): array
511532
{
512-
$strategies = [
513-
AccessDecisionManager::STRATEGY_AFFIRMATIVE,
514-
AccessDecisionManager::STRATEGY_CONSENSUS,
515-
AccessDecisionManager::STRATEGY_UNANIMOUS,
533+
return [
534+
self::STRATEGY_AFFIRMATIVE,
535+
self::STRATEGY_CONSENSUS,
536+
self::STRATEGY_UNANIMOUS,
537+
self::STRATEGY_PRIORITY,
516538
];
517-
518-
if (\defined(AccessDecisionManager::class.'::STRATEGY_PRIORITY')) {
519-
$strategies[] = AccessDecisionManager::STRATEGY_PRIORITY;
520-
}
521-
522-
return $strategies;
523539
}
524540
}

‎src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
+32-3Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
use Symfony\Component\PasswordHasher\Hasher\Pbkdf2PasswordHasher;
3939
use Symfony\Component\PasswordHasher\Hasher\PlaintextPasswordHasher;
4040
use Symfony\Component\PasswordHasher\Hasher\SodiumPasswordHasher;
41+
use Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeStrategy;
42+
use Symfony\Component\Security\Core\Authorization\Strategy\ConsensusStrategy;
43+
use Symfony\Component\Security\Core\Authorization\Strategy\PriorityStrategy;
44+
use Symfony\Component\Security\Core\Authorization\Strategy\UnanimousStrategy;
4145
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
4246
use Symfony\Component\Security\Core\Encoder\NativePasswordEncoder;
4347
use Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder;
@@ -144,12 +148,18 @@ public function load(array $configs, ContainerBuilder $container)
144148

145149
if (isset($config['access_decision_manager']['service'])) {
146150
$container->setAlias('security.access.decision_manager', $config['access_decision_manager']['service']);
151+
} elseif (isset($config['access_decision_manager']['strategy_service'])) {
152+
$container
153+
->getDefinition('security.access.decision_manager')
154+
->addArgument(new Reference($config['access_decision_manager']['strategy_service']));
147155
} else {
148156
$container
149157
->getDefinition('security.access.decision_manager')
150-
->addArgument($config['access_decision_manager']['strategy'])
151-
->addArgument($config['access_decision_manager']['allow_if_all_abstain'])
152-
->addArgument($config['access_decision_manager']['allow_if_equal_granted_denied']);
158+
->addArgument($this->createStrategyDefinition(
159+
$config['access_decision_manager']['strategy'],
160+
$config['access_decision_manager']['allow_if_all_abstain'],
161+
$config['access_decision_manager']['allow_if_equal_granted_denied']
162+
));
153163
}
154164

155165
$container->setParameter('security.access.always_authenticate_before_granting', $config['always_authenticate_before_granting']);
@@ -190,6 +200,25 @@ public function load(array $configs, ContainerBuilder $container)
190200
->addTag('security.voter');
191201
}
192202

203+
/**
204+
* @throws \InvalidArgumentException if the $strategy is invalid
205+
*/
206+
private function createStrategyDefinition(string $strategy, bool $allowIfAllAbstainDecisions, bool $allowIfEqualGrantedDeniedDecisions): Definition
207+
{
208+
switch ($strategy) {
209+
case MainConfiguration::STRATEGY_AFFIRMATIVE:
210+
return new Definition(AffirmativeStrategy::class, [$allowIfAllAbstainDecisions]);
211+
case MainConfiguration::STRATEGY_CONSENSUS:
212+
return new Definition(ConsensusStrategy::class, [$allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions]);
213+
case MainConfiguration::STRATEGY_UNANIMOUS:
214+
return new Definition(UnanimousStrategy::class, [$allowIfAllAbstainDecisions]);
215+
case MainConfiguration::STRATEGY_PRIORITY:
216+
return new Definition(PriorityStrategy::class, [$allowIfAllAbstainDecisions]);
217+
}
218+
219+
throw new \InvalidArgumentException(sprintf('The strategy "%s" is not supported.', $strategy));
220+
}
221+
193222
private function createRoleHierarchy(array $config, ContainerBuilder $container)
194223
{
195224
if (!isset($config['role_hierarchy']) || 0 === \count($config['role_hierarchy'])) {

‎src/Symfony/Bundle/SecurityBundle/Resources/config/schema/security-1.0.xsd

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Resources/config/schema/security-1.0.xsd
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
<xsd:complexType name="access_decision_manager">
6464
<xsd:attribute name="strategy" type="access_decision_manager_strategy" />
6565
<xsd:attribute name="service" type="xsd:string" />
66+
<xsd:attribute name="strategy-service" type="xsd:string" />
6667
<xsd:attribute name="allow-if-all-abstain" type="xsd:boolean" />
6768
<xsd:attribute name="allow-if-equal-granted-denied" type="xsd:boolean" />
6869
</xsd:complexType>

‎src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
+14-4Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
1818
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
1919
use Symfony\Component\DependencyInjection\ContainerBuilder;
20+
use Symfony\Component\DependencyInjection\Definition;
2021
use Symfony\Component\DependencyInjection\Reference;
2122
use Symfony\Component\PasswordHasher\Hasher\NativePasswordHasher;
2223
use Symfony\Component\PasswordHasher\Hasher\Pbkdf2PasswordHasher;
2324
use Symfony\Component\PasswordHasher\Hasher\PlaintextPasswordHasher;
2425
use Symfony\Component\PasswordHasher\Hasher\SodiumPasswordHasher;
2526
use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
27+
use Symfony\Component\Security\Core\Authorization\Strategy\AffirmativeStrategy;
2628
use Symfony\Component\Security\Core\Encoder\NativePasswordEncoder;
2729
use Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder;
2830
use Symfony\Component\Security\Http\Authentication\AuthenticatorManager;
@@ -1046,7 +1048,7 @@ public function testDefaultAccessDecisionManagerStrategyIsAffirmative()
10461048
{
10471049
$container = $this->getContainer('access_decision_manager_default_strategy');
10481050

1049-
$this->assertSame(AccessDecisionManager::STRATEGY_AFFIRMATIVE, $container->getDefinition('security.access.decision_manager')->getArgument(1), 'Default vote strategy is affirmative');
1051+
$this->assertEquals((new Definition(AffirmativeStrategy::class, [false])), $container->getDefinition('security.access.decision_manager')->getArgument(1), 'Default vote strategy is affirmative');
10501052
}
10511053

10521054
public function testCustomAccessDecisionManagerService()
@@ -1069,9 +1071,17 @@ public function testAccessDecisionManagerOptionsAreNotOverriddenByImplicitStrate
10691071

10701072
$accessDecisionManagerDefinition = $container->getDefinition('security.access.decision_manager');
10711073

1072-
$this->assertSame(AccessDecisionManager::STRATEGY_AFFIRMATIVE, $accessDecisionManagerDefinition->getArgument(1));
1073-
$this->assertTrue($accessDecisionManagerDefinition->getArgument(2));
1074-
$this->assertFalse($accessDecisionManagerDefinition->getArgument(3));
1074+
$this->assertEquals((new Definition(AffirmativeStrategy::class, [true])), $accessDecisionManagerDefinition->getArgument(1));
1075+
}
1076+
1077+
public function testAccessDecisionManagerWithStrategyService()
1078+
{
1079+
$container = $this->getContainer('access_decision_manager_strategy_service');
1080+
1081+
$accessDecisionManagerDefinition = $container->getDefinition('security.access.decision_manager');
1082+
1083+
$this->assertEquals(AccessDecisionManager::class, $accessDecisionManagerDefinition->getClass());
1084+
$this->assertEquals(new Reference('app.custom_access_decision_strategy'), $accessDecisionManagerDefinition->getArgument(1));
10751085
}
10761086

10771087
public function testFirewallUndefinedUserProvider()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
$container->loadFromExtension('security', [
4+
'enable_authenticator_manager' => true,
5+
'access_decision_manager' => [
6+
'strategy_service' => 'app.custom_access_decision_strategy',
7+
],
8+
'providers' => [
9+
'default' => [
10+
'memory' => [
11+
'users' => [
12+
'foo' => ['password' => 'foo', 'roles' => 'ROLE_USER'],
13+
],
14+
],
15+
],
16+
],
17+
'firewalls' => [
18+
'simple' => ['pattern' => '/login', 'security' => false],
19+
],
20+
]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<srv:container xmlns="http://symfony.com/schema/dic/security"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:srv="http://symfony.com/schema/dic/services"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services
6+
https://symfony.com/schema/dic/services/services-1.0.xsd
7+
http://symfony.com/schema/dic/security
8+
https://symfony.com/schema/dic/security/security-1.0.xsd">
9+
10+
<config enable-authenticator-manager="true">
11+
<access-decision-manager strategy-service="app.custom_access_decision_strategy" />
12+
13+
<provider name="default">
14+
<memory>
15+
<user identifier="foo" password="foo" roles="ROLE_USER" />
16+
</memory>
17+
</provider>
18+
19+
<firewall name="simple" pattern="/login" security="false" />
20+
</config>
21+
</srv:container>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
security:
2+
enable_authenticator_manager: true
3+
access_decision_manager:
4+
strategy_service: app.custom_access_decision_strategy
5+
providers:
6+
default:
7+
memory:
8+
users:
9+
foo: { password: foo, roles: ROLE_USER }
10+
firewalls:
11+
simple: { pattern: /login, security: false }

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.