ApiClient   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 169
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 0%

Importance

Changes 15
Bugs 0 Features 4
Metric Value
wmc 27
c 15
b 0
f 4
lcom 1
cbo 6
dl 0
loc 169
ccs 0
cts 75
cp 0
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 8 1
A __construct() 0 5 1
A authenticate() 0 21 4
A getAuthToken() 0 4 1
B getLogins() 0 22 5
B getWebAccounts() 0 23 5
A doHandshake() 0 12 3
A setAuthToken() 0 4 1
A isEncryptionKeyRegistered() 0 14 3
A registerEncryptionKey() 0 9 2
A send() 0 11 1
1
<?php
2
namespace Graceland\SafeInCloud;
3
4
use GuzzleHttp\Client;
5
use GuzzleHttp\ClientInterface;
6
7
class ApiClient
8
{
9
    const EXPIRATION_HOUR  = 3600;
10
    const EXPIRATION_NEVER = -1;
11
    const EXPIRATION_ONCE  = -2;
12
13
    const URL = 'http://localhost:19756/';
14
15
    protected $client;
16
17
    protected $factory;
18
19
    protected $registered = false;
20
21
    protected $token;
22
23
    public static function create()
24
    {
25
        $guzzle    = new Client;
26
        $encrypter = new Encrypter(Encrypter::generateKey());
27
        $factory   = new MessageFactory($encrypter);
28
29
        return new static($guzzle, $factory);
30
    }
31
32
    public function __construct(ClientInterface $client, MessageFactory $factory)
33
    {
34
        $this->client  = $client;
35
        $this->factory = $factory;
36
    }
37
38
    public function authenticate($password)
39
    {
40
        $request = $this->factory->createRequest('authenticate');
41
42
        $request->addData('expiresin', static::EXPIRATION_HOUR);
43
        $request->addEncryptedData('password', $password);
44
45
        $response = $this->send($request);
46
47
        if ($response->isValid() === false) {
48
            throw new \RuntimeException('Unable to authenticate against the API.');
49
        }
50
51
        if ($response->isSuccessful() === false || $response->has('token') === false) {
52
            throw new \RuntimeException('Authenticated unsuccessfully, invalid password?');
53
        }
54
55
        $this->token = $response->getDecrypted('token');
56
57
        return $this->token;
58
    }
59
60
    /**
61
     * @return string
62
    */
63
    public function getAuthToken()
64
    {
65
        return $this->token;
66
    }
67
68
    /**
69
     * @return array
70
    */
71
    public function getLogins()
72
    {
73
        if ($this->token === null) {
74
            throw new \RuntimeException('You need to be authenticated before making this request.');
75
        }
76
77
        $request = $this->factory->createRequest('get_logins');
78
79
        $request->addEncryptedData('token', $this->token);
80
81
        $response = $this->send($request);
82
83
        if ($response->isValid() === false) {
84
            throw new \RuntimeException('Unable to retrieve logins from the API.');
85
        }
86
87
        if ($response->isSuccessful() === false || $response->has('logins') === false) {
88
            throw new \RuntimeException('Retrieved web accounts unsuccessfully, invalid authentication token?');
89
        }
90
91
        return $response->getDecrypted('logins', []);
92
    }
93
94
    /**
95
     * @return array
96
    */
97
    public function getWebAccounts($url)
98
    {
99
        if ($this->token === null) {
100
            throw new \RuntimeException('You need to be authenticated before making this request.');
101
        }
102
103
        $request = $this->factory->createRequest('get_web_accounts_2');
104
105
        $request->addEncryptedData('token', $this->token);
106
        $request->addEncryptedData('url', $url);
107
108
        $response = $this->send($request);
109
110
        if ($response->isValid() === false) {
111
            throw new \RuntimeException('Unable to retrieve web accounts from the API.');
112
        }
113
114
        if ($response->isSuccessful() === false || $response->has('accounts') === false) {
115
            throw new \RuntimeException('Retrieved web accounts unsuccessfully, invalid authentication token?');
116
        }
117
118
        return $response->getDecrypted('accounts', [], ['login', 'password']);
119
    }
120
121
    public function doHandshake()
122
    {
123
        if ($this->isEncryptionKeyRegistered() === true) {
124
            return;
125
        }
126
127
        $this->registerEncryptionKey();
128
129
        if ($this->isEncryptionKeyRegistered() === false) {
130
            throw new \RuntimeException('Unable to register key with the API.');
131
        }
132
    }
133
134
    public function setAuthToken($token)
135
    {
136
        $this->token = $token;
137
    }
138
139
    protected function isEncryptionKeyRegistered()
140
    {
141
        if ($this->registered === false) {
142
            return false;
143
        }
144
145
        $request = $this->factory->createRequest('test_handshake');
146
147
        $request->addEncodedData('key', $this->factory->getEncrypter()->getKey());
148
149
        $response = $this->send($request);
150
151
        return ($response->isValid() && $response->isSuccessful());
152
    }
153
154
    protected function registerEncryptionKey()
155
    {
156
        $request = $this->factory->createRequest('handshake');
157
158
        $request->addEncodedData('key', $this->factory->getEncrypter()->getKey());
159
160
        $response         = $this->send($request);
161
        $this->registered = ($response->isValid() && $response->isSuccessful());
162
    }
163
164
    protected function send(Request $request)
165
    {
166
        $response = $this->client->post(static::URL, [
167
            'body' => json_encode($request->getPayload()),
168
            'headers' => [
169
                'content-type' => 'application/json',
170
            ],
171
        ]);
172
173
        return $this->factory->createResponse($response, $request);
174
    }
175
}
176