[Security] added AbstractFactory

This commit is contained in:
Lukas Kahwe Smith 2011-01-28 16:35:16 +01:00 committed by Fabien Potencier
parent 3ac4994507
commit 2539da5e6a
3 changed files with 210 additions and 63 deletions

View File

@ -0,0 +1,171 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
/**
* AbstractFactory is the base class for all classes inheriting from
* AbstractAuthenticationListener
*
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
abstract class AbstractFactory implements SecurityFactoryInterface
{
protected $options = array(
'check_path' => '/login_check',
'login_path' => '/login',
'use_forward' => false,
'always_use_default_target_path' => false,
'default_target_path' => '/',
'target_path_parameter' => '_target_path',
'use_referer' => false,
'failure_path' => null,
'failure_forward' => false,
);
public function create(ContainerBuilder $container, $id, $config, $userProviderId, $defaultEntryPointId)
{
if (!is_array($config)) {
$config = array();
}
// merge set options with default options
$options = $this->getOptionsFromConfig($config);
// authentication provider
$authProviderId = $this->createAuthProvider($container, $id, $options, $userProviderId);
$container
->getDefinition($authProviderId)
->addTag('security.authentication_provider')
;
// authentication listener
$listenerId = $this->createListener($container, $id, $options, $userProviderId);
// add remember-me aware tag if requested
if ($this->isRememberMeAware($config)) {
$container
->getDefinition($listenerId)
->addTag('security.remember_me_aware', array('id' => $id, 'provider' => $userProviderId))
;
}
// create entry point if applicable (optional)
$entryPointId = $this->createEntryPoint($container, $id, $options, $defaultEntryPointId);
return array($authProviderId, $listenerId, $entryPointId);
}
public final function addOption($name, $default = null)
{
$this->options[$name] = $default;
}
/**
* Subclasses must return the id of a service which implements the
* AuthenticationProviderInterface.
*
* @param ContainerBuilder $container
* @param string $id The unique id of the firewall
* @param array $options The options array for this listener
* @param string $userProviderId The id of the user provider
*
* @return string never null, the id of the authentication provider
*/
abstract protected function createAuthProvider(ContainerBuilder $container, $id, $options, $userProviderId);
/**
* Subclasses must return the id of the abstract listener template.
*
* Listener definitions should inherit from the AbstractAuthenticationListener
* like this:
*
* <service id="my.listener.id"
* class="My\Concrete\Classname"
* parent="security.authentication.listener.abstract"
* abstract="true" />
*
* In the above case, this method would return "my.listener.id".
*
* @return string
*/
abstract protected function getListenerId();
/**
* Subclasses may create an entry point of their as they see fit. The
* default implementation does not change the default entry point.
*
* @param ContainerBuilder $container
* @param string $id
* @param array $options
* @param string $defaultEntryPointId
*
* @return string the entry point id
*/
protected function createEntryPoint($container, $id, $options, $defaultEntryPointId)
{
return $defaultEntryPointId;
}
/**
* Subclasses may disable remember-me features for the listener, by
* always returning false from this method.
*
* @param array $config
*
* @return Boolean Whether a possibly configured RememberMeServices should be set for this listener
*/
protected function isRememberMeAware($config)
{
return !isset($config['remember_me']) || (Boolean) $config['remember_me'];
}
protected function createListener($container, $id, $options, $userProvider)
{
$listenerId = $this->getListenerId();
$listener = new DefinitionDecorator($listenerId);
$listener->setArgument(3, $id);
$listener->setArgument(4, $options);
// success handler
if (isset($config['success_handler'])) {
$listener->setArgument(5, new Reference($config['success_handler']));
}
// failure handler
if (isset($config['failure_handler'])) {
$listener->setArgument(6, new Reference($config['failure_handler']));
}
$listenerId .= '.'.$id;
$container->setDefinition($listenerId, $listener);
return $listenerId;
}
protected final function getOptionsFromConfig($config)
{
$options = $this->options;
foreach (array_keys($options) as $key) {
if (array_key_exists($key, $config)) {
$options[$key] = $config[$key];
}
}
return $options;
}
}

View File

@ -19,71 +19,15 @@ use Symfony\Component\DependencyInjection\Reference;
* FormLoginFactory creates services for form login authentication.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class FormLoginFactory implements SecurityFactoryInterface
class FormLoginFactory extends AbstractFactory
{
public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
public function __construct()
{
$provider = 'security.authentication.provider.dao.'.$id;
$container
->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.dao'))
->setArgument(0, new Reference($userProvider))
->setArgument(2, $id)
->addTag('security.authentication_provider')
;
// listener
$listenerId = 'security.authentication.listener.form.'.$id;
$listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.form'));
$listener->setArgument(3, $id);
// add remember-me tag
$rememberMe = true;
if (isset($config['remember_me']) && false === $config['remember_me']) {
$rememberMe = false;
}
if ($rememberMe) {
$listener->addTag('security.remember_me_aware', array('id' => $id, 'provider' => $userProvider));
}
// generate options
$options = array(
'check_path' => '/login_check',
'login_path' => '/login',
'use_forward' => false,
'always_use_default_target_path' => false,
'default_target_path' => '/',
'target_path_parameter' => '_target_path',
'use_referer' => false,
'failure_path' => null,
'failure_forward' => false,
);
foreach (array_keys($options) as $key) {
if (array_key_exists($key, $config)) {
$options[$key] = $config[$key];
}
}
$listener->setArgument(4, $options);
// success handler
if (isset($config['success_handler'])) {
$listener->setArgument(5, new Reference($config['success_handler']));
}
// failure handler
if (isset($config['failure_handler'])) {
$listener->setArgument(6, new Reference($config['failure_handler']));
}
// form entry point
$entryPointId = 'security.authentication.form_entry_point.'.$id;
$container
->setDefinition($entryPointId, new DefinitionDecorator('security.authentication.form_entry_point'))
->addArgument($options['login_path'])
->addArgument($options['use_forward'])
;
return array($provider, $listenerId, $entryPointId);
$this->addOption('username_parameter', '_username');
$this->addOption('password_parameter', '_password');
$this->addOption('post_only', true);
}
public function getPosition()
@ -95,4 +39,33 @@ class FormLoginFactory implements SecurityFactoryInterface
{
return 'form-login';
}
protected function getListenerId()
{
return 'security.authentication.listener.form';
}
protected function createAuthProvider(ContainerBuilder $container, $id, $options, $userProviderId)
{
$provider = 'security.authentication.provider.dao.'.$id;
$container
->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.dao'))
->setArgument(0, new Reference($userProviderId))
->setArgument(2, $id)
;
return $provider;
}
protected function createEntryPoint($container, $id, $options, $defaultEntryPoint)
{
$entryPointId = 'security.authentication.form_entry_point.'.$id;
$container
->setDefinition($entryPointId, new DefinitionDecorator('security.authentication.form_entry_point'))
->addArgument($options['login_path'])
->addArgument($options['use_forward'])
;
return $entryPointId;
}
}

View File

@ -43,6 +43,9 @@ abstract class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
'security.authentication.provider.doctrine',
'security.authentication.provider.service',
'security.authentication.provider.anonymous',
'security.authentication.provider.dao',
'security.authentication.provider.pre_authenticated',
'security.authentication.provider.rememberme',
);
$this->assertEquals(array(), array_diff($expectedProviders, $providers));
@ -58,7 +61,7 @@ abstract class SecurityExtensionTest extends \PHPUnit_Framework_TestCase
foreach (array_keys($arguments[1]) as $contextId) {
$contextDef = $container->getDefinition($contextId);
$arguments = $contextDef->getArguments();
$listeners[] = array_map(function ($ref) { return preg_replace('/\.[a-f0-9]+$/', '', (string) $ref); }, $arguments[0]);
$listeners[] = array_map(function ($ref) { return preg_replace('/\.[a-f0-9]+$/', '', (string) $ref); }, $arguments['index_0']);
}
$this->assertEquals(array(