better errors when security deps are missing
This commit is contained in:
parent
34d5f9eefe
commit
56ee4aa543
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
||||
|
||||
/**
|
||||
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
||||
*/
|
||||
class WorkflowGuardListenerPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->hasParameter('workflow.has_guard_listeners')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$container->getParameterBag()->remove('workflow.has_guard_listeners');
|
||||
|
||||
if (!$container->has('security.token_storage')) {
|
||||
throw new LogicException('The "security.token_storage" service is needed to be able to use the workflow guard listener.');
|
||||
}
|
||||
|
||||
if (!$container->has('security.authorization_checker')) {
|
||||
throw new LogicException('The "security.authorization_checker" service is needed to be able to use the workflow guard listener.');
|
||||
}
|
||||
|
||||
if (!$container->has('security.authentication.trust_resolver')) {
|
||||
throw new LogicException('The "security.authentication.trust_resolver" service is needed to be able to use the workflow guard listener.');
|
||||
}
|
||||
|
||||
if (!$container->has('security.role_hierarchy')) {
|
||||
throw new LogicException('The "security.role_hierarchy" service is needed to be able to use the workflow guard listener.');
|
||||
}
|
||||
}
|
||||
}
|
@ -46,6 +46,7 @@ use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
|
||||
use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface;
|
||||
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
|
||||
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Serializer\Encoder\CsvEncoder;
|
||||
use Symfony\Component\Serializer\Encoder\DecoderInterface;
|
||||
use Symfony\Component\Serializer\Encoder\EncoderInterface;
|
||||
@ -597,6 +598,10 @@ class FrameworkExtension extends Extension
|
||||
throw new LogicException('Cannot guard workflows as the ExpressionLanguage component is not installed.');
|
||||
}
|
||||
|
||||
if (!class_exists(Security::class)) {
|
||||
throw new LogicException('Cannot guard workflows as the Security component is not installed.');
|
||||
}
|
||||
|
||||
$eventName = sprintf('workflow.%s.guard.%s', $name, $transitionName);
|
||||
$guard->addTag('kernel.event_listener', array('event' => $eventName, 'method' => 'onTransition'));
|
||||
$configuration[$eventName] = $config['guard'];
|
||||
@ -612,6 +617,7 @@ class FrameworkExtension extends Extension
|
||||
));
|
||||
|
||||
$container->setDefinition(sprintf('%s.listener.guard', $workflowId), $guard);
|
||||
$container->setParameter('workflow.has_guard_listeners', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilder
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass;
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass;
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass;
|
||||
use Symfony\Component\Config\DependencyInjection\ConfigCachePass;
|
||||
use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass;
|
||||
@ -109,6 +110,7 @@ class FrameworkBundle extends Bundle
|
||||
$this->addCompilerPassIfExists($container, ValidateWorkflowsPass::class);
|
||||
$container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING);
|
||||
$this->addCompilerPassIfExists($container, FormPass::class);
|
||||
$container->addCompilerPass(new WorkflowGuardListenerPass());
|
||||
|
||||
if ($container->getParameter('kernel.debug')) {
|
||||
$container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);
|
||||
|
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Symfony\Component\Security\Core\Role\RoleHierarchy;
|
||||
use Symfony\Component\Workflow\EventListener\GuardListener;
|
||||
|
||||
class WorkflowGuardListenerPassTest extends TestCase
|
||||
{
|
||||
private $container;
|
||||
private $compilerPass;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->container = new ContainerBuilder();
|
||||
$this->container->register('foo.listener.guard', GuardListener::class);
|
||||
$this->container->register('bar.listener.guard', GuardListener::class);
|
||||
$this->compilerPass = new WorkflowGuardListenerPass();
|
||||
}
|
||||
|
||||
public function testListenersAreNotRemovedIfParameterIsNotSet()
|
||||
{
|
||||
$this->compilerPass->process($this->container);
|
||||
|
||||
$this->assertTrue($this->container->hasDefinition('foo.listener.guard'));
|
||||
$this->assertTrue($this->container->hasDefinition('bar.listener.guard'));
|
||||
}
|
||||
|
||||
public function testParameterIsRemovedWhenThePassIsProcessed()
|
||||
{
|
||||
$this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard'));
|
||||
|
||||
try {
|
||||
$this->compilerPass->process($this->container);
|
||||
} catch (LogicException $e) {
|
||||
// Here, we are not interested in the exception handling. This is tested further down.
|
||||
}
|
||||
|
||||
$this->assertFalse($this->container->hasParameter('workflow.has_guard_listeners'));
|
||||
}
|
||||
|
||||
public function testListenersAreNotRemovedIfAllDependenciesArePresent()
|
||||
{
|
||||
$this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard'));
|
||||
$this->container->register('security.token_storage', TokenStorageInterface::class);
|
||||
$this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class);
|
||||
$this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class);
|
||||
$this->container->register('security.role_hierarchy', RoleHierarchy::class);
|
||||
|
||||
$this->compilerPass->process($this->container);
|
||||
|
||||
$this->assertTrue($this->container->hasDefinition('foo.listener.guard'));
|
||||
$this->assertTrue($this->container->hasDefinition('bar.listener.guard'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException
|
||||
* @expectedExceptionMessage The "security.token_storage" service is needed to be able to use the workflow guard listener.
|
||||
*/
|
||||
public function testListenersAreRemovedIfTheTokenStorageServiceIsNotPresent()
|
||||
{
|
||||
$this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard'));
|
||||
$this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class);
|
||||
$this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class);
|
||||
$this->container->register('security.role_hierarchy', RoleHierarchy::class);
|
||||
|
||||
$this->compilerPass->process($this->container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException
|
||||
* @expectedExceptionMessage The "security.authorization_checker" service is needed to be able to use the workflow guard listener.
|
||||
*/
|
||||
public function testListenersAreRemovedIfTheAuthorizationCheckerServiceIsNotPresent()
|
||||
{
|
||||
$this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard'));
|
||||
$this->container->register('security.token_storage', TokenStorageInterface::class);
|
||||
$this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class);
|
||||
$this->container->register('security.role_hierarchy', RoleHierarchy::class);
|
||||
|
||||
$this->compilerPass->process($this->container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException
|
||||
* @expectedExceptionMessage The "security.authentication.trust_resolver" service is needed to be able to use the workflow guard listener.
|
||||
*/
|
||||
public function testListenersAreRemovedIfTheAuthenticationTrustResolverServiceIsNotPresent()
|
||||
{
|
||||
$this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard'));
|
||||
$this->container->register('security.token_storage', TokenStorageInterface::class);
|
||||
$this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class);
|
||||
$this->container->register('security.role_hierarchy', RoleHierarchy::class);
|
||||
|
||||
$this->compilerPass->process($this->container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException
|
||||
* @expectedExceptionMessage The "security.role_hierarchy" service is needed to be able to use the workflow guard listener.
|
||||
*/
|
||||
public function testListenersAreRemovedIfTheRoleHierarchyServiceIsNotPresent()
|
||||
{
|
||||
$this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard'));
|
||||
$this->container->register('security.token_storage', TokenStorageInterface::class);
|
||||
$this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class);
|
||||
$this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class);
|
||||
|
||||
$this->compilerPass->process($this->container);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user