merged branch vicb/acl (PR #3560)

Commits
-------

6d27aec [SecurityBundle] Improve the init:acl command
e809458 [Security]replaced acl:init command with postGenerateSchema listener

Discussion
----------

[WIP][Security]replaced acl:init command with postGenerateSchema listener

Attempt to fix #2091.

The code is from @schmittjoh (see #1313) but was never merged.

The difference is that the `init:acl` command has not been dropped in order to overcome [the limitations](https://github.com/symfony/symfony/pull/1313#issuecomment-1387091) described by @stof. @stof do you think this is ok ?

Left to fix:

* Using the code from this PR, the generated migration does not drop the tables but still alter them,

@stof you know this part of the code far better than me. I would appreacite your feedback on this PR and any hint on solving the remaining item. Thanks.
This commit is contained in:
Fabien Potencier 2012-03-11 17:58:59 +01:00
commit fb7b88b226
6 changed files with 99 additions and 23 deletions

View File

@ -15,6 +15,7 @@ use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Security\Acl\Dbal\Schema;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\DBAL\Schema\SchemaException;
/**
* Installs the tables required by the ACL system
@ -50,26 +51,19 @@ EOT
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$connection = $this->getContainer()->get('security.acl.dbal.connection');
$sm = $connection->getSchemaManager();
$tableNames = $sm->listTableNames();
$tables = array(
'class_table_name' => $this->getContainer()->getParameter('security.acl.dbal.class_table_name'),
'sid_table_name' => $this->getContainer()->getParameter('security.acl.dbal.sid_table_name'),
'oid_table_name' => $this->getContainer()->getParameter('security.acl.dbal.oid_table_name'),
'oid_ancestors_table_name' => $this->getContainer()->getParameter('security.acl.dbal.oid_ancestors_table_name'),
'entry_table_name' => $this->getContainer()->getParameter('security.acl.dbal.entry_table_name'),
);
$container = $this->getContainer();
foreach ($tables as $table) {
if (in_array($table, $tableNames, true)) {
$output->writeln(sprintf('The table "%s" already exists. Aborting.', $table));
$connection = $container->get('security.acl.dbal.connection');
$schema = $container->get('security.acl.dbal.schema');
return;
}
try {
$schema->addToSchema($connection->getSchemaManager()->createSchema());
} catch (SchemaException $e) {
$output->writeln("Aborting: " . $e->getMessage());
return;
}
$schema = new Schema($tables, $sm->createSchemaConfig());
foreach ($schema->toSql($connection->getDatabasePlatform()) as $sql) {
$connection->exec($sql);
}

View File

@ -89,7 +89,11 @@ class MainConfiguration implements ConfigurationInterface
->children()
->arrayNode('acl')
->children()
->scalarNode('connection')->setInfo('any name configured in doctrine.dbal section')->end()
->scalarNode('connection')
->defaultValue('default')
->cannotBeEmpty()
->setInfo('any name configured in doctrine.dbal section')
->end()
->arrayNode('cache')
->addDefaultsIfNotSet()
->children()

View File

@ -133,9 +133,16 @@ class SecurityExtension extends Extension
{
$loader->load('security_acl_dbal.xml');
if (isset($config['connection'])) {
$container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection']));
}
$container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection']));
$container
->getDefinition('security.acl.dbal.schema_listener')
->addTag('doctrine.event_listener', array(
'connection' => $config['connection'],
'event' => 'postGenerateSchema'
))
;
$container->getDefinition('security.acl.cache.doctrine')->addArgument($config['cache']['prefix']);
$container->setParameter('security.acl.dbal.class_table_name', $config['tables']['class']);

View File

@ -0,0 +1,36 @@
<?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\EventListener;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
/**
* Merges ACL schema into the given schema.
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
class AclSchemaListener
{
private $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function postGenerateSchema(GenerateSchemaEventArgs $args)
{
$schema = $args->getSchema();
$this->container->get('security.acl.dbal.schema')->addToSchema($schema);
}
}

View File

@ -6,6 +6,8 @@
<parameters>
<parameter key="security.acl.dbal.provider.class">Symfony\Component\Security\Acl\Dbal\MutableAclProvider</parameter>
<parameter key="security.acl.dbal.schema.class">Symfony\Component\Security\Acl\Dbal\Schema</parameter>
<parameter key="security.acl.dbal.schema_listener.class">Symfony\Bundle\SecurityBundle\EventListener\AclSchemaListener</parameter>
</parameters>
<services>
@ -24,6 +26,20 @@
<argument type="service" id="security.acl.cache" on-invalid="null" />
</service>
<service id="security.acl.dbal.schema" class="%security.acl.dbal.schema.class%">
<argument type="collection">
<argument key="class_table_name">%security.acl.dbal.class_table_name%</argument>
<argument key="entry_table_name">%security.acl.dbal.entry_table_name%</argument>
<argument key="oid_table_name">%security.acl.dbal.oid_table_name%</argument>
<argument key="oid_ancestors_table_name">%security.acl.dbal.oid_ancestors_table_name%</argument>
<argument key="sid_table_name">%security.acl.dbal.sid_table_name%</argument>
</argument>
<argument type="service" id="security.acl.dbal.connection" />
</service>
<service id="security.acl.dbal.schema_listener" class="%security.acl.dbal.schema_listener.class%" public="false">
<argument type="service" id="service_container" />
</service>
<service id="security.acl.provider" alias="security.acl.dbal.provider" />
<service id="security.acl.cache.doctrine" class="%security.acl.cache.doctrine.class%" public="false">

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Acl\Dbal;
use Doctrine\DBAL\Schema\Schema as BaseSchema;
use Doctrine\DBAL\Schema\SchemaConfig;
use Doctrine\DBAL\Connection;
/**
* The schema used for the ACL system.
@ -26,11 +27,13 @@ final class Schema extends BaseSchema
/**
* Constructor
*
* @param array $options the names for tables
* @param SchemaConfig $schemaConfig
* @param array $options the names for tables
* @param Connection $connection
*/
public function __construct(array $options, SchemaConfig $schemaConfig = null)
public function __construct(array $options, Connection $connection = null)
{
$schemaConfig = null === $connection ? null : $connection->getSchemaManager()->createSchemaConfig();
parent::__construct(array(), array(), $schemaConfig);
$this->options = $options;
@ -42,6 +45,22 @@ final class Schema extends BaseSchema
$this->addEntryTable();
}
/**
* Merges ACL schema with the given schema.
*
* @param BaseSchema $schema
*/
public function addToSchema(BaseSchema $schema)
{
foreach ($this->getTables() as $table) {
$schema->_addTable($table);
}
foreach ($this->getSequences() as $sequence) {
$schema->_addSequence($sequence);
}
}
/**
* Adds the class table to the schema
*/