VettingService   A
last analyzed

Complexity

Total Complexity 33

Size/Duplication

Total Lines 437
Duplicated Lines 7.32 %

Coupling/Cohesion

Components 1
Dependencies 32

Importance

Changes 0
Metric Value
wmc 33
lcom 1
cbo 32
dl 32
loc 437
rs 9.76
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 23 1
A isLoaSufficientToStartProcedure() 0 6 1
A isExpiredRegistrationCode() 0 10 1
A startProcedure() 0 28 2
A cancelProcedure() 16 16 3
A getSmsOtpRequestsRemainingCount() 0 4 1
A getSmsMaximumOtpRequestsCount() 0 4 1
A sendSmsChallenge() 0 21 2
A verifyPhoneNumber() 0 15 2
A verifyYubikeyPublicId() 0 18 2
A startGssfVerification() 0 6 1
A verifyGssfId() 0 15 2
A createU2fSignRequest() 0 11 1
A verifyU2fAuthentication() 0 19 2
A verifyIdentity() 0 7 1
A vet() 0 24 2
A getIdentityCommonName() 0 4 1
A getSecondFactorIdentifier() 0 4 1
A getProcedure() 16 16 3
A hasProcedure() 0 8 2
A isProvePossessionSkippable() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * Copyright 2014 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\StepupRa\RaBundle\Service;
20
21
use DateInterval;
22
use RuntimeException;
23
use Surfnet\StepupBundle\Command\SendSmsChallengeCommand;
24
use Surfnet\StepupBundle\Command\VerifyPossessionOfPhoneCommand;
25
use Surfnet\StepupBundle\Service\SecondFactorTypeService;
26
use Surfnet\StepupBundle\Service\SmsSecondFactor\OtpVerification;
27
use Surfnet\StepupBundle\Service\SmsSecondFactorServiceInterface;
28
use Surfnet\StepupBundle\Value\PhoneNumber\InternationalPhoneNumber;
29
use Surfnet\StepupBundle\Value\SecondFactorType;
30
use Surfnet\StepupMiddlewareClientBundle\Identity\Service\SecondFactorService;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Surfnet\StepupRa\RaBundl...ice\SecondFactorService.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
31
use Surfnet\StepupMiddlewareClientBundle\Identity\Command\VetSecondFactorCommand;
32
use Surfnet\StepupRa\RaBundle\Command\CreateU2fSignRequestCommand;
33
use Surfnet\StepupRa\RaBundle\Command\StartVettingProcedureCommand;
34
use Surfnet\StepupRa\RaBundle\Command\VerifyIdentityCommand;
35
use Surfnet\StepupRa\RaBundle\Command\VerifyU2fAuthenticationCommand;
36
use Surfnet\StepupRa\RaBundle\Command\VerifyYubikeyPublicIdCommand;
37
use Surfnet\StepupRa\RaBundle\Exception\DomainException;
38
use Surfnet\StepupRa\RaBundle\Exception\InvalidArgumentException;
39
use Surfnet\StepupRa\RaBundle\Exception\LoaTooLowException;
40
use Surfnet\StepupRa\RaBundle\Exception\UnknownVettingProcedureException;
41
use Surfnet\StepupRa\RaBundle\Repository\VettingProcedureRepository;
42
use Surfnet\StepupRa\RaBundle\Service\Gssf\VerificationResult as GssfVerificationResult;
43
use Surfnet\StepupRa\RaBundle\Service\U2f\AuthenticationVerificationResult;
44
use Surfnet\StepupRa\RaBundle\Service\U2f\SignRequestCreationResult;
45
use Surfnet\StepupRa\RaBundle\Value\DateTime;
46
use Surfnet\StepupRa\RaBundle\VettingProcedure;
47
use Surfnet\StepupU2fBundle\Dto\SignRequest;
48
use Surfnet\StepupU2fBundle\Dto\SignResponse;
49
use Symfony\Component\Translation\TranslatorInterface;
50
51
/**
52
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
53
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
54
 */
55
class VettingService
56
{
57
    const REGISTRATION_CODE_EXPIRED_ERROR =
58
        'Surfnet\Stepup\Exception\DomainException: Cannot vet second factor, the registration window is closed.';
59
60
    /**
61
     * @var \Surfnet\StepupBundle\Service\SmsSecondFactorServiceInterface
62
     */
63
    private $smsSecondFactorService;
64
65
    /**
66
     * @var \Surfnet\StepupRa\RaBundle\Service\YubikeySecondFactorService
67
     */
68
    private $yubikeySecondFactorService;
69
70
    /**
71
     * @var \Surfnet\StepupRa\RaBundle\Service\GssfService
72
     */
73
    private $gssfService;
74
75
    /**
76
     * @var \Surfnet\StepupRa\RaBundle\Service\U2fService
77
     */
78
    private $u2fService;
79
80
    /**
81
     * @var \Surfnet\StepupRa\RaBundle\Service\CommandService
82
     */
83
    private $commandService;
84
85
    /**
86
     * @var \Surfnet\StepupRa\RaBundle\Repository\VettingProcedureRepository
87
     */
88
    private $vettingProcedureRepository;
89
90
    /**
91
     * @var \Symfony\Component\Translation\TranslatorInterface
92
     */
93
    private $translator;
94
95
    /**
96
     * @var \Surfnet\StepupRa\RaBundle\Service\IdentityService
97
     */
98
    private $identityService;
99
100
    /**
101
     * @var \Surfnet\StepupBundle\Service\SecondFactorTypeService
102
     */
103
    private $secondFactorTypeService;
104
105
    /**
106
     * @var SecondFactorService
107
     */
108
    private $secondFactorService;
109
110
    /**
111
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
112
     */
113
    public function __construct(
114
        SmsSecondFactorServiceInterface $smsSecondFactorService,
115
        YubikeySecondFactorService $yubikeySecondFactorService,
116
        GssfService $gssfService,
117
        U2fService $u2fService,
118
        CommandService $commandService,
119
        VettingProcedureRepository $vettingProcedureRepository,
120
        TranslatorInterface $translator,
121
        IdentityService $identityService,
122
        SecondFactorTypeService $secondFactorTypeService,
123
        SecondFactorService $secondFactorService
124
    ) {
125
        $this->smsSecondFactorService = $smsSecondFactorService;
126
        $this->yubikeySecondFactorService = $yubikeySecondFactorService;
127
        $this->gssfService = $gssfService;
128
        $this->u2fService = $u2fService;
129
        $this->commandService = $commandService;
130
        $this->vettingProcedureRepository = $vettingProcedureRepository;
131
        $this->translator = $translator;
132
        $this->identityService = $identityService;
133
        $this->secondFactorTypeService = $secondFactorTypeService;
134
        $this->secondFactorService = $secondFactorService;
135
    }
136
137
    /**
138
     * @param StartVettingProcedureCommand $command
139
     * @return bool
140
     */
141
    public function isLoaSufficientToStartProcedure(StartVettingProcedureCommand $command)
142
    {
143
        $secondFactorType = new SecondFactorType($command->secondFactor->type);
144
145
        return $this->secondFactorTypeService->isSatisfiedBy($secondFactorType, $command->authorityLoa);
146
    }
147
148
    /**
149
     * @param StartVettingProcedureCommand $command
150
     * @return bool
151
     */
152
    public function isExpiredRegistrationCode(StartVettingProcedureCommand $command)
153
    {
154
        return DateTime::now()->comesAfter(
155
            new DateTime(
156
                $command->secondFactor->registrationRequestedAt
157
                    ->add(new DateInterval('P14D'))
158
                    ->setTime(23, 59, 59)
159
            )
160
        );
161
    }
162
163
    /**
164
     * @param StartVettingProcedureCommand $command
165
     * @return string The procedure ID.
166
     */
167
    public function startProcedure(StartVettingProcedureCommand $command)
168
    {
169
        $this->smsSecondFactorService->clearSmsVerificationState();
170
171
        if (!$this->isLoaSufficientToStartProcedure($command)) {
172
            throw new LoaTooLowException(
173
                sprintf(
174
                    "Registration authority has LoA '%s', which is not enough to allow vetting of a '%s' second factor",
175
                    $command->authorityLoa,
176
                    $command->secondFactor->type
177
                )
178
            );
179
        }
180
181
        $provePossessionSkipped = $this->secondFactorService->getVerifiedCanSkipProvePossession($command->secondFactor->id);
182
183
        $procedure = VettingProcedure::start(
184
            $command->secondFactor->id,
185
            $command->authorityId,
186
            $command->registrationCode,
187
            $command->secondFactor,
188
            $provePossessionSkipped
0 ignored issues
show
Bug introduced by
It seems like $provePossessionSkipped defined by $this->secondFactorServi...mand->secondFactor->id) on line 181 can also be of type null; however, Surfnet\StepupRa\RaBundl...ttingProcedure::start() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
189
        );
190
191
        $this->vettingProcedureRepository->store($procedure);
192
193
        return $procedure->getId();
194
    }
195
196
    /**
197
     * @param string $procedureId
198
     * @throws UnknownVettingProcedureException
199
     */
200 View Code Duplication
    public function cancelProcedure($procedureId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
    {
202
        if (!is_string($procedureId)) {
203
            throw InvalidArgumentException::invalidType('string', 'procedureId', $procedureId);
204
        }
205
206
        $procedure = $this->vettingProcedureRepository->retrieve($procedureId);
207
208
        if (!$procedure) {
209
            throw new UnknownVettingProcedureException(
210
                sprintf("No vetting procedure with id '%s' is known.", $procedureId)
211
            );
212
        }
213
214
        $this->vettingProcedureRepository->remove($procedureId);
215
    }
216
217
    /**
218
     * @return int
219
     */
220
    public function getSmsOtpRequestsRemainingCount()
221
    {
222
        return $this->smsSecondFactorService->getOtpRequestsRemainingCount();
223
    }
224
225
    /**
226
     * @return int
227
     */
228
    public function getSmsMaximumOtpRequestsCount()
229
    {
230
        return $this->smsSecondFactorService->getMaximumOtpRequestsCount();
231
    }
232
233
    /**
234
     * @param string $procedureId
235
     * @param SendSmsChallengeCommand $command
236
     * @return bool
237
     * @throws UnknownVettingProcedureException
238
     * @throws RuntimeException
239
     */
240
    public function sendSmsChallenge($procedureId, SendSmsChallengeCommand $command)
241
    {
242
        $procedure = $this->getProcedure($procedureId);
243
244
        $phoneNumber = InternationalPhoneNumber::fromStringFormat(
245
            $procedure->getSecondFactor()->secondFactorIdentifier
246
        );
247
248
        $identity = $this->identityService->findById($procedure->getSecondFactor()->identityId);
249
250
        if (!$identity) {
251
            throw new RuntimeException("Second factor is coupled to an identity that doesn't exist");
252
        }
253
254
        $command->phoneNumber = $phoneNumber;
255
        $command->body        = $this->translator->trans('ra.vetting.sms.challenge_body', [], 'messages', $identity->preferredLocale);
256
        $command->identity    = $procedure->getSecondFactor()->identityId;
257
        $command->institution = $procedure->getSecondFactor()->institution;
258
259
        return $this->smsSecondFactorService->sendChallenge($command);
260
    }
261
262
    /**
263
     * @param string                   $procedureId
264
     * @param VerifyPossessionOfPhoneCommand $command
265
     * @return OtpVerification
266
     * @throws UnknownVettingProcedureException
267
     * @throws DomainException
268
     */
269
    public function verifyPhoneNumber($procedureId, VerifyPossessionOfPhoneCommand $command)
270
    {
271
        $procedure = $this->getProcedure($procedureId);
272
273
        $verification = $this->smsSecondFactorService->verifyPossession($command);
274
275
        if (!$verification->wasSuccessful()) {
276
            return $verification;
277
        }
278
279
        $procedure->verifySecondFactorIdentifier($verification->getPhoneNumber());
280
        $this->vettingProcedureRepository->store($procedure);
0 ignored issues
show
Bug introduced by
It seems like $procedure defined by $this->getProcedure($procedureId) on line 271 can be null; however, Surfnet\StepupRa\RaBundl...dureRepository::store() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
281
282
        return $verification;
283
    }
284
285
    /**
286
     * @param string                       $procedureId
287
     * @param VerifyYubikeyPublicIdCommand $command
288
     * @return YubikeySecondFactor\VerificationResult
289
     */
290
    public function verifyYubikeyPublicId($procedureId, VerifyYubikeyPublicIdCommand $command)
291
    {
292
        $procedure = $this->getProcedure($procedureId);
293
294
        $command->expectedPublicId = $procedure->getSecondFactor()->secondFactorIdentifier;
295
        $command->identityId = $procedure->getSecondFactor()->identityId;
296
        $command->institution = $procedure->getSecondFactor()->institution;
297
298
        $result = $this->yubikeySecondFactorService->verifyYubikeyPublicId($command);
299
300
        if ($result->didPublicIdMatch()) {
301
            $procedure->verifySecondFactorIdentifier($result->getPublicId()->getYubikeyPublicId());
302
303
            $this->vettingProcedureRepository->store($procedure);
0 ignored issues
show
Bug introduced by
It seems like $procedure defined by $this->getProcedure($procedureId) on line 292 can be null; however, Surfnet\StepupRa\RaBundl...dureRepository::store() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
304
        }
305
306
        return $result;
307
    }
308
309
    /**
310
     * @param string $procedureId
311
     */
312
    public function startGssfVerification($procedureId)
313
    {
314
        $procedure = $this->getProcedure($procedureId);
315
316
        $this->gssfService->startVerification($procedure->getSecondFactor()->secondFactorIdentifier, $procedureId);
317
    }
318
319
    /**
320
     * @param string $gssfId
321
     * @return GssfVerificationResult
322
     */
323
    public function verifyGssfId($gssfId)
324
    {
325
        $result = $this->gssfService->verify($gssfId);
326
327
        if (!$result->isSuccess()) {
328
            return $result;
329
        }
330
331
        $procedure = $this->getProcedure($result->getProcedureId());
332
        $procedure->verifySecondFactorIdentifier($gssfId);
333
334
        $this->vettingProcedureRepository->store($procedure);
0 ignored issues
show
Bug introduced by
It seems like $procedure defined by $this->getProcedure($result->getProcedureId()) on line 331 can be null; however, Surfnet\StepupRa\RaBundl...dureRepository::store() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
335
336
        return $result;
337
    }
338
339
    /**
340
     * @param string $procedureId
341
     * @return SignRequestCreationResult
342
     */
343
    public function createU2fSignRequest($procedureId)
344
    {
345
        $procedure = $this->getProcedure($procedureId);
346
347
        $command = new CreateU2fSignRequestCommand();
348
        $command->keyHandle = $procedure->getSecondFactor()->secondFactorIdentifier;
349
        $command->identityId = $procedure->getSecondFactor()->identityId;
350
        $command->institution = $procedure->getSecondFactor()->institution;
351
352
        return $this->u2fService->createSignRequest($command);
353
    }
354
355
    /**
356
     * @param string       $procedureId
357
     * @param SignRequest  $signRequest
358
     * @param SignResponse $signResponse
359
     * @return AuthenticationVerificationResult
360
     */
361
    public function verifyU2fAuthentication($procedureId, SignRequest $signRequest, SignResponse $signResponse)
362
    {
363
        $procedure = $this->getProcedure($procedureId);
364
365
        $command = new VerifyU2fAuthenticationCommand();
366
        $command->identityId = $procedure->getSecondFactor()->identityId;
367
        $command->institution = $procedure->getSecondFactor()->institution;
368
        $command->signRequest = $signRequest;
369
        $command->signResponse = $signResponse;
370
371
        $result = $this->u2fService->verifyAuthentication($command);
372
373
        if ($result->wasSuccessful()) {
374
            $procedure->verifySecondFactorIdentifier($signResponse->keyHandle);
375
            $this->vettingProcedureRepository->store($procedure);
0 ignored issues
show
Bug introduced by
It seems like $procedure defined by $this->getProcedure($procedureId) on line 363 can be null; however, Surfnet\StepupRa\RaBundl...dureRepository::store() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
376
        }
377
378
        return $result;
379
    }
380
381
    /**
382
     * @param string $procedureId
383
     * @param VerifyIdentityCommand $command
384
     * @return void
385
     * @throws UnknownVettingProcedureException
386
     * @throws DomainException
387
     */
388
    public function verifyIdentity($procedureId, VerifyIdentityCommand $command)
389
    {
390
        $procedure = $this->getProcedure($procedureId);
391
        $procedure->verifyIdentity($command->documentNumber, $command->identityVerified);
392
393
        $this->vettingProcedureRepository->store($procedure);
0 ignored issues
show
Bug introduced by
It seems like $procedure defined by $this->getProcedure($procedureId) on line 390 can be null; however, Surfnet\StepupRa\RaBundl...dureRepository::store() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
394
    }
395
396
    /**
397
     * @param string $procedureId
398
     * @return \Surfnet\StepupMiddlewareClient\Service\ExecutionResult
399
     * @throws UnknownVettingProcedureException
400
     * @throws DomainException
401
     */
402
    public function vet($procedureId)
403
    {
404
        $procedure = $this->getProcedure($procedureId);
405
        $procedure->vet();
406
407
        $command = new VetSecondFactorCommand();
408
        $command->authorityId = $procedure->getAuthorityId();
409
        $command->identityId = $procedure->getSecondFactor()->identityId;
410
        $command->secondFactorId = $procedure->getSecondFactor()->id;
411
        $command->registrationCode = $procedure->getRegistrationCode();
412
        $command->secondFactorType = $procedure->getSecondFactor()->type;
413
        $command->secondFactorIdentifier = $procedure->getSecondFactor()->secondFactorIdentifier;
414
        $command->documentNumber = $procedure->getDocumentNumber();
415
        $command->identityVerified = $procedure->isIdentityVerified();
416
        $command->provePossessionSkipped = $procedure->isProvePossessionSkippable();
417
418
        $result = $this->commandService->execute($command);
419
420
        if ($result->isSuccessful()) {
421
            $this->vettingProcedureRepository->remove($procedureId);
422
        }
423
424
        return $result;
425
    }
426
427
    /**
428
     * @param string $procedureId
429
     * @return string
430
     * @throws UnknownVettingProcedureException
431
     */
432
    public function getIdentityCommonName($procedureId)
433
    {
434
        return $this->getProcedure($procedureId)->getSecondFactor()->commonName;
435
    }
436
437
    /**
438
     * @param $procedureId
439
     * @return string
440
     * @throws UnknownVettingProcedureException
441
     */
442
    public function isProvePossessionSkippable($procedureId)
443
    {
444
        return $this->getProcedure($procedureId)->isProvePossessionSkippable();
445
    }
446
447
    /**
448
     * @param $procedureId
449
     * @return string
450
     * @throws UnknownVettingProcedureException
451
     */
452
    public function getSecondFactorIdentifier($procedureId)
453
    {
454
        return $this->getProcedure($procedureId)->getSecondFactor()->secondFactorIdentifier;
455
    }
456
457
    /**
458
     * @param string $procedureId
459
     * @return null|VettingProcedure
460
     * @throws UnknownVettingProcedureException
461
     */
462 View Code Duplication
    private function getProcedure($procedureId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
463
    {
464
        if (!is_string($procedureId)) {
465
            throw InvalidArgumentException::invalidType('string', 'procedureId', $procedureId);
466
        }
467
468
        $procedure = $this->vettingProcedureRepository->retrieve($procedureId);
469
470
        if (!$procedure) {
471
            throw new UnknownVettingProcedureException(
472
                sprintf("No vetting procedure with id '%s' is known.", $procedureId)
473
            );
474
        }
475
476
        return $procedure;
477
    }
478
479
    /**
480
     * @param string $procedureId
481
     * @return bool
482
     */
483
    public function hasProcedure($procedureId)
484
    {
485
        if (!is_string($procedureId)) {
486
            throw InvalidArgumentException::invalidType('string', 'procedureId', $procedureId);
487
        }
488
489
        return $this->vettingProcedureRepository->retrieve($procedureId) !== null;
490
    }
491
}
492