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

BootstrapYubikeySecondFactorCommand::__invoke()   B

Complexity

Conditions 8
Paths 27

Size

Total Lines 88
Code Lines 58

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 58
nc 27
nop 6
dl 0
loc 88
rs 7.6719
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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