Passed
Pull Request — main (#557)
by Johan
10:46 queued 05:30
created

BootstrapSmsSecondFactorCommand::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
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\Console\Command;
20
21
use Exception;
22
use Ramsey\Uuid\Uuid;
23
use Surfnet\Stepup\Identity\Value\Institution;
24
use Surfnet\Stepup\Identity\Value\NameId;
25
use Surfnet\StepupMiddleware\MiddlewareBundle\Service\BootstrapCommandService;
26
use Surfnet\StepupMiddleware\MiddlewareBundle\Service\TransactionHelper;
0 ignored issues
show
Bug introduced by
The type Surfnet\StepupMiddleware...rvice\TransactionHelper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
use Symfony\Component\Console\Attribute\Argument;
28
use Symfony\Component\Console\Attribute\AsCommand;
29
use Symfony\Component\Console\Output\OutputInterface;
30
31
#[AsCommand(
32
    name: 'middleware:bootstrap:sms',
33
    description: 'Creates a SMS second factor for a specified user'
34
)]
35
final class BootstrapSmsSecondFactorCommand
36
{
37
    public function __construct(private readonly BootstrapCommandService $bootstrapService, private readonly TransactionHelper $transactionHelper)
38
    {
39
    }
40
41
    public function __invoke(#[Argument(description: 'The NameID of the identity to create', name: 'name-id')]
42
    string $nameId, #[Argument(description: 'The institution of the identity to create', name: 'institution')]
43
    string $institution, #[Argument(description: 'The phone number of the user should be formatted like "+31 (0) 612345678"', name: 'phone-number')]
44
    string $phoneNumber, #[Argument(description: 'Valid arguments: unverified, verified, vetted', name: 'registration-status')]
45
    string $registrationStatus, #[Argument(description: 'The id of the vetting actor', name: 'actor-id')]
46
    string $actorId, OutputInterface $output): int
47
    {
48
        $this->bootstrapService->validRegistrationStatus($registrationStatus);
49
50
        $nameId = new NameId($nameId);
51
        $institutionText = $institution;
52
        $institution = new Institution($institutionText);
53
        $mailVerificationRequired = $this->bootstrapService->requiresMailVerification($institutionText);
54
55
        $this->bootstrapService->enrichEventMetadata($actorId);
56
        if (!$this->bootstrapService->identityExists($nameId, $institution)) {
57
            $output->writeln(
58
                sprintf(
59
                    '<error>An identity with name ID "%s" from institution "%s" does not exist, create it first.</error>',
60
                    $nameId->getNameId(),
61
                    $institution->getInstitution(),
62
                ),
63
            );
64
65
            return 1;
66
        }
67
        $identity = $this->bootstrapService->getIdentity($nameId, $institution);
68
        $output->writeln(
69
            sprintf('<comment>Adding a %s SMS token for %s</comment>', $registrationStatus, $identity->commonName),
70
        );
71
        $this->transactionHelper->beginTransaction();
72
        $secondFactorId = Uuid::uuid4()->toString();
73
74
        try {
75
            switch ($registrationStatus) {
76
                case "unverified":
77
                    $output->writeln('<comment>Creating an unverified SMS token</comment>');
78
                    $this->bootstrapService->provePhonePossession($secondFactorId, $identity, $phoneNumber);
79
                    break;
80
                case "verified":
81
                    $output->writeln('<comment>Creating an unverified SMS token</comment>');
82
                    $this->bootstrapService->provePhonePossession($secondFactorId, $identity, $phoneNumber);
83
                    if ($mailVerificationRequired) {
84
                        $output->writeln('<comment>Creating a verified SMS token</comment>');
85
                        $this->bootstrapService->verifyEmail($identity, 'sms');
86
                    }
87
                    break;
88
                case "vetted":
89
                    $output->writeln('<comment>Creating an unverified SMS token</comment>');
90
                    $this->bootstrapService->provePhonePossession($secondFactorId, $identity, $phoneNumber);
91
                    if ($mailVerificationRequired) {
92
                        $output->writeln('<comment>Creating a verified SMS token</comment>');
93
                        $this->bootstrapService->verifyEmail($identity, 'sms');
94
                    }
95
                    $output->writeln('<comment>Vetting the verified SMS token</comment>');
96
                    $this->bootstrapService->vetSecondFactor(
97
                        'sms',
98
                        $actorId,
99
                        $identity,
100
                        $secondFactorId,
101
                        $phoneNumber,
102
                    );
103
                    break;
104
            }
105
            $this->transactionHelper->finishTransaction();
106
        } catch (Exception $e) {
107
            $output->writeln(
108
                sprintf(
109
                    '<error>An Error occurred when trying to bootstrap the SMS token: "%s"</error>',
110
                    $e->getMessage(),
111
                ),
112
            );
113
            $this->transactionHelper->rollback();
114
            return 1;
115
        }
116
        $output->writeln(
117
            sprintf(
118
                '<info>Successfully registered a SMS token with UUID %s</info>',
119
                $secondFactorId,
120
            ),
121
        );
122
        return 0;
123
    }
124
}
125