Passed
Push — master ( 3d85c1...365911 )
by Peter
02:26
created

Console/Commands/ApiClient/RegenerateSecret.php (1 issue)

Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\Admin\Console\Commands\ApiClient;
6
7
use AbterPhp\Admin\Orm\ApiClientRepo;
8
use AbterPhp\Framework\Authorization\CacheManager;
9
use AbterPhp\Framework\Crypto\Crypto;
10
use Hackzilla\PasswordGenerator\Generator\ComputerPasswordGenerator as PasswordGenerator;
11
use Opulence\Console\Commands\Command;
12
use Opulence\Console\Requests\Argument;
13
use Opulence\Console\Requests\ArgumentTypes;
14
use Opulence\Console\Requests\Option;
15
use Opulence\Console\Requests\OptionTypes;
16
use Opulence\Console\Responses\IResponse;
17
use Opulence\Console\StatusCodes;
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
            $apiClient = $this->apiClientRepo->getById($identifier);
116
            if (!$apiClient) {
0 ignored issues
show
$apiClient is of type object, thus it always evaluated to true.
Loading history...
117
                $response->writeln(sprintf('<fatal>API client not found</fatal>'));
118
119
                return StatusCodes::ERROR;
120
            }
121
122
            $rawSecret        = $this->passwordGenerator->generatePassword();
123
            $preparedPassword = $this->crypto->prepareSecret($rawSecret);
124
            $packedPassword   = $this->crypto->hashCrypt($preparedPassword);
125
126
            $apiClient->setSecret($packedPassword);
127
        } catch (\Exception $e) {
128
            if ($e->getPrevious()) {
129
                $response->writeln(sprintf('<error>%s</error>', $e->getPrevious()->getMessage()));
130
            }
131
            $response->writeln(sprintf('<fatal>%s</fatal>', $e->getMessage()));
132
133
            return StatusCodes::FATAL;
134
        }
135
136
        if ($dryRun) {
137
            $this->unitOfWork->dispose();
138
            $response->writeln(static::COMMAND_DRY_RUN_MESSAGE);
139
140
            return StatusCodes::OK;
141
        }
142
143
        try {
144
            $this->unitOfWork->commit();
145
            $this->cacheManager->clearAll();
146
        } catch (\Exception $e) {
147
            if ($e->getPrevious()) {
148
                $response->writeln(sprintf('<error>%s</error>', $e->getPrevious()->getMessage()));
149
            }
150
            $response->writeln(sprintf('<fatal>%s</fatal>', $e->getMessage()));
151
152
            return StatusCodes::FATAL;
153
        }
154
155
        $response->writeln(sprintf(static::RESPONSE_SECRET, $rawSecret));
156
        $response->writeln(static::COMMAND_SUCCESS);
157
158
        return StatusCodes::OK;
159
    }
160
}
161