Skip to content

Commit 435bb0b

Browse files
committed
Allow defining security provider factories without config
1 parent 697b1c0 commit 435bb0b

6 files changed

Lines changed: 153 additions & 18 deletions

File tree

DependencyInjection/SecurityExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ private function createUserDaoProvider(string $name, array $provider, ContainerB
848848
foreach ($this->userProviderFactories as $factory) {
849849
$key = str_replace('-', '_', $factory->getKey());
850850

851-
if (!empty($provider[$key])) {
851+
if (\array_key_exists($key, $provider)) {
852852
$factory->create($container, $name, $provider[$key]);
853853

854854
return $name;

Tests/DependencyInjection/Fixtures/UserProvider/DummyProvider.php

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,27 @@
22

33
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProvider;
44

5-
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface;
6-
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
7-
use Symfony\Component\DependencyInjection\ContainerBuilder;
5+
use Symfony\Component\Security\Core\User\UserInterface;
6+
use Symfony\Component\Security\Core\User\UserProviderInterface;
87

9-
class DummyProvider implements UserProviderFactoryInterface
8+
class DummyProvider implements UserProviderInterface
109
{
11-
public function create(ContainerBuilder $container, $id, $config): void
10+
public function __construct(string $foo)
1211
{
1312
}
1413

15-
public function getKey(): string
14+
public function refreshUser(UserInterface $user): UserInterface
1615
{
17-
return 'foo';
16+
throw new \Exception('Not implemented');
1817
}
1918

20-
public function addConfiguration(NodeDefinition $node): void
19+
public function supportsClass(string $class): bool
2120
{
21+
throw new \Exception('Not implemented');
22+
}
23+
24+
public function loadUserByIdentifier(string $identifier): UserInterface
25+
{
26+
throw new \Exception('Not implemented');
2227
}
2328
}

Tests/DependencyInjection/Fixtures/UserProvider/CustomProvider.php renamed to Tests/DependencyInjection/Fixtures/UserProviderFactory/CustomProviderFactory.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
<?php
22

3-
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProvider;
3+
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProviderFactory;
44

55
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface;
6+
use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProvider\DummyProvider;
67
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
78
use Symfony\Component\DependencyInjection\ContainerBuilder;
9+
use Symfony\Component\DependencyInjection\Definition;
810

9-
class CustomProvider implements UserProviderFactoryInterface
11+
class CustomProviderFactory implements UserProviderFactoryInterface
1012
{
1113
public function create(ContainerBuilder $container, string $id, array $config): void
1214
{
15+
$definition = $container->setDefinition($id, new Definition(DummyProvider::class));
16+
$definition->setArgument('$foo', $config['foo']);
1317
}
1418

1519
public function getKey(): string
@@ -21,7 +25,9 @@ public function addConfiguration(NodeDefinition $builder): void
2125
{
2226
$builder
2327
->children()
24-
->scalarNode('foo')->defaultValue('bar')->end()
28+
->scalarNode('foo')
29+
->defaultValue('bar')
30+
->end()
2531
->end()
2632
;
2733
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProviderFactory;
4+
5+
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface;
6+
use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProvider\DummyProvider;
7+
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
8+
use Symfony\Component\DependencyInjection\ContainerBuilder;
9+
use Symfony\Component\DependencyInjection\Definition;
10+
11+
class DummyProviderFactory implements UserProviderFactoryInterface
12+
{
13+
public function create(ContainerBuilder $container, $id, $config): void
14+
{
15+
$container->setDefinition($id, new Definition(DummyProvider::class));
16+
}
17+
18+
public function getKey(): string
19+
{
20+
return 'foo';
21+
}
22+
23+
public function addConfiguration(NodeDefinition $node): void
24+
{
25+
}
26+
}

Tests/DependencyInjection/SecurityExtensionTest.php

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FirewallListenerFactoryInterface;
1818
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
1919
use Symfony\Bundle\SecurityBundle\SecurityBundle;
20-
use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProvider\DummyProvider;
20+
use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProviderFactory\CustomProviderFactory;
21+
use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProviderFactory\DummyProviderFactory;
2122
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
2223
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
2324
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
@@ -68,16 +69,80 @@ public function testInvalidCheckPath()
6869
$container->compile();
6970
}
7071

72+
public function testFirewallWithCustomUserProvider()
73+
{
74+
$container = $this->getRawContainer();
75+
76+
$extension = $container->getExtension('security');
77+
$extension->addUserProviderFactory(new CustomProviderFactory());
78+
79+
$container->loadFromExtension('security', [
80+
'providers' => [
81+
'my_app_provider' => [
82+
'custom' => [
83+
'foo' => 'baz',
84+
],
85+
],
86+
],
87+
88+
'firewalls' => [
89+
'some_firewall' => [
90+
'pattern' => '/.*',
91+
'http_basic' => [],
92+
],
93+
],
94+
]);
95+
96+
$container->compile();
97+
98+
$this->assertTrue($container->hasDefinition('security.user.provider.concrete.my_app_provider'));
99+
$this->assertEquals('baz', $container->getDefinition('security.user.provider.concrete.my_app_provider')->getArgument('$foo'));
100+
}
101+
71102
public function testFirewallWithInvalidUserProvider()
72103
{
73104
$container = $this->getRawContainer();
74105

75106
$extension = $container->getExtension('security');
76-
$extension->addUserProviderFactory(new DummyProvider());
107+
$extension->addUserProviderFactory(new CustomProviderFactory());
108+
109+
$container->loadFromExtension('security', [
110+
'providers' => [
111+
'my_app_provider' => [
112+
'some_other' => [
113+
'bar' => 'baz',
114+
],
115+
],
116+
],
117+
118+
'firewalls' => [
119+
'some_firewall' => [
120+
'pattern' => '/.*',
121+
'http_basic' => [],
122+
],
123+
],
124+
]);
125+
126+
$this->expectException(InvalidConfigurationException::class);
127+
$this->expectExceptionMessage('Unrecognized option "some_other" under "security.providers.my_app_provider". Available options are "chain", "custom", "id", "ldap", "memory".');
128+
129+
$container->compile();
130+
}
131+
132+
public function testFirewallWithInvalidUserProviderConfig()
133+
{
134+
$container = $this->getRawContainer();
135+
136+
$extension = $container->getExtension('security');
137+
$extension->addUserProviderFactory(new CustomProviderFactory());
77138

78139
$container->loadFromExtension('security', [
79140
'providers' => [
80-
'my_foo' => ['foo' => []],
141+
'my_app_provider' => [
142+
'custom' => [
143+
'bar' => 'baz',
144+
],
145+
],
81146
],
82147

83148
'firewalls' => [
@@ -89,9 +154,42 @@ public function testFirewallWithInvalidUserProvider()
89154
]);
90155

91156
$this->expectException(InvalidConfigurationException::class);
92-
$this->expectExceptionMessage('Unable to create definition for "security.user.provider.concrete.my_foo" user provider');
157+
$this->expectExceptionMessage('Unrecognized option "bar" under "security.providers.my_app_provider.custom". Available option is "foo".');
158+
159+
$container->compile();
160+
}
161+
162+
public function testFirewallWithUserProviderWithoutConfig()
163+
{
164+
$container = $this->getRawContainer();
165+
166+
$extension = $container->getExtension('security');
167+
$extension->addUserProviderFactory(new DummyProviderFactory());
168+
169+
$container->loadFromExtension('security', [
170+
'providers' => [
171+
'my_app_provider' => [
172+
'foo' => null,
173+
],
174+
'my_other_app_provider' => [
175+
'foo' => [],
176+
],
177+
],
178+
179+
'firewalls' => [
180+
'some_firewall' => [
181+
'pattern' => '/.*',
182+
'http_basic' => [
183+
'provider' => 'my_app_provider',
184+
],
185+
],
186+
],
187+
]);
93188

94189
$container->compile();
190+
191+
$this->assertTrue($container->hasDefinition('security.user.provider.concrete.my_app_provider'));
192+
$this->assertTrue($container->hasDefinition('security.user.provider.concrete.my_other_app_provider'));
95193
}
96194

97195
public function testDisableRoleHierarchyVoter()

Tests/DependencyInjection/XmlCustomProviderTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
16-
use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProvider\CustomProvider;
16+
use Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Fixtures\UserProviderFactory\CustomProviderFactory;
1717
use Symfony\Component\Config\FileLocator;
1818
use Symfony\Component\DependencyInjection\ContainerBuilder;
1919
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
@@ -30,7 +30,7 @@ public function testCustomProviderElement(string $configurationFile)
3030
$container->register('cache.system', \stdClass::class);
3131

3232
$security = new SecurityExtension();
33-
$security->addUserProviderFactory(new CustomProvider());
33+
$security->addUserProviderFactory(new CustomProviderFactory());
3434
$container->registerExtension($security);
3535

3636
(new XmlFileLoader($container, new FileLocator(__DIR__.'/Fixtures/xml')))->load($configurationFile);

0 commit comments

Comments
 (0)