Issues (222)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/DependencyInjection/Modules/User.php (1 issue)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright (C) 2020-2025 Iain Cambridge
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
10
 * the Free Software Foundation, either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace Parthenon\DependencyInjection\Modules;
23
24
use Parthenon\Common\Exception\NonExistentClass;
25
use Parthenon\Common\Exception\ParameterNotSetException;
26
use Parthenon\User\Entity\TeamInterface;
27
use Parthenon\User\Entity\UserInterface;
28
use Parthenon\User\Gdpr\Deletion\DeleterInterface;
29
use Parthenon\User\Gdpr\Deletion\VoterInterface;
30
use Parthenon\User\Gdpr\Export\ExporterInterface;
31
use Parthenon\User\Gdpr\Export\FormatterInterface;
32
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
33
use Symfony\Component\Config\FileLocator;
34
use Symfony\Component\DependencyInjection\ContainerBuilder;
35
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
36
37
final class User implements ModuleConfigurationInterface
38
{
39
    public function addConfig(NodeBuilder $nodeBuilder): void
40
    {
41
        $nodeBuilder
42
            ->arrayNode('user')
43
                ->children()
44
                    ->booleanNode('enabled')->defaultValue(false)->end()
45
                    ->scalarNode('user_class')->end()
0 ignored issues
show
The method scalarNode() does not exist on Symfony\Component\Config...der\NodeParentInterface. It seems like you code against a sub-type of Symfony\Component\Config...der\NodeParentInterface such as Symfony\Component\Config...ion\Builder\NodeBuilder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

45
                    ->/** @scrutinizer ignore-call */ scalarNode('user_class')->end()
Loading history...
46
                    ->booleanNode('email_confirmation')->defaultValue(true)->end()
47
                    ->booleanNode('signed_in_after_signup')->defaultValue(false)->end()
48
                    ->booleanNode('user_invites_enabled')->defaultValue(false)->end()
49
                    ->scalarNode('login_route')->defaultValue('parthenon_user_login')->end()
50
                    ->scalarNode('login_redirect_route')->defaultValue('parthenon_user_profile')->end()
51
                    ->scalarNode('signup_success_route')->defaultValue('parthenon_user_signed_up')->end()
52
                    ->booleanNode('teams_enabled')->defaultValue(false)->end()
53
                    ->booleanNode('teams_invites_enabled')->defaultValue(false)->end()
54
                    ->booleanNode('self_signup_enabled')->defaultValue(true)->end()
55
                    ->scalarNode('team_class')->end()
56
                    ->scalarNode('firewall_name')->end()
57
                    ->arrayNode('roles')
58
                        ->children()
59
                            ->scalarNode('default_role')->defaultValue('ROLE_USER')->end()
60
                            ->arrayNode('user_assignable')
61
                                 ->useAttributeAsKey('name')
62
                                ->scalarPrototype()->end()
63
                            ->end()
64
                            ->arrayNode('athena_assignable')
65
                                ->useAttributeAsKey('name')
66
                                ->scalarPrototype()->end()
67
                            ->end()
68
                        ->end()
69
                    ->end()
70
                    ->arrayNode('gdpr')
71
                        ->children()
72
                            ->arrayNode('export')
73
                                ->children()
74
                                ->scalarNode('export_format')->end()
75
                                ->end()
76
                            ->end()
77
                        ->end()
78
                    ->end()
79
                ->end()
80
            ->end();
81
    }
82
83
    public function handleDefaultParameters(ContainerBuilder $container): void
84
    {
85
        $container->setParameter('parthenon_user_login_route', 'parthenon_user_login');
86
        $container->setParameter('parthenon_user_signup_success_route', 'parthenon_user_signed_up');
87
        $container->setParameter('parthenon_user_users_invites_enabled', false);
88
        $container->setParameter('parthenon_user_teams_enabled', false);
89
        $container->setParameter('parthenon_user_team_class', null);
90
        $container->setParameter('parthenon_user_teams_invites_enabled', false);
91
        $container->setParameter('parthenon_user_gdpr_formatter_type', 'json');
92
        $container->setParameter('parthenon_user_roles_default_role', 'ROLE_USER');
93
        $container->setParameter('parthenon_user_roles_user_assignable_roles', []);
94
        $container->setParameter('parthenon_user_roles_athena_assignable_roles', []);
95
        $container->setParameter('parthenon_user_self_signup_enabled', true);
96
        $container->setParameter('parthenon_user_email_confirmation', true);
97
        $container->setParameter('parthenon_user_signed_in_after_signup', false);
98
        $container->setParameter('parthenon_user_firewall_name', 'main');
99
    }
100
101
    public function handleConfiguration(array $config, ContainerBuilder $container): void
102
    {
103
        if (!isset($config['user']) || !isset($config['user']['enabled']) || false == $config['user']['enabled']) {
104
            return;
105
        }
106
        $container->setParameter('parthenon_user_enabled', true);
107
108
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../../Resources/config'));
109
        $bundles = $container->getParameter('kernel.bundles');
110
111
        $this->configureMongoDb($bundles, $loader);
112
        $this->configureDoctrine($bundles, $loader);
113
114
        $loader->load('services/user.xml');
115
116
        $this->configureAutotagging($container);
117
        $config = $this->configureUserClass($config, $container);
118
        $config = $this->configureSignupSuccessRoute($config, $container);
119
        $config = $this->configureLoginRoute($config, $container);
120
        $config = $this->configureUserInvitesEnabled($config, $container);
121
        $config = $this->configureTeamsInviteEnabled($config, $container);
122
        $config = $this->configureGdprFormatterType($config, $container);
123
        $config = $this->configureRoles($config, $container);
124
        $config = $this->configureSelfSignup($config, $container);
125
        $config = $this->configureEmailConfirmation($config, $container);
126
        $config = $this->configureSignedInAfterSignup($config, $container);
127
        $config = $this->configureFirewall($config, $container);
128
129
        $this->configureTeams($config, $container);
130
    }
131
132
    /**
133
     * @throws NonExistentClass
134
     * @throws ParameterNotSetException
135
     */
136
    private function configureTeams(array $config, ContainerBuilder $container): void
137
    {
138
        if (isset($config['user']['teams_enabled']) && $config['user']['teams_enabled']) {
139
            $container->setParameter('parthenon_user_teams_enabled_flag', true);
140
            $container->setParameter('parthenon_user_teams_enabled', $config['user']['teams_enabled']);
141
            if (!isset($config['user']['team_class']) || empty($config['user']['team_class'])) {
142
                throw new ParameterNotSetException('When the user module is enabled and teams are enabled the team_class must be defined');
143
            }
144
145
            if (!class_exists($config['user']['team_class'])) {
146
                throw new NonExistentClass(sprintf("The class '%s' does not exist.", $config['user']['team_class']));
147
            }
148
149
            $teamDdfinition = $container->getDefinition(TeamInterface::class);
150
            $teamDdfinition->setClass($config['user']['team_class']);
151
            $container->setDefinition(TeamInterface::class, $teamDdfinition);
152
        }
153
    }
154
155
    private function configureGdprFormatterType(array $config, ContainerBuilder $container): array
156
    {
157
        if (isset($config['user']['gdpr']['export']['formatter_type']) && !empty($config['user']['gdpr']['export']['formatter_type'])) {
158
            $container->setParameter('parthenon_user_gdpr_formatter_type', $config['user']['gdpr']['export']['formatter_type']);
159
        }
160
161
        return $config;
162
    }
163
164
    private function configureTeamsInviteEnabled(array $config, ContainerBuilder $container): array
165
    {
166
        if (isset($config['user']['teams_invites_enabled'])) {
167
            $container->setParameter('parthenon_user_teams_invites_enabled', $config['user']['teams_invites_enabled']);
168
        }
169
170
        return $config;
171
    }
172
173
    private function configureUserInvitesEnabled(array $config, ContainerBuilder $container): array
174
    {
175
        if (isset($config['user']['user_invites_enabled'])) {
176
            $container->setParameter('parthenon_user_users_invites_enabled', $config['user']['user_invites_enabled']);
177
        }
178
179
        return $config;
180
    }
181
182
    private function configureRoles(array $config, ContainerBuilder $containerBuilder): array
183
    {
184
        if (!isset($config['user']['roles'])) {
185
            return $config;
186
        }
187
188
        $containerBuilder->setParameter('parthenon_user_roles_default_role', $config['user']['roles']['default_role'] ?? 'ROLE_USER');
189
        $containerBuilder->setParameter('parthenon_user_roles_user_assignable_roles', $config['user']['roles']['user_assignable'] ?? []);
190
        $containerBuilder->setParameter('parthenon_user_roles_athena_assignable_roles', $config['user']['roles']['athena_assignable'] ?? []);
191
192
        return $config;
193
    }
194
195
    private function configureLoginRoute(array $config, ContainerBuilder $container): array
196
    {
197
        if (isset($config['user']['login_route'])) {
198
            $container->setParameter('parthenon_user_login_route', $config['user']['login_route']);
199
        }
200
201
        return $config;
202
    }
203
204
    private function configureSignupSuccessRoute(array $config, ContainerBuilder $container): array
205
    {
206
        if (isset($config['user']['signup_success_route'])) {
207
            $container->setParameter('parthenon_user_signup_success_route', $config['user']['signup_success_route']);
208
        }
209
210
        return $config;
211
    }
212
213
    private function configureEmailConfirmation(array $config, ContainerBuilder $container): array
214
    {
215
        if (isset($config['user']['email_confirmation'])) {
216
            $container->setParameter('parthenon_user_email_confirmation', $config['user']['email_confirmation']);
217
        }
218
219
        return $config;
220
    }
221
222
    private function configureFirewall(array $config, ContainerBuilder $container): array
223
    {
224
        if (isset($config['user']['firewall_name'])) {
225
            $container->setParameter('parthenon_user_firewall_name', $config['user']['firewall_name']);
226
        }
227
228
        return $config;
229
    }
230
231
    private function configureSignedInAfterSignup(array $config, ContainerBuilder $container): array
232
    {
233
        if (isset($config['user']['signed_in_after_signup'])) {
234
            $container->setParameter('parthenon_user_signed_in_after_signup', $config['user']['signed_in_after_signup']);
235
        }
236
237
        return $config;
238
    }
239
240
    private function configureSelfSignup(array $config, ContainerBuilder $container): array
241
    {
242
        if (isset($config['user']['self_signup_enabled'])) {
243
            $container->setParameter('parthenon_user_self_signup_enabled', $config['user']['self_signup_enabled']);
244
        }
245
246
        return $config;
247
    }
248
249
    private function configureAutotagging(ContainerBuilder $container): void
250
    {
251
        $container->registerForAutoconfiguration(ExporterInterface::class)->addTag('parthenon.user.gdpr.export.exporter');
252
        $container->registerForAutoconfiguration(FormatterInterface::class)->addTag('parthenon.user.gdpr.export.formatter');
253
        $container->registerForAutoconfiguration(DeleterInterface::class)->addTag('parthenon.user.gdpr.delete.deleter');
254
        $container->registerForAutoconfiguration(VoterInterface::class)->addTag('parthenon.user.gdpr.delete.voter');
255
    }
256
257
    /**
258
     * @throws \Exception
259
     */
260
    private function configureDoctrine(float|array|bool|int|string|null $bundles, XmlFileLoader $loader): string|int|bool|array|float|null
261
    {
262
        if (isset($bundles['DoctrineBundle'])) {
263
            $loader->load('services/orm/user.xml');
264
        }
265
266
        return $bundles;
267
    }
268
269
    /**
270
     * @throws \Exception
271
     */
272
    private function configureMongoDb(float|int|bool|array|string|null $bundles, XmlFileLoader $loader): void
273
    {
274
        if (isset($bundles['DoctrineMongoDBBundle'])) {
275
            $loader->load('services/odm/user.xml');
276
        }
277
    }
278
279
    /**
280
     * @throws NonExistentClass
281
     * @throws ParameterNotSetException
282
     */
283
    private function configureUserClass(array $config, ContainerBuilder $container): array
284
    {
285
        if (!isset($config['user']['user_class']) || empty($config['user']['user_class'])) {
286
            throw new ParameterNotSetException('When the user module is enabled the user_class must be defined');
287
        }
288
289
        if (!class_exists($config['user']['user_class'])) {
290
            throw new NonExistentClass(sprintf("The class '%s' does not exist.", $config['user']['user_class']));
291
        }
292
293
        $userDefintion = $container->getDefinition(UserInterface::class);
294
        $userDefintion->setClass($config['user']['user_class']);
295
        $container->setDefinition(UserInterface::class, $userDefintion);
296
297
        return $config;
298
    }
299
}
300