diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php
index c2bcb7d0e3..6b23e29958 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php
@@ -59,6 +59,26 @@ class MainConfiguration implements ConfigurationInterface
$rootNode = $tb->root('security');
$rootNode
+ ->beforeNormalization()
+ ->ifTrue(function ($v) {
+ if (!isset($v['access_decision_manager'])) {
+ return true;
+ }
+
+ if (!isset($v['access_decision_manager']['strategy']) && !isset($v['access_decision_manager']['service'])) {
+ return true;
+ }
+
+ return false;
+ })
+ ->then(function ($v) {
+ $v['access_decision_manager'] = array(
+ 'strategy' => AccessDecisionManager::STRATEGY_AFFIRMATIVE,
+ );
+
+ return $v;
+ })
+ ->end()
->children()
->scalarNode('access_denied_url')->defaultNull()->example('/foo/error403')->end()
->enumNode('session_fixation_strategy')
@@ -73,11 +93,15 @@ class MainConfiguration implements ConfigurationInterface
->children()
->enumNode('strategy')
->values(array(AccessDecisionManager::STRATEGY_AFFIRMATIVE, AccessDecisionManager::STRATEGY_CONSENSUS, AccessDecisionManager::STRATEGY_UNANIMOUS))
- ->defaultValue(AccessDecisionManager::STRATEGY_AFFIRMATIVE)
->end()
+ ->scalarNode('service')->end()
->booleanNode('allow_if_all_abstain')->defaultFalse()->end()
->booleanNode('allow_if_equal_granted_denied')->defaultTrue()->end()
->end()
+ ->validate()
+ ->ifTrue(function ($v) { return isset($v['strategy']) && isset($v['service']); })
+ ->thenInvalid('"strategy" and "service" cannot be used together.')
+ ->end()
->end()
->end()
;
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
index ba8a528008..226b197a5a 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
@@ -83,12 +83,17 @@ class SecurityExtension extends Extension
$container->setParameter('security.access.denied_url', $config['access_denied_url']);
$container->setParameter('security.authentication.manager.erase_credentials', $config['erase_credentials']);
$container->setParameter('security.authentication.session_strategy.strategy', $config['session_fixation_strategy']);
- $container
- ->getDefinition('security.access.decision_manager')
- ->addArgument($config['access_decision_manager']['strategy'])
- ->addArgument($config['access_decision_manager']['allow_if_all_abstain'])
- ->addArgument($config['access_decision_manager']['allow_if_equal_granted_denied'])
- ;
+
+ if (isset($config['access_decision_manager']['service'])) {
+ $container->setAlias('security.access.decision_manager', $config['access_decision_manager']['service']);
+ } else {
+ $container
+ ->getDefinition('security.access.decision_manager')
+ ->addArgument($config['access_decision_manager']['strategy'])
+ ->addArgument($config['access_decision_manager']['allow_if_all_abstain'])
+ ->addArgument($config['access_decision_manager']['allow_if_equal_granted_denied']);
+ }
+
$container->setParameter('security.access.always_authenticate_before_granting', $config['always_authenticate_before_granting']);
$container->setParameter('security.authentication.hide_user_not_found', $config['hide_user_not_found']);
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
index aa67377ce5..6bfe37efd7 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
@@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\Reference;
use Symfony\Bundle\SecurityBundle\SecurityBundle;
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
abstract class CompleteConfigurationTest extends TestCase
{
@@ -357,6 +358,29 @@ abstract class CompleteConfigurationTest extends TestCase
$this->assertTrue($this->getContainer('remember_me_options')->has('security.console.user_password_encoder_command'));
}
+ public function testDefaultAccessDecisionManagerStrategyIsAffirmative()
+ {
+ $container = $this->getContainer('access_decision_manager_default_strategy');
+
+ $this->assertSame(AccessDecisionManager::STRATEGY_AFFIRMATIVE, $container->getDefinition('security.access.decision_manager')->getArgument(1), 'Default vote strategy is affirmative');
+ }
+
+ public function testCustomAccessDecisionManagerService()
+ {
+ $container = $this->getContainer('access_decision_manager_service');
+
+ $this->assertSame('app.access_decision_manager', (string) $container->getAlias('security.access.decision_manager'), 'The custom access decision manager service is aliased');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
+ * @expectedExceptionMessage "strategy" and "service" cannot be used together.
+ */
+ public function testAccessDecisionManagerServiceAndStrategyCannotBeUsedAtTheSameTime()
+ {
+ $container = $this->getContainer('access_decision_manager_service_and_strategy');
+ }
+
protected function getContainer($file)
{
$file = $file.'.'.$this->getFileExtension();
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_default_strategy.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_default_strategy.php
new file mode 100644
index 0000000000..d06fc3e686
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_default_strategy.php
@@ -0,0 +1,16 @@
+loadFromExtension('security', array(
+ 'providers' => array(
+ 'default' => array(
+ 'memory' => array(
+ 'users' => array(
+ 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'),
+ ),
+ ),
+ ),
+ ),
+ 'firewalls' => array(
+ 'simple' => array('pattern' => '/login', 'security' => false),
+ ),
+));
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service.php
new file mode 100644
index 0000000000..29db539362
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service.php
@@ -0,0 +1,19 @@
+loadFromExtension('security', array(
+ 'access_decision_manager' => array(
+ 'service' => 'app.access_decision_manager',
+ ),
+ 'providers' => array(
+ 'default' => array(
+ 'memory' => array(
+ 'users' => array(
+ 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'),
+ ),
+ ),
+ ),
+ ),
+ 'firewalls' => array(
+ 'simple' => array('pattern' => '/login', 'security' => false),
+ ),
+));
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service_and_strategy.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service_and_strategy.php
new file mode 100644
index 0000000000..f7175e21f6
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service_and_strategy.php
@@ -0,0 +1,20 @@
+loadFromExtension('security', array(
+ 'access_decision_manager' => array(
+ 'service' => 'app.access_decision_manager',
+ 'strategy' => 'affirmative',
+ ),
+ 'providers' => array(
+ 'default' => array(
+ 'memory' => array(
+ 'users' => array(
+ 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'),
+ ),
+ ),
+ ),
+ ),
+ 'firewalls' => array(
+ 'simple' => array('pattern' => '/login', 'security' => false),
+ ),
+));
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_default_strategy.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_default_strategy.xml
new file mode 100644
index 0000000000..6c267a2e77
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_default_strategy.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service.xml
new file mode 100644
index 0000000000..4e67e168c8
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service_and_strategy.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service_and_strategy.xml
new file mode 100644
index 0000000000..dbadce4fa7
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service_and_strategy.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_default_strategy.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_default_strategy.yml
new file mode 100644
index 0000000000..f7fb5adc2c
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_default_strategy.yml
@@ -0,0 +1,8 @@
+security:
+ providers:
+ default:
+ memory:
+ users:
+ foo: { password: foo, roles: ROLE_USER }
+ firewalls:
+ simple: { pattern: /login, security: false }
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service.yml
new file mode 100644
index 0000000000..7ef3d8d93c
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service.yml
@@ -0,0 +1,10 @@
+security:
+ access_decision_manager:
+ service: app.access_decision_manager
+ providers:
+ default:
+ memory:
+ users:
+ foo: { password: foo, roles: ROLE_USER }
+ firewalls:
+ simple: { pattern: /login, security: false }
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service_and_strategy.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service_and_strategy.yml
new file mode 100644
index 0000000000..bd38b21ef3
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service_and_strategy.yml
@@ -0,0 +1,11 @@
+security:
+ access_decision_manager:
+ service: app.access_decision_manager
+ strategy: affirmative
+ providers:
+ default:
+ memory:
+ users:
+ foo: { password: foo, roles: ROLE_USER }
+ firewalls:
+ simple: { pattern: /login, security: false }