[BC break][SecurityBundle] Changed the way to register factories

This commit is contained in:
Christophe Coevoet 2011-11-17 20:16:17 +01:00
parent ae1e9cbedf
commit 413756c103
7 changed files with 37 additions and 132 deletions

View File

@ -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)

View File

@ -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;
}
}

View File

@ -70,11 +70,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);

View File

@ -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
@ -207,14 +210,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'));
@ -236,7 +236,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;
@ -309,7 +309,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);
@ -345,14 +345,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])) {
@ -548,44 +548,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)

View File

@ -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());
}
}

View File

@ -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
*/

View File

@ -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());