merged branch stof/security_factories (PR #2668)
Commits
-------
413756c
[BC break][SecurityBundle] Changed the way to register factories
Discussion
----------
[BC break][SecurityBundle] Changed the way to register factories
As discussed in #2454, this changes the way to register the factories to let each bundles register the factories it provides.
This commit is contained in:
commit
c73476929b
@ -36,6 +36,9 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
|
||||
|
||||
### SecurityBundle
|
||||
|
||||
* [BC BREAK] The custom factories for the firewall configuration are now registered during the build method of
|
||||
bundles instead of being registered by the end-user.
|
||||
|
||||
* [BC BREAK] The Firewall listener is now registered after the Router one.
|
||||
It means that specific Firewall URLs (like /login_check and /logout must now have proper
|
||||
route defined in your routing configuration)
|
||||
|
@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\SecurityBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
/**
|
||||
* This class contains the configuration information for the following tags:
|
||||
*
|
||||
* * security.config
|
||||
* * security.acl
|
||||
*
|
||||
* This information is solely responsible for how the different configuration
|
||||
* sections are normalized, and merged.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class FactoryConfiguration implements ConfigurationInterface
|
||||
{
|
||||
/**
|
||||
* Generates the configuration tree builder.
|
||||
*
|
||||
* @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
|
||||
*/
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$tb = new TreeBuilder();
|
||||
|
||||
$tb
|
||||
->root('security')
|
||||
->ignoreExtraKeys()
|
||||
->fixXmlConfig('factory', 'factories')
|
||||
->children()
|
||||
->arrayNode('factories')
|
||||
->prototype('scalar')->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
|
||||
return $tb;
|
||||
}
|
||||
}
|
@ -71,11 +71,6 @@ class MainConfiguration implements ConfigurationInterface
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
// add a faux-entry for factories, so that no validation error is thrown
|
||||
->fixXmlConfig('factory', 'factories')
|
||||
->children()
|
||||
->arrayNode('factories')->ignoreExtraKeys()->end()
|
||||
->end()
|
||||
;
|
||||
|
||||
$this->addAclSection($rootNode);
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Bundle\SecurityBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface;
|
||||
use Symfony\Component\DependencyInjection\DefinitionDecorator;
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
@ -36,22 +37,24 @@ class SecurityExtension extends Extension
|
||||
private $requestMatchers = array();
|
||||
private $contextListeners = array();
|
||||
private $listenerPositions = array('pre_auth', 'form', 'http', 'remember_me');
|
||||
private $factories;
|
||||
private $factories = array();
|
||||
private $userProviderFactories = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
foreach ($this->listenerPositions as $position) {
|
||||
$this->factories[$position] = array();
|
||||
}
|
||||
}
|
||||
|
||||
public function load(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
if (!array_filter($configs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// first assemble the factories
|
||||
$factoriesConfig = new FactoryConfiguration();
|
||||
$config = $this->processConfiguration($factoriesConfig, $configs);
|
||||
$factories = $this->createListenerFactories($container, $config);
|
||||
|
||||
// normalize and merge the actual configuration
|
||||
$mainConfig = new MainConfiguration($factories, $this->userProviderFactories);
|
||||
$mainConfig = new MainConfiguration($this->factories, $this->userProviderFactories);
|
||||
$config = $this->processConfiguration($mainConfig, $configs);
|
||||
|
||||
// load services
|
||||
@ -208,14 +211,11 @@ class SecurityExtension extends Extension
|
||||
$arguments[1] = $userProviders;
|
||||
$definition->setArguments($arguments);
|
||||
|
||||
// create security listener factories
|
||||
$factories = $this->createListenerFactories($container, $config);
|
||||
|
||||
// load firewall map
|
||||
$mapDef = $container->getDefinition('security.firewall.map');
|
||||
$map = $authenticationProviders = array();
|
||||
foreach ($firewalls as $name => $firewall) {
|
||||
list($matcher, $listeners, $exceptionListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $factories);
|
||||
list($matcher, $listeners, $exceptionListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds);
|
||||
|
||||
$contextId = 'security.firewall.map.context.'.$name;
|
||||
$context = $container->setDefinition($contextId, new DefinitionDecorator('security.firewall.context'));
|
||||
@ -237,7 +237,7 @@ class SecurityExtension extends Extension
|
||||
;
|
||||
}
|
||||
|
||||
private function createFirewall(ContainerBuilder $container, $id, $firewall, &$authenticationProviders, $providerIds, array $factories)
|
||||
private function createFirewall(ContainerBuilder $container, $id, $firewall, &$authenticationProviders, $providerIds)
|
||||
{
|
||||
// Matcher
|
||||
$i = 0;
|
||||
@ -310,7 +310,7 @@ class SecurityExtension extends Extension
|
||||
}
|
||||
|
||||
// Authentication listeners
|
||||
list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $authenticationProviders, $defaultProvider, $factories);
|
||||
list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $authenticationProviders, $defaultProvider);
|
||||
|
||||
$listeners = array_merge($listeners, $authListeners);
|
||||
|
||||
@ -346,14 +346,14 @@ class SecurityExtension extends Extension
|
||||
return $this->contextListeners[$contextKey] = $listenerId;
|
||||
}
|
||||
|
||||
private function createAuthenticationListeners($container, $id, $firewall, &$authenticationProviders, $defaultProvider, array $factories)
|
||||
private function createAuthenticationListeners($container, $id, $firewall, &$authenticationProviders, $defaultProvider)
|
||||
{
|
||||
$listeners = array();
|
||||
$hasListeners = false;
|
||||
$defaultEntryPoint = null;
|
||||
|
||||
foreach ($this->listenerPositions as $position) {
|
||||
foreach ($factories[$position] as $factory) {
|
||||
foreach ($this->factories[$position] as $factory) {
|
||||
$key = str_replace('-', '_', $factory->getKey());
|
||||
|
||||
if (isset($firewall[$key])) {
|
||||
@ -549,44 +549,9 @@ class SecurityExtension extends Extension
|
||||
return $this->requestMatchers[$id] = new Reference($id);
|
||||
}
|
||||
|
||||
private function createListenerFactories(ContainerBuilder $container, $config)
|
||||
public function addSecurityListenerFactory(SecurityFactoryInterface $factory)
|
||||
{
|
||||
if (null !== $this->factories) {
|
||||
return $this->factories;
|
||||
}
|
||||
|
||||
// load service templates
|
||||
$c = new ContainerBuilder();
|
||||
$parameterBag = $container->getParameterBag();
|
||||
|
||||
$locator = new FileLocator(__DIR__.'/../Resources/config');
|
||||
$resolver = new LoaderResolver(array(
|
||||
new XmlFileLoader($c, $locator),
|
||||
new YamlFileLoader($c, $locator),
|
||||
new PhpFileLoader($c, $locator),
|
||||
));
|
||||
$loader = new DelegatingLoader($resolver);
|
||||
|
||||
$loader->load('security_factories.xml');
|
||||
|
||||
// load user-created listener factories
|
||||
foreach ($config['factories'] as $factory) {
|
||||
$loader->load($parameterBag->resolveValue($factory));
|
||||
}
|
||||
|
||||
$tags = $c->findTaggedServiceIds('security.listener.factory');
|
||||
|
||||
$factories = array();
|
||||
foreach ($this->listenerPositions as $position) {
|
||||
$factories[$position] = array();
|
||||
}
|
||||
|
||||
foreach (array_keys($tags) as $tag) {
|
||||
$factory = $c->get($tag);
|
||||
$factories[$factory->getPosition()][] = $factory;
|
||||
}
|
||||
|
||||
return $this->factories = $factories;
|
||||
$this->factories[$factory->getPosition()][] = $factory;
|
||||
}
|
||||
|
||||
public function addUserProviderFactory(UserProviderFactoryInterface $factory)
|
||||
|
@ -14,6 +14,11 @@ namespace Symfony\Bundle\SecurityBundle;
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FormLoginFactory;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpBasicFactory;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpDigestFactory;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\RememberMeFactory;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\X509Factory;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\InMemoryFactory;
|
||||
|
||||
/**
|
||||
@ -27,7 +32,14 @@ class SecurityBundle extends Bundle
|
||||
{
|
||||
parent::build($container);
|
||||
|
||||
$container->getExtension('security')->addUserProviderFactory(new InMemoryFactory());
|
||||
$extension = $container->getExtension('security');
|
||||
$extension->addSecurityListenerFactory(new FormLoginFactory());
|
||||
$extension->addSecurityListenerFactory(new HttpBasicFactory());
|
||||
$extension->addSecurityListenerFactory(new HttpDigestFactory());
|
||||
$extension->addSecurityListenerFactory(new RememberMeFactory());
|
||||
$extension->addSecurityListenerFactory(new X509Factory());
|
||||
|
||||
$extension->addUserProviderFactory(new InMemoryFactory());
|
||||
$container->addCompilerPass(new AddSecurityVotersPass());
|
||||
}
|
||||
}
|
||||
|
@ -33,25 +33,6 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Test that the main tree is OK to be passed a factory or factories
|
||||
* key, without throwing any validation errors.
|
||||
*/
|
||||
public function testMainConfigTreeWithFactories()
|
||||
{
|
||||
$config = array_merge(self::$minimalConfig, array(
|
||||
'factory' => array('foo' => 'bar'),
|
||||
'factories' => array('lorem' => 'ipsum'),
|
||||
));
|
||||
|
||||
$processor = new Processor();
|
||||
$configuration = new MainConfiguration(array(), array());
|
||||
$config = $processor->processConfiguration($configuration, array($config));
|
||||
|
||||
$this->assertFalse(array_key_exists('factory', $config), 'The factory key is silently removed without an exception');
|
||||
$this->assertEquals(array(), $config['factories'], 'The factories key is just an empty array');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
||||
*/
|
||||
|
@ -14,7 +14,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Parameter;
|
||||
|
||||
use Symfony\Bundle\SecurityBundle\SecurityBundle;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
|
||||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\InMemoryFactory;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
@ -169,8 +169,10 @@ abstract class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$security = new SecurityExtension();
|
||||
$security->addUserProviderFactory(new InMemoryFactory());
|
||||
$container->registerExtension($security);
|
||||
|
||||
$bundle = new SecurityBundle();
|
||||
$bundle->build($container); // Attach all default factories
|
||||
$this->loadFromFile($container, $file);
|
||||
|
||||
$container->getCompilerPassConfig()->setOptimizationPasses(array());
|
||||
|
Reference in New Issue
Block a user