Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[Security] moved Security classes out of DoctrineBundle, cleaned-up S…
…ecurityExtension accordingly

Note that this commit removes the built-in support for MongoDB user providers.
This code can be moved back in once there is a stable release for MongoDB, but
for now you have to set-up that user provider just like you would set-up any
custom user provider:

    security:
         providers:
             document_provider:
                 id: my.mongo.provider
  • Loading branch information
schmittjoh authored and fabpot committed Feb 16, 2011
1 parent dfd9218 commit 82c6844
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 92 deletions.
8 changes: 0 additions & 8 deletions src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml
Expand Up @@ -37,12 +37,6 @@
<parameter key="doctrine.orm.metadata.staticphp_class">Doctrine\ORM\Mapping\Driver\StaticPHPDriver</parameter>
<parameter key="doctrine.orm.class_metadata_factory_name">Doctrine\ORM\Mapping\ClassMetadataFactory</parameter>

<!-- security/user -->
<parameter key="security.user.provider.entity.class">Symfony\Bundle\DoctrineBundle\Security\EntityUserProvider</parameter>

<!-- security/acl -->
<parameter key="security.acl.collection_cache.class">Symfony\Bundle\DoctrineBundle\Security\AclCollectionCache</parameter>

<!-- cache warmer -->
<parameter key="doctrine.orm.proxy_cache_warmer.class">Symfony\Bundle\DoctrineBundle\CacheWarmer\ProxyCacheWarmer</parameter>

Expand All @@ -59,8 +53,6 @@
</call>
</service>

<service id="security.user.entity_manager" alias="doctrine.orm.default_entity_manager" public="false" />

<service id="doctrine.orm.proxy_cache_warmer" class="%doctrine.orm.proxy_cache_warmer.class%" public="false">
<tag name="kernel.cache_warmer" />
<argument type="service" id="service_container" />
Expand Down
Expand Up @@ -17,18 +17,6 @@
*/
class Configuration
{
public function getAclConfigTree()
{
$tb = new TreeBuilder();

return $tb
->root('security', 'array')
->scalarNode('connection')->end()
->scalarNode('cache')->end()
->end()
->buildTree();
}

public function getFactoryConfigTree()
{
$tb = new TreeBuilder();
Expand All @@ -53,6 +41,7 @@ public function getMainConfigTree(array $factories)
->scalarNode('session_fixation_strategy')->cannotBeEmpty()->defaultValue('migrate')->end()
;

$this->addAclSection($rootNode);
$this->addEncodersSection($rootNode);
$this->addProvidersSection($rootNode);
$this->addFirewallsSection($rootNode, $factories);
Expand All @@ -62,6 +51,16 @@ public function getMainConfigTree(array $factories)
return $tb->buildTree();
}

protected function addAclSection($rootNode)
{
$rootNode
->arrayNode('acl')
->scalarNode('connection')->end()
->scalarNode('cache')->end()
->end()
;
}

protected function addRoleHierarchySection($rootNode)
{
$rootNode
Expand Down
Expand Up @@ -47,8 +47,6 @@ public function __construct()

public function load(array $configs, ContainerBuilder $container)
{
$this->aclLoad($configs, $container);

$tmp = array_filter($configs);
if (empty($tmp)) {
return;
Expand Down Expand Up @@ -83,22 +81,10 @@ public function load(array $configs, ContainerBuilder $container)
if ($config['encoders']) {
$this->createEncoders($config['encoders'], $container);
}
}

protected function aclLoad(array $configs, ContainerBuilder $container)
{
$processor = new Processor();
$config = $processor->process($this->configuration->getAclConfigTree(), $configs);

$loader = new XmlFileLoader($container, new FileLocator(array(__DIR__.'/../Resources/config', __DIR__.'/Resources/config')));
$loader->load('security_acl.xml');

if (isset($config['connection'])) {
$container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection']));
}

if (isset($config['cache'])) {
$container->setAlias('security.acl.cache', sprintf('security.acl.cache.%s', $config['cache']));
// load ACL
if (isset($config['acl'])) {
$this->aclLoad($config['acl'], $container);
}
}

Expand All @@ -122,6 +108,20 @@ public function getAlias()
return 'security';
}

protected function aclLoad($config, ContainerBuilder $container)
{
$loader = new XmlFileLoader($container, new FileLocator(array(__DIR__.'/../Resources/config', __DIR__.'/Resources/config')));
$loader->load('security_acl.xml');

if (isset($config['connection'])) {
$container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection']));
}

if (isset($config['cache'])) {
$container->setAlias('security.acl.cache', sprintf('security.acl.cache.%s', $config['cache']));
}
}

/**
* Loads the web configuration.
*
Expand Down Expand Up @@ -421,8 +421,6 @@ protected function createUserProviders($config, ContainerBuilder $container)
}

// Parses a <provider> tag and returns the id for the related user provider service
// FIXME: Replace register() calls in this method with DefinitionDecorator
// and move the actual definition to an xml file
protected function createUserDaoProvider($name, $provider, ContainerBuilder $container, $master = true)
{
$name = $this->getUserProviderId(strtolower($name));
Expand All @@ -443,42 +441,22 @@ protected function createUserDaoProvider($name, $provider, ContainerBuilder $con
// Doctrine Entity DAO provider
if (isset($provider['entity'])) {
$container
->register($name, '%security.user.provider.entity.class%')
->setPublic(false)
->setArguments(array(
new Reference('security.user.entity_manager'),
$provider['entity']['class'],
$provider['entity']['property'],
))
->setDefinition($name, new DefinitionDecorator('security.user.provider.entity'))
->addArgument($provider['entity']['class'])
->addArgument($provider['entity']['property'])
;

return $name;
}

// Doctrine Document DAO provider
if (isset($provider['document'])) {
$container
->register($name, '%security.user.provider.document.class%')
->setPublic(false)
->setArguments(array(
new Reference('security.user.document_manager'),
$provider['document']['class'],
$provider['document']['property'],
));

return $name;
}

// In-memory DAO provider
$definition = $container->register($name, '%security.user.provider.in_memory.class%');
$definition->setPublic(false);
$definition = $container->setDefinition($name, new DefinitionDecorator('security.user.provider.in_memory'));
foreach ($provider['users'] as $username => $user) {
$userId = $name.'_'.$username;

$container
->register($userId, 'Symfony\Component\Security\Core\User\User')
->setDefinition($userId, new DefinitionDecorator('security.user.provider.in_memory.user'))
->setArguments(array($username, $user['password'], $user['roles']))
->setPublic(false)
;

$definition->addMethodCall('createUser', array(new Reference($userId)));
Expand All @@ -489,7 +467,7 @@ protected function createUserDaoProvider($name, $provider, ContainerBuilder $con

protected function getUserProviderId($name)
{
return 'security.user.provider.'.$name;
return 'security.user.provider.concrete.'.$name;
}

protected function createExceptionListener($container, $config, $id, $defaultEntryPoint)
Expand Down
12 changes: 12 additions & 0 deletions src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
Expand Up @@ -14,7 +14,9 @@
<parameter key="security.encoder.digest.class">Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder</parameter>
<parameter key="security.encoder.plain.class">Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder</parameter>

<parameter key="security.user.provider.entity.class">Symfony\Component\Security\Core\User\EntityUserProvider</parameter>
<parameter key="security.user.provider.in_memory.class">Symfony\Component\Security\Core\User\InMemoryUserProvider</parameter>
<parameter key="security.user.provider.in_memory.user.class">Symfony\Component\Security\Core\User\User</parameter>

<parameter key="security.authentication.trust_resolver.class">Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver</parameter>
<parameter key="security.authentication.trust_resolver.anonymous_class">Symfony\Component\Security\Core\Authentication\Token\AnonymousToken</parameter>
Expand Down Expand Up @@ -117,5 +119,15 @@
<argument type="collection" />
<argument type="service" id="security.exception_listener" />
</service>


<!-- Provisioning -->
<service id="security.user.provider.entity" class="%security.user.provider.entity.class%" abstract="true" public="false">
<argument type="service" id="security.user.entity_manager" />
</service>
<service id="security.user.entity_manager" alias="doctrine.orm.default_entity_manager" public="false" />

<service id="security.user.provider.in_memory" class="%security.user.provider.in_memory.class%" abstract="true" public="false" />
<service id="security.user.provider.in_memory.user" class="%security.user.provider.in_memory.user.class%" abstract="true" public="false" />
</services>
</container>
26 changes: 14 additions & 12 deletions src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl.xml
Expand Up @@ -11,30 +11,32 @@
<parameter key="security.acl.dbal.oid_ancestors_table_name">acl_object_identity_ancestors</parameter>
<parameter key="security.acl.dbal.sid_table_name">acl_security_identities</parameter>
<parameter key="security.acl.dbal.provider.class">Symfony\Component\Security\Acl\Dbal\MutableAclProvider</parameter>

<parameter key="security.acl.permission_granting_strategy.class">Symfony\Component\Security\Acl\Domain\PermissionGrantingStrategy</parameter>

<parameter key="security.acl.voter.class">Symfony\Component\Security\Acl\Voter\AclVoter</parameter>
<parameter key="security.acl.voter.allow_if_object_identity_unavailable">true</parameter>
<parameter key="security.acl.permission.map.class">Symfony\Component\Security\Acl\Permission\BasicPermissionMap</parameter>

<parameter key="security.acl.object_identity_retrieval_strategy.class">Symfony\Component\Security\Acl\Domain\ObjectIdentityRetrievalStrategy</parameter>
<parameter key="security.acl.security_identity_retrieval_strategy.class">Symfony\Component\Security\Acl\Domain\SecurityIdentityRetrievalStrategy</parameter>

<parameter key="security.acl.cache.doctrine.class">Symfony\Component\Security\Acl\Domain\DoctrineAclCache</parameter>
<parameter key="security.acl.cache.doctrine.prefix">sf2_acl_</parameter>

<parameter key="security.acl.collection_cache.class">Symfony\Component\Security\Acl\Domain\AclCollectionCache</parameter>
</parameters>

<services>
<service id="security.acl.dbal.connection" alias="doctrine.dbal.default_connection" />

<service id="security.acl.object_identity_retrieval_strategy" class="%security.acl.object_identity_retrieval_strategy.class%" public="false"></service>

<service id="security.acl.security_identity_retrieval_strategy" class="%security.acl.security_identity_retrieval_strategy.class%" public="false">
<argument type="service" id="security.role_hierarchy" />
<argument type="service" id="security.authentication.trust_resolver" />
</service>

<service id="security.acl.dbal.provider" class="%security.acl.dbal.provider.class%" public="false">
<argument type="service" id="security.acl.dbal.connection" />
<argument type="service" id="security.acl.permission_granting_strategy" />
Expand All @@ -49,23 +51,23 @@
</service>

<service id="security.acl.provider" alias="security.acl.dbal.provider" />

<service id="security.acl.permission_granting_strategy" class="%security.acl.permission_granting_strategy.class%" public="false">
<call method="setAuditLogger">
<argument type="service" id="security.acl.audit_logger" on-invalid="ignore" />
</call>
</service>

<service id="security.acl.cache.doctrine" class="%security.acl.cache.doctrine.class%" public="false">
<argument type="service" id="security.acl.cache.doctrine_cache_impl" />
<argument type="service" id="security.acl.permission_granting_strategy" />
<argument>%security.acl.cache.doctrine.prefix%</argument>
</service>

<service id="security.acl.cache.doctrine.cache_impl" alias="doctrine.orm.default_result_cache" public="false" />

<service id="security.acl.permission.map" class="%security.acl.permission.map.class%" public="false"></service>

<service id="security.acl.voter.basic_permissions" class="%security.acl.voter.class%" public="false">
<argument type="service" id="security.acl.provider" />
<argument type="service" id="security.acl.object_identity_retrieval_strategy" />
Expand Down
Expand Up @@ -36,18 +36,18 @@ public function testUserProviders()
{
$container = $this->getContainer('container1');

$providers = array_values(array_filter($container->getServiceIds(), function ($key) { return 0 === strpos($key, 'security.user.provider.'); }));
$providers = array_values(array_filter($container->getServiceIds(), function ($key) { return 0 === strpos($key, 'security.user.provider.concrete'); }));

$expectedProviders = array(
'security.user.provider.default',
'security.user.provider.default_foo',
'security.user.provider.digest',
'security.user.provider.digest_foo',
'security.user.provider.basic',
'security.user.provider.basic_foo',
'security.user.provider.basic_bar',
'security.user.provider.doctrine',
'security.user.provider.service',
'security.user.provider.concrete.default',
'security.user.provider.concrete.default_foo',
'security.user.provider.concrete.digest',
'security.user.provider.concrete.digest_foo',
'security.user.provider.concrete.basic',
'security.user.provider.concrete.basic_foo',
'security.user.provider.concrete.basic_bar',
'security.user.provider.concrete.doctrine',
'security.user.provider.concrete.service',
);

$this->assertEquals(array(), array_diff($expectedProviders, $providers));
Expand Down
66 changes: 66 additions & 0 deletions src/Symfony/Component/Security/Acl/Domain/AclCollectionCache.php
@@ -0,0 +1,66 @@
<?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\Component\Security\Acl\Domain;

use Symfony\Component\Security\Acl\Model\AclProviderInterface;
use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface;
use Symfony\Component\Security\Acl\Model\SecurityIdentityRetrievalStrategyInterface;

/**
* This service caches ACLs for an entire collection of objects.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AclCollectionCache
{
protected $aclProvider;
protected $objectIdentityRetrievalStrategy;
protected $securityIdentityRetrievalStrategy;

/**
* Constructor
*
* @param AclProviderInterface $aclProvider
* @param ObjectIdentityRetrievalStrategy $oidRetrievalStrategy
* @param SecurityIdentityRetrievalStrategy $sidRetrievalStrategy
* @return void
*/
public function __construct(AclProviderInterface $aclProvider, ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy, SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy)
{
$this->aclProvider = $aclProvider;
$this->objectIdentityRetrievalStrategy = $oidRetrievalStrategy;
$this->securityIdentityRetrievalStrategy = $sidRetrievalStrategy;
}

/**
* Batch loads ACLs for an entire collection; thus, it reduces the number
* of required queries considerably.
*
* @param mixed $collection anything that can be passed to foreach()
* @param array $tokens an array of TokenInterface implementations
* @return void
*/
public function cache($collection, array $tokens = array())
{
$sids = array();
foreach ($tokens as $token) {
$sids = array_merge($sids, $this->securityIdentityRetrievalStrategy->getSecurityIdentities($token));
}

$oids = array();
foreach ($collection as $domainObject) {
$oids[] = $this->objectIdentityRetrievalStrategy->getObjectIdentity($domainObject);
}

$this->aclProvider->findAcls($oids, $sids);
}
}

0 comments on commit 82c6844

Please sign in to comment.