BootstrapCommandService::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
nc 1
nop 8
dl 0
loc 10
rs 10
c 1
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * Copyright 2020 SURFnet bv
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace Surfnet\StepupMiddleware\MiddlewareBundle\Service;
20
21
use Ramsey\Uuid\Uuid;
22
use Surfnet\Stepup\Configuration\Value\Institution as ConfigurationInstitution;
23
use Surfnet\Stepup\Identity\Value\Institution;
24
use Surfnet\Stepup\Identity\Value\NameId;
25
use Surfnet\StepupMiddleware\ApiBundle\Configuration\Entity\InstitutionConfigurationOptions;
26
use Surfnet\StepupMiddleware\ApiBundle\Configuration\Repository\InstitutionConfigurationOptionsRepository;
27
use Surfnet\StepupMiddleware\ApiBundle\Identity\Entity\Identity;
28
use Surfnet\StepupMiddleware\ApiBundle\Identity\Entity\VettedSecondFactor;
29
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\IdentityRepository;
30
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\UnverifiedSecondFactorRepository;
31
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\VerifiedSecondFactorRepository;
32
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\VettedSecondFactorRepository;
33
use Surfnet\StepupMiddleware\CommandHandlingBundle\Command\Metadata;
34
use Surfnet\StepupMiddleware\CommandHandlingBundle\EventSourcing\MetadataEnricher;
35
use Surfnet\StepupMiddleware\CommandHandlingBundle\Identity\Command\CreateIdentityCommand;
36
use Surfnet\StepupMiddleware\CommandHandlingBundle\Identity\Command\MigrateVettedSecondFactorCommand as CommandHandlingMigrateSecondFactorCommand;
37
use Surfnet\StepupMiddleware\CommandHandlingBundle\Identity\Command\ProveGssfPossessionCommand;
38
use Surfnet\StepupMiddleware\CommandHandlingBundle\Identity\Command\ProvePhonePossessionCommand;
39
use Surfnet\StepupMiddleware\CommandHandlingBundle\Identity\Command\ProveYubikeyPossessionCommand;
40
use Surfnet\StepupMiddleware\CommandHandlingBundle\Identity\Command\VerifyEmailCommand;
41
use Surfnet\StepupMiddleware\CommandHandlingBundle\Identity\Command\VetSecondFactorCommand;
42
use Surfnet\StepupMiddleware\CommandHandlingBundle\Pipeline\Pipeline;
43
use Surfnet\StepupMiddleware\MiddlewareBundle\Exception\InvalidArgumentException;
44
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
45
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
46
47
/**
48
 * @SuppressWarnings("PHPMD.CouplingBetweenObjects")
49
 * @SuppressWarnings("PHPMD.TooManyPublicMethods")
50
 */
51
class BootstrapCommandService
52
{
53
    /**
54
     * @var string[]
55
     */
56
    private array $validRegistrationStatuses = ['unverified', 'verified', 'vetted'];
57
58
    public function __construct(
59
        private readonly Pipeline $pipeline,
60
        private readonly MetadataEnricher $enricher,
61
        private readonly TokenStorageInterface $tokenStorage,
62
        private readonly IdentityRepository $identityRepository,
63
        private readonly UnverifiedSecondFactorRepository $unverifiedSecondFactorRepository,
64
        private readonly VerifiedSecondFactorRepository $verifiedSecondFactorRepository,
65
        private readonly VettedSecondFactorRepository $vettedSecondFactorRepository,
66
        private readonly InstitutionConfigurationOptionsRepository $institutionConfigurationRepository,
67
    ) {
68
    }
69
70
    public function setToken(TokenInterface $token): void
71
    {
72
        $this->tokenStorage->setToken($token);
73
    }
74
75
    public function validRegistrationStatus(string $registrationStatus): void
76
    {
77
        if (!in_array($registrationStatus, $this->validRegistrationStatuses)) {
78
            throw new InvalidArgumentException(
79
                sprintf(
80
                    'Invalid argument provided for the "registration-status" argument. One of: %s is expected. Received: "%s"',
81
                    implode(', ', $this->validRegistrationStatuses),
82
                    $registrationStatus,
83
                ),
84
            );
85
        }
86
    }
87
88
    public function requiresMailVerification(string $institution): bool
89
    {
90
        $configuration = $this->institutionConfigurationRepository->findConfigurationOptionsFor(
91
            new ConfigurationInstitution($institution),
92
        );
93
        if ($configuration instanceof InstitutionConfigurationOptions) {
94
            return $configuration->verifyEmailOption->isEnabled();
95
        }
96
        return true;
97
    }
98
99
    public function vetSecondFactor(
100
        string $tokenType,
101
        string $actorId,
102
        Identity $identity,
103
        string $secondFactorId,
104
        string $secondFactorIdentifier,
105
    ): void {
106
        $verifiedSecondFactor = $this->verifiedSecondFactorRepository->findOneBy(
107
            ['identityId' => $identity->id, 'type' => $tokenType],
108
        );
109
110
        $command = new VetSecondFactorCommand();
111
        $command->UUID = (string)Uuid::uuid4();
112
        $command->authorityId = $actorId;
113
        $command->identityId = $identity->id;
114
        $command->secondFactorId = $secondFactorId;
115
        $command->registrationCode = $verifiedSecondFactor->registrationCode;
116
        $command->secondFactorType = $tokenType;
117
        $command->secondFactorIdentifier = $secondFactorIdentifier;
118
        $command->documentNumber = '123987';
119
        $command->identityVerified = true;
120
121
        $this->pipeline->process($command);
122
    }
123
124
    public function createIdentity(
125
        Institution $institution,
126
        NameId $nameId,
127
        string $commonName,
128
        string $email,
129
        string $preferredLocale,
130
    ): CreateIdentityCommand {
131
        $command = new CreateIdentityCommand();
132
        $command->UUID = (string)Uuid::uuid4();
133
        $command->id = (string)Uuid::uuid4();
134
        $command->institution = $institution->getInstitution();
135
        $command->nameId = $nameId->getNameId();
136
        $command->commonName = $commonName;
137
        $command->email = $email;
138
        $command->preferredLocale = $preferredLocale;
139
140
        $this->pipeline->process($command);
141
142
        return $command;
143
    }
144
145
    public function proveGsspPossession(
146
        string $secondFactorId,
147
        Identity $identity,
148
        string $tokenType,
149
        string $tokenIdentifier
150
    ): void {
151
        $command = new ProveGssfPossessionCommand();
152
        $command->UUID = (string)Uuid::uuid4();
153
        $command->secondFactorId = $secondFactorId;
154
        $command->identityId = $identity->id;
155
        $command->stepupProvider = $tokenType;
156
        $command->gssfId = $tokenIdentifier;
157
158
        $this->pipeline->process($command);
159
    }
160
161
    public function provePhonePossession(
162
        string $secondFactorId,
163
        Identity $identity,
164
        string $phoneNumber
165
    ): void {
166
        $command = new ProvePhonePossessionCommand();
167
        $command->UUID = (string)Uuid::uuid4();
168
        $command->secondFactorId = $secondFactorId;
169
        $command->identityId = $identity->id;
170
        $command->phoneNumber = $phoneNumber;
171
172
        $this->pipeline->process($command);
173
    }
174
175
    public function proveYubikeyPossession(
176
        string $secondFactorId,
177
        Identity $identity,
178
        string $yubikeyPublicId
179
    ): void {
180
        $command = new ProveYubikeyPossessionCommand();
181
        $command->UUID = (string)Uuid::uuid4();
182
        $command->secondFactorId = $secondFactorId;
183
        $command->identityId = $identity->id;
184
        $command->yubikeyPublicId = $yubikeyPublicId;
185
186
        $this->pipeline->process($command);
187
    }
188
189
    public function verifyEmail(
190
        Identity $identity,
191
        string $tokenType
192
    ): void {
193
        $unverifiedSecondFactor = $this->unverifiedSecondFactorRepository->findOneBy(
194
            ['identityId' => $identity->id, 'type' => $tokenType],
195
        );
196
197
        $command = new VerifyEmailCommand();
198
        $command->UUID = (string)Uuid::uuid4();
199
        $command->identityId = $identity->id;
200
        $command->verificationNonce = $unverifiedSecondFactor->verificationNonce;
201
202
        $this->pipeline->process($command);
203
    }
204
205
    public function migrateVettedSecondFactor(
206
        Identity $sourceIdentity,
207
        Identity $targetIdentity,
208
        VettedSecondFactor $vettedSecondFactor,
209
    ): void {
210
        $command = new CommandHandlingMigrateSecondFactorCommand();
211
        $command->UUID = (string)Uuid::uuid4();
212
        $command->sourceIdentityId = $sourceIdentity->id;
213
        $command->targetIdentityId = $targetIdentity->id;
214
        $command->sourceSecondFactorId = $vettedSecondFactor->id;
215
        $command->targetSecondFactorId = (string)Uuid::uuid4();
216
217
        $this->pipeline->process($command);
218
    }
219
220
    public function enrichEventMetadata(string $actorId): void
221
    {
222
        $actor = $this->identityRepository->findOneBy(['id' => $actorId]);
223
224
        $metadata = new Metadata();
225
        $metadata->actorId = $actor->id;
226
        $metadata->actorInstitution = $actor->institution;
227
        $this->enricher->setMetadata($metadata);
228
    }
229
230
    public function getIdentity(NameId $nameId, Institution $institution): Identity
231
    {
232
        return $this->identityRepository->findOneByNameIdAndInstitution($nameId, $institution);
233
    }
234
235
    public function getIdentityByNameId(NameId $nameId): ?Identity
236
    {
237
        return $this->identityRepository->findOneByNameId($nameId);
238
    }
239
240
    public function identityExists(NameId $nameId, Institution $institution): bool
241
    {
242
        return $this->identityRepository->hasIdentityWithNameIdAndInstitution($nameId, $institution);
243
    }
244
245
    /**
246
     * @return array|VettedSecondFactor[]
247
     */
248
    public function getVettedSecondFactorsFromIdentity(Identity $identity): array
249
    {
250
        return $this->vettedSecondFactorRepository->findBy(['identityId' => $identity->id]);
251
    }
252
}
253