Passed
Push — master ( 956163...dedbc7 )
by Christian
03:02
created

ApiTokenOptionProvider   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 68
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 31
dl 0
loc 68
rs 10
c 0
b 0
f 0
wmc 8

7 Methods

Rating   Name   Duplication   Size   Complexity  
A optionName() 0 3 1
A __construct() 0 3 1
A validate() 0 13 2
A question() 0 4 1
A option() 0 8 1
A onCorrectAnswer() 0 4 1
A helpMessage() 0 9 1
1
<?php declare(strict_types=1);
2
3
namespace Cocotte\DigitalOcean;
4
5
use Cocotte\Console\OptionProvider;
6
use Cocotte\Console\Style;
7
use Cocotte\Console\StyledInputOption;
8
use Cocotte\Environment\EnvironmentState;
9
use DigitalOceanV2\Adapter\GuzzleHttpAdapter;
10
use DigitalOceanV2\DigitalOceanV2;
11
use Symfony\Component\Console\Input\InputOption;
12
use Symfony\Component\Console\Question\Question;
13
14
class ApiTokenOptionProvider implements OptionProvider
15
{
16
    /**
17
     * @var Style
18
     */
19
    private $style;
20
21
    public function __construct(Style $style)
22
    {
23
        $this->style = $style;
24
    }
25
26
    public function option(EnvironmentState $environmentState): InputOption
27
    {
28
        return new StyledInputOption(
29
            $this->optionName(),
30
            null,
31
            InputOption::VALUE_REQUIRED,
32
            $this->helpMessage(),
33
            $environmentState->defaultValue(ApiToken::DIGITAL_OCEAN_API_TOKEN)
34
        );
35
    }
36
37
    public function helpMessage(): string
38
    {
39
        return $this->style->optionHelp(
40
            "Digital Ocean API Token",
41
            [
42
                "If you don't have a Digital Ocean account yet, get one with a 100$ credit at\n".
43
                $this->style->link('https://m.do.co/c/c25ed78e51c5'),
44
                "Then generate a token at ".$this->style->link('https://cloud.digitalocean.com/settings/api/tokens'),
45
                "Cocotte will make a call to Digital Ocean's API to validate the token.",
46
            ]
47
        );
48
    }
49
50
    public function validate(string $value)
51
    {
52
        $token = new ApiToken($value);
53
        $adapter = new GuzzleHttpAdapter($token->toString());
54
        $digitalOceanV2 = new DigitalOceanV2($adapter);
55
        try {
56
            $domain = sprintf('cocotte-validate-%s.token', uniqid());
57
            $digitalOceanV2->domain()->create($domain, '127.0.0.1');
58
            $digitalOceanV2->domain()->delete($domain);
59
        } catch (\Throwable $e) {
60
            throw new \Exception(
61
                "Failed to validate that the Digital Ocean token has 'write' permissions. Error message was:\n".
62
                $e->getMessage()
63
            );
64
        }
65
    }
66
67
    public function onCorrectAnswer(string $answer)
68
    {
69
        $this->style->success("Token '$answer' is valid");
70
        $this->style->pause();
71
    }
72
73
    public function optionName(): string
74
    {
75
        return ApiToken::OPTION_NAME;
76
    }
77
78
    public function question(): Question
79
    {
80
        return new Question(
81
            $this->style->quittableQuestion("Enter your <options=bold>Digital Ocean API token</>")
82
        );
83
    }
84
85
}
86