Passed
Push — main ( a1448d...532f1f )
by Peter
03:51
created

SecretGenerator   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 43
dl 0
loc 114
rs 10
c 2
b 0
f 0
wmc 12

6 Methods

Rating   Name   Duplication   Size   Complexity  
A setEnvFile() 0 5 1
A handleKey() 0 14 3
A getEnvFile() 0 15 3
A doExecute() 0 14 3
A define() 0 10 1
A addKey() 0 3 1
1
<?php
2
3
/*
4
 * Opulence
5
 *
6
 * @link      https://www.opulencephp.com
7
 * @copyright Copyright (C) 2017 David Young
8
 * @license   https://github.com/opulencephp/Opulence/blob/master/LICENSE.md
9
 */
10
11
namespace AbterPhp\Framework\Console\Commands\Security;
12
13
use AbterPhp\Framework\Constant\Env;
14
use Defuse\Crypto\Key;
15
use Exception;
16
use Opulence\Console\Commands\Command;
17
use Opulence\Console\Requests\Option;
18
use Opulence\Console\Requests\OptionTypes;
19
use Opulence\Console\Responses\IResponse;
20
use Opulence\Framework\Configuration\Config;
21
22
/**
23
 * Defines the encryption key generator command
24
 */
25
class SecretGenerator extends Command
26
{
27
    /** @var array */
28
    protected array $keys = [
29
        Env::DB_PASSWORD                 => 12,
30
        Env::ENCRYPTION_KEY              => 32,
31
        Env::CRYPTO_FRONTEND_SALT        => 8,
32
        Env::CRYPTO_ENCRYPTION_PEPPER    => 16,
33
        Env::OAUTH2_PRIVATE_KEY_PASSWORD => 16,
34
    ];
35
36
    /** @var null|string */
37
    protected ?string $envFile = null;
38
39
    /**
40
     * @inheritdoc
41
     */
42
    protected function define()
43
    {
44
        $this->setName('abterphp:generatesecrets')
45
            ->setDescription('Creates secrets for AbterAdmin')
46
            ->addOption(
47
                new Option(
48
                    'dry-run',
49
                    'd',
50
                    OptionTypes::NO_VALUE,
51
                    'Whether to just show the new secrets or also replace them in the environment config'
52
                )
53
            );
54
    }
55
56
    /**
57
     * @param string $name
58
     * @param int    $length
59
     */
60
    public function addKey(string $name, int $length)
61
    {
62
        $this->keys[$name] = $length;
63
    }
64
65
    /**
66
     * @inheritdoc
67
     * @throws Exception
68
     */
69
    protected function doExecute(IResponse $response)
70
    {
71
        $maxNameLength = strlen(Env::OAUTH2_ENCRYPTION_KEY);
72
        foreach ($this->keys as $name => $length) {
73
            $maxNameLength = (int)max($maxNameLength, strlen($name));
74
        }
75
76
        foreach ($this->keys as $name => $length) {
77
            $key = \bin2hex(\random_bytes($length));
78
            $this->handleKey($response, $name, $key, $maxNameLength);
79
        }
80
81
        $key = Key::createNewRandomKey()->saveToAsciiSafeString();
82
        $this->handleKey($response, Env::OAUTH2_ENCRYPTION_KEY, $key, $maxNameLength);
83
    }
84
85
    /**
86
     * @return string|null
87
     */
88
    protected function getEnvFile(): ?string
89
    {
90
        if (null !== $this->envFile) {
91
            return $this->envFile;
92
        }
93
94
        $fileName = Config::get('paths', 'config') . '/environment/.env.app.php';
95
96
        if (!file_exists($fileName)) {
97
            throw new \RuntimeException('app config not found: ' . $fileName);
98
        }
99
100
        $this->envFile = $fileName;
101
102
        return $this->envFile;
103
    }
104
105
    /**
106
     * @param string|null $envFile
107
     *
108
     * @return $this
109
     */
110
    public function setEnvFile(?string $envFile = null): self
111
    {
112
        $this->envFile = $envFile;
113
114
        return $this;
115
    }
116
117
    /**
118
     * @param IResponse $response
119
     * @param string    $name
120
     * @param string    $key
121
     * @param int       $maxNameLength
122
     *
123
     * @throws Exception
124
     */
125
    protected function handleKey(IResponse $response, string $name, string $key, int $maxNameLength)
126
    {
127
        if (!$this->optionIsSet('dry-run') && $this->getEnvFile()) {
128
            $contents    = file_get_contents($this->getEnvFile());
129
            $newContents = preg_replace(
130
                sprintf("/\"%s\",\s*\"[^\"]*\"/U", $name),
131
                sprintf('"%s", "' . $key . '"', $name),
132
                $contents
133
            );
134
            file_put_contents($this->getEnvFile(), $newContents);
135
        }
136
137
        $pad = str_repeat(' ', $maxNameLength - strlen($name));
138
        $response->writeln("Generated $name:$pad <info>$key</info>");
139
    }
140
}
141