Passed
Pull Request — master (#36)
by Rogier
01:42
created

Account::postToAccountUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Rogierw\RwAcme\Endpoints;
4
5
use Rogierw\RwAcme\DTO\AccountData;
6
use Rogierw\RwAcme\Exceptions\LetsEncryptClientException;
7
use Rogierw\RwAcme\Http\Response;
8
use Rogierw\RwAcme\Support\JsonWebSignature;
9
10
class Account extends Endpoint
11
{
12
    public function exists(): bool
13
    {
14
        return $this->client->localAccount()->exists();
15
    }
16
17
    public function create(): AccountData
18
    {
19
        $this->client->localAccount()->generateNewKeys();
20
21
        $payload = [
22
            'contact' => ['mailto:'.$this->client->localAccount()->getEmailAddress()],
23
            'termsOfServiceAgreed' => true,
24
        ];
25
26
        $response = $this->postToAccountUrl($payload);
27
28
        if ($response->getHttpResponseCode() === 201 && $response->hasHeader('location')) {
29
            return AccountData::fromResponse($response);
30
        }
31
32
        $this->throwError($response, 'Creating account failed');
33
    }
34
35
    public function get(): AccountData
36
    {
37
        if (!$this->exists()) {
38
            throw new LetsEncryptClientException('Local account keys not found.');
39
        }
40
41
        // Use the newAccountUrl to get the account data based on the key.
42
        // See https://datatracker.ietf.org/doc/html/rfc8555#section-7.3.1
43
        $payload = ['onlyReturnExisting' => true];
44
        $response = $this->postToAccountUrl($payload);
45
46
        if ($response->getHttpResponseCode() === 200) {
47
            return AccountData::fromResponse($response);
48
        }
49
50
        $this->throwError($response, 'Retrieving account failed');
51
    }
52
53
    private function signPayload(array $payload): array
54
    {
55
        return JsonWebSignature::generate(
56
            $payload,
57
            $this->client->directory()->newAccount(),
58
            $this->client->nonce()->getNew(),
59
            $this->client->localAccount()->getPrivateKey(),
60
        );
61
    }
62
63
    private function postToAccountUrl(array $payload): Response
64
    {
65
        return $this->client->getHttpClient()->post(
66
            $this->client->directory()->newAccount(),
67
            $this->signPayload($payload)
68
        );
69
    }
70
71
    protected function throwError(Response $response, string $defaultMessage): never
72
    {
73
        $message = $response->getBody()['details'] ?? $defaultMessage;
74
        $this->logResponse('error', $message, $response);
75
76
        throw new LetsEncryptClientException($message);
77
    }
78
}
79