Passed
Push — master ( 1bb2de...d52d38 )
by Gerard
02:56
created

addSecurityEncodersConfig()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 9
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gbere\SimpleAuth\DependencyInjection;
6
7
use Exception;
8
use Gbere\SimpleAuth\Repository\AdminUserRepository;
9
use Gbere\SimpleAuth\Repository\UserRepository;
10
use Gbere\SimpleAuth\Security\Constant;
11
use Gbere\SimpleAuth\Security\LoginFormAuthenticator;
12
use Symfony\Component\Config\FileLocator;
13
use Symfony\Component\DependencyInjection\ContainerBuilder;
14
use Symfony\Component\DependencyInjection\Definition;
15
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
16
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
17
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
18
19
class GbereSimpleAuthExtension extends Extension implements PrependExtensionInterface
20
{
21
    /** @var array|null */
22
    private $securityConfig;
23
    /** @var array|null */
24
    private $config;
25
26
    /**
27
     * @throws Exception
28
     */
29
    public function load(array $configs, ContainerBuilder $container): void
30
    {
31
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
32
        $loader->load('services.yaml');
33
34
        $definition = $container->getDefinition(UserRepository::class);
35
        $definition->setArgument(1, new Definition($this->config['user']['entity']));
36
37
        $definition = $container->getDefinition(AdminUserRepository::class);
38
        $definition->setArgument(1, new Definition($this->config['admin_user']['entity']));
39
    }
40
41
    public function prepend(ContainerBuilder $container): void
42
    {
43
        $configs = $container->getExtensionConfig($this->getAlias());
44
        $this->config = $this->processConfiguration(new Configuration(), $configs);
45
46
        if ('test' === $container->getParameter('kernel.environment')) {
47
            $this->addSecurityTestingRoutesConfig();
48
        }
49
50
        $this->addSecurityEncodersConfig();
51
        $this->addSecurityProvidersConfig();
52
        $this->addSecurityFirewallConfig();
53
54
        $this->updateSecurityExtensionConfig($container);
55
    }
56
57
    private function addSecurityTestingRoutesConfig(): void
58
    {
59
        $this->securityConfig['access_control'] = constant::TESTING_ROUTES;
60
    }
61
62
    private function addSecurityEncodersConfig(): void
63
    {
64
        if (isset($this->config['user'])) {
65
            $this->securityConfig['encoders'] = [
66
                $this->config['user']['entity'] => [
67
                    'algorithm' => $this->config['user']['encoder_algorithm'],
68
                ],
69
                $this->config['admin_user']['entity'] => [
70
                    'algorithm' => $this->config['admin_user']['encoder_algorithm'],
71
                ],
72
            ];
73
        }
74
    }
75
76
    private function addSecurityProvidersConfig(): void
77
    {
78
        if (isset($this->config['user'])) {
79
            $this->securityConfig['providers'] = [
80
                Constant::PROVIDER_NAME => [
81
                    'entity' => [
82
                        'class' => $this->config['user']['entity'],
83
                        'property' => 'email',
84
                    ],
85
                ],
86
            ];
87
        }
88
    }
89
90
    private function addSecurityFirewallConfig(): void
91
    {
92
        $this->securityConfig['firewalls'] = [
93
            Constant::FIREWALL_NAME => [
94
                'anonymous' => 'lazy',
95
                'provider' => Constant::PROVIDER_NAME,
96
                'guard' => [
97
                    'authenticators' => [LoginFormAuthenticator::class],
98
                ],
99
                'logout' => [
100
                    'path' => 'gbere_auth_logout',
101
                ],
102
            ],
103
        ];
104
105
        if (isset($this->config['remember_me_lifetime']) && null != $this->config['remember_me_lifetime']) {
106
            $this->securityConfig['firewalls'][Constant::FIREWALL_NAME]['remember_me'] = [
107
                'secret' => '%kernel.secret%',
108
                'lifetime' => $this->config['remember_me_lifetime'],
109
            ];
110
        }
111
    }
112
113
    private function updateSecurityExtensionConfig(ContainerBuilder $container): void
114
    {
115
        if (null === $this->securityConfig) {
116
            return;
117
        }
118
119
        $extensionConfigsRefl = new \ReflectionProperty(ContainerBuilder::class, 'extensionConfigs');
120
        $extensionConfigsRefl->setAccessible(true);
121
        $extensionConfigs = $extensionConfigsRefl->getValue($container);
122
123
        foreach ($this->securityConfig as $section => $configs) {
124
            if (isset($extensionConfigs['security'][0][$section])) {
125
                // Constant::FIREWALL_NAME must be inserted after the firewall->dev
126
                if ('firewalls' === $section) {
127
                    $extensionConfigs['security'][0][$section] = array_merge($extensionConfigs['security'][0][$section], $configs);
128
                } else {
129
                    $extensionConfigs['security'][0][$section] = array_merge($configs, $extensionConfigs['security'][0][$section]);
130
                }
131
            } else {
132
                $extensionConfigs['security'][0][$section] = $configs;
133
            }
134
        }
135
136
        $extensionConfigsRefl->setValue($container, $extensionConfigs);
137
    }
138
}
139