Passed
Push — master ( 7c51ba...a22fab )
by Peter
04:20
created

RegenerateSecret   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 9
eloc 67
dl 0
loc 139
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 16 1
B doExecute() 0 51 7
A define() 0 18 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\Admin\Console\Commands\ApiClient;
6
7
use AbterPhp\Admin\Domain\Entities\ApiClient;
8
use AbterPhp\Admin\Orm\ApiClientRepo;
9
use AbterPhp\Framework\Authorization\CacheManager;
10
use AbterPhp\Framework\Crypto\Crypto;
11
use Hackzilla\PasswordGenerator\Generator\ComputerPasswordGenerator as PasswordGenerator;
0 ignored issues
show
Bug introduced by
The type Hackzilla\PasswordGenera...mputerPasswordGenerator 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...
12
use Opulence\Console\Commands\Command;
13
use Opulence\Console\Requests\Argument;
14
use Opulence\Console\Requests\ArgumentTypes;
15
use Opulence\Console\Requests\Option;
16
use Opulence\Console\Requests\OptionTypes;
17
use Opulence\Console\Responses\IResponse;
18
use Opulence\Orm\IUnitOfWork;
19
use ZxcvbnPhp\Zxcvbn;
20
21
class RegenerateSecret extends Command
22
{
23
    const COMMAND_NAME            = 'apiclient:regenerate-secret';
24
    const COMMAND_DESCRIPTION     = 'Regenerate the secret of an existing API client';
25
    const COMMAND_SUCCESS         = '<success>API client secret is updated.</success>';
26
    const COMMAND_DRY_RUN_MESSAGE = '<info>Dry run prevented updating existing API client.</info>';
27
28
    const ARGUMENT_IDENTIFIER = 'identifier';
29
30
    const OPTION_DRY_RUN    = 'dry-run';
31
    const SHORTENED_DRY_RUN = 'd';
32
33
    const RESPONSE_SECRET = '<info>Secret generated: <b>%s</b></info>';
34
35
    /** @var ApiClientRepo */
36
    protected $apiClientRepo;
37
38
    /** @var PasswordGenerator */
39
    protected $passwordGenerator;
40
41
    /** @var Crypto */
42
    protected $crypto;
43
44
    /** @var IUnitOfWork */
45
    protected $unitOfWork;
46
47
    /** @var CacheManager */
48
    protected $cacheManager;
49
50
    /** @var Zxcvbn */
51
    protected $zxcvbn;
52
53
    /**
54
     * RegenerateSecret constructor.
55
     *
56
     * @param ApiClientRepo     $apiClientRepo
57
     * @param PasswordGenerator $passwordGenerator
58
     * @param Crypto            $crypto
59
     * @param IUnitOfWork       $unitOfWork
60
     * @param CacheManager      $cacheManager
61
     * @param Zxcvbn            $zxcvbn
62
     */
63
    public function __construct(
64
        ApiClientRepo $apiClientRepo,
65
        PasswordGenerator $passwordGenerator,
66
        Crypto $crypto,
67
        IUnitOfWork $unitOfWork,
68
        CacheManager $cacheManager,
69
        Zxcvbn $zxcvbn
70
    ) {
71
        $this->apiClientRepo     = $apiClientRepo;
72
        $this->passwordGenerator = $passwordGenerator;
73
        $this->crypto            = $crypto;
74
        $this->unitOfWork        = $unitOfWork;
75
        $this->cacheManager      = $cacheManager;
76
        $this->zxcvbn            = $zxcvbn;
77
78
        parent::__construct();
79
    }
80
81
    /**
82
     * @inheritdoc
83
     */
84
    protected function define()
85
    {
86
        $this->setName(static::COMMAND_NAME)
87
            ->setDescription(static::COMMAND_DESCRIPTION)
88
            ->addArgument(
89
                new Argument(
90
                    static::ARGUMENT_IDENTIFIER,
91
                    ArgumentTypes::REQUIRED,
92
                    'Identifier'
93
                )
94
            )
95
            ->addOption(
96
                new Option(
97
                    static::OPTION_DRY_RUN,
98
                    static::SHORTENED_DRY_RUN,
99
                    OptionTypes::OPTIONAL_VALUE,
100
                    'Dry run (default: 0)',
101
                    '0'
102
                )
103
            );
104
    }
105
106
    /**
107
     * @inheritdoc
108
     */
109
    protected function doExecute(IResponse $response)
110
    {
111
        $identifier = $this->getArgumentValue(static::ARGUMENT_IDENTIFIER);
112
        $dryRun     = $this->getOptionValue(static::OPTION_DRY_RUN);
113
114
        try {
115
            /** @var ApiClient $apiClient */
116
            $apiClient = $this->apiClientRepo->getById($identifier);
117
            if (!$apiClient) {
0 ignored issues
show
introduced by
$apiClient is of type AbterPhp\Admin\Domain\Entities\ApiClient, thus it always evaluated to true.
Loading history...
118
                $response->writeln(sprintf('<fatal>API client not found</fatal>'));
119
120
                return;
121
            }
122
123
            $adminResources = $apiClient->getAdminResources();
0 ignored issues
show
Unused Code introduced by
The assignment to $adminResources is dead and can be removed.
Loading history...
124
125
            $rawSecret        = $this->passwordGenerator->generatePassword();
126
            $preparedPassword = $this->crypto->prepareSecret($rawSecret);
127
            $packedPassword   = $this->crypto->hashCrypt($preparedPassword);
128
129
            $apiClient->setSecret($packedPassword);
130
        } catch (\Exception $e) {
131
            if ($e->getPrevious()) {
132
                $response->writeln(sprintf('<error>%s</error>', $e->getPrevious()->getMessage()));
133
            }
134
            $response->writeln(sprintf('<fatal>%s</fatal>', $e->getMessage()));
135
136
            return;
137
        }
138
139
        if ($dryRun) {
140
            $this->unitOfWork->dispose();
141
            $response->writeln(static::COMMAND_DRY_RUN_MESSAGE);
142
143
            return;
144
        }
145
146
        try {
147
            $this->unitOfWork->commit();
148
            $this->cacheManager->clearAll();
149
        } catch (\Exception $e) {
150
            if ($e->getPrevious()) {
151
                $response->writeln(sprintf('<error>%s</error>', $e->getPrevious()->getMessage()));
152
            }
153
            $response->writeln(sprintf('<fatal>%s</fatal>', $e->getMessage()));
154
155
            return;
156
        }
157
158
        $response->writeln(sprintf(static::RESPONSE_SECRET, $rawSecret));
159
        $response->writeln(static::COMMAND_SUCCESS);
160
    }
161
}
162