Skip to content

Commit

Permalink
[BC break][SecurityBundle] Changed the way to register factories
Browse files Browse the repository at this point in the history
  • Loading branch information
stof committed Nov 17, 2011
1 parent ae1e9cb commit 413756c
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 132 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG-2.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,6 @@ public function getConfigTreeBuilder()
->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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -207,14 +210,11 @@ private function createFirewalls($config, ContainerBuilder $container)
$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'));
Expand All @@ -236,7 +236,7 @@ private function createFirewalls($config, ContainerBuilder $container)
;
}

private function createFirewall(ContainerBuilder $container, $id, $firewall, &$authenticationProviders, $providerIds, array $factories)
private function createFirewall(ContainerBuilder $container, $id, $firewall, &$authenticationProviders, $providerIds)
{
// Matcher
$i = 0;
Expand Down Expand Up @@ -309,7 +309,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a
}

// 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);

Expand Down Expand Up @@ -345,14 +345,14 @@ private function createContextListener($container, $contextKey)
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])) {
Expand Down Expand Up @@ -548,44 +548,9 @@ private function createRequestMatcher($container, $path = null, $host = null, $m
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)
Expand Down
14 changes: 13 additions & 1 deletion src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
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;

/**
Expand All @@ -27,7 +32,14 @@ public function build(ContainerBuilder $container)
{
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());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
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;
Expand Down Expand Up @@ -169,8 +169,10 @@ protected function getContainer($file)
{
$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());
Expand Down

3 comments on commit 413756c

@weaverryan
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stof Doesn't this change render the old security_factories.xml file useless? I noticed this file still exists - but I can't see any use for it.

Thanks!

@stof
Copy link
Member Author

@stof stof commented on 413756c Apr 21, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@weaverryan it is indeed useless. I simply forgot to remove it. Please send a pull request :)

@weaverryan
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification - I will do that!

Please sign in to comment.