Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Push — master ( 24da77...3cb3b4 )
by Denis
01:19 queued 11s
created

Centrifugo::getSecret()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
declare(strict_types=1);
3
4
namespace denis660\Centrifugo;
5
6
use denis660\Centrifugo\Contracts\CentrifugoInterface;
7
use GuzzleHttp\Client as HttpClient;
8
use GuzzleHttp\Exception\ClientException;
9
10
class Centrifugo implements CentrifugoInterface
11
{
12
    const API_PATH = '/api';
13
14
    /**
15
     * @var \GuzzleHttp\Client
16
     */
17
    protected $httpClient;
18
19
    /**
20
     * @var array
21
     */
22
    protected $config;
23
24
    /**
25
     * Create a new Centrifugo instance.
26
     *
27
     * @param array $config
28
     * @param \GuzzleHttp\Client $httpClient
29
     */
30
    public function __construct(array $config, HttpClient $httpClient)
31
    {
32
        $this->httpClient = $httpClient;
33
        $this->config = $this->initConfiguration($config);
34
    }
35
36
    /**
37
     * Init centrifugo configuration.
38
     *
39
     * @param array $config
40
     * @return array
41
     */
42
    protected function initConfiguration(array $config)
43
    {
44
        $defaults = [
45
            'url'     => 'http://localhost:8000',
46
            'secret'  => null,
47
            'apikey'  => null,
48
            'ssl_key' => null,
49
            'verify'  => true,
50
        ];
51
52
        foreach ($config as $key => $value) {
53
            if (array_key_exists($key, $defaults)) {
54
                $defaults[$key] = $value;
55
            }
56
        }
57
58
        return $defaults;
59
    }
60
61
    /**
62
     * Send message into channel.
63
     *
64
     * @param string $channel
65
     * @param array $data
66
     * @return mixed
67
     */
68
    public function publish(string $channel, array $data)
69
    {
70
        return $this->send('publish', [
71
            'channel' => $channel,
72
            'data'    => $data,
73
        ]);
74
    }
75
76
    /**
77
     * Send message into multiple channel.
78
     *
79
     * @param array $channels
80
     * @param array $data
81
     * @return mixed
82
     */
83
    public function broadcast(array $channels, array $data)
84
    {
85
        $params = ['channels' => $channels, 'data' => $data];
86
87
        return $this->send('broadcast', $params);
88
    }
89
90
    /**
91
     * Get channel presence information (all clients currently subscribed on this channel).
92
     *
93
     * @param string $channel
94
     * @return mixed
95
     */
96
    public function presence(string $channel)
97
    {
98
        return $this->send('presence', ['channel' => $channel]);
99
    }
100
101
    /**
102
     * Get channel presence information in short form.
103
     *
104
     * @param string $channel
105
     * @return mixed
106
     */
107
    public function presenceStats(string $channel)
108
    {
109
        return $this->send('presence_stats', ['channel' => $channel]);
110
    }
111
112
    /**
113
     * Get channel history information (list of last messages sent into channel).
114
     *
115
     * @param string $channel
116
     * @return mixed
117
     */
118
    public function history(string $channel)
119
    {
120
        return $this->send('history', ['channel' => $channel]);
121
    }
122
123
    /**
124
     * Remove channel history information.
125
     *
126
     * @param string $channel
127
     * @return mixed
128
     */
129
    public function historyRemove(string $channel)
130
    {
131
        return $this->send('history_remove', [
132
            'channel' => $channel,
133
        ]);
134
    }
135
136
    /**
137
     * Unsubscribe user from channel.
138
     *
139
     * @param string $channel
140
     * @param string $user
141
     * @return mixed
142
     */
143
    public function unsubscribe(string $channel, string $user)
144
    {
145
        return $this->send('unsubscribe', [
146
            'channel' => $channel,
147
            'user'    => $user,
148
        ]);
149
    }
150
151
    /**
152
     * Disconnect user by its ID.
153
     *
154
     * @param string $user_id
155
     * @return mixed
156
     */
157
    public function disconnect(string $user_id)
158
    {
159
        return $this->send('disconnect', ['user' => (string)$user_id]);
160
    }
161
162
    /**
163
     * Get channels information (list of currently active channels).
164
     *
165
     * @return mixed
166
     */
167
    public function channels()
168
    {
169
        return $this->send('channels');
170
    }
171
172
    /**
173
     * Get stats information about running server nodes.
174
     *
175
     * @return mixed
176
     */
177
    public function info()
178
    {
179
        return $this->send('info');
180
    }
181
182
    /**
183
     * Generate connection token.
184
     *
185
     * @param string $userId
186
     * @param int $exp
187
     * @param array $info
188
     * @return string
189
     */
190
    public function generateConnectionToken(string $userId = '', int $exp = 0, array $info = []): string
191
    {
192
        $header = ['typ' => 'JWT', 'alg' => 'HS256'];
193
        $payload = ['sub' => $userId];
194
        if (!empty($info)) {
195
            $payload['info'] = $info;
196
        }
197
        if ($exp) {
198
            $payload['exp'] = $exp;
199
        }
200
        $segments = [];
201
        $segments[] = $this->urlsafeB64Encode(json_encode($header));
202
        $segments[] = $this->urlsafeB64Encode(json_encode($payload));
203
        $signing_input = implode('.', $segments);
204
        $signature = $this->sign($signing_input, $this->getSecret());
205
        $segments[] = $this->urlsafeB64Encode($signature);
206
207
        return implode('.', $segments);
208
    }
209
210
    /**
211
     * Generate private channel token.
212
     *
213
     * @param string $client
214
     * @param string $channel
215
     * @param int $exp
216
     * @param array $info
217
     * @return string
218
     */
219
    public function generatePrivateChannelToken(string $client, string $channel, int $exp = 0, array $info = []): string
220
    {
221
        $header = ['typ' => 'JWT', 'alg' => 'HS256'];
222
        $payload = ['channel' => $channel, 'client' => $client];
223
        if (!empty($info)) {
224
            $payload['info'] = $info;
225
        }
226
        if ($exp) {
227
            $payload['exp'] = $exp;
228
        }
229
        $segments = [];
230
        $segments[] = $this->urlsafeB64Encode(json_encode($header));
231
        $segments[] = $this->urlsafeB64Encode(json_encode($payload));
232
        $signing_input = implode('.', $segments);
233
        $signature = $this->sign($signing_input, $this->getSecret());
234
        $segments[] = $this->urlsafeB64Encode($signature);
235
236
        return implode('.', $segments);
237
    }
238
239
    /**
240
     * Get secret key.
241
     *
242
     * @return string
243
     */
244
    protected function getSecret()
245
    {
246
        return $this->config['secret'];
247
    }
248
249
    /**
250
     * Send message to centrifugo server.
251
     *
252
     * @param string $method
253
     * @param array $params
254
     * @return mixed
255
     */
256
    protected function send($method, array $params = [])
257
    {
258
        $json = json_encode(['method' => $method, 'params' => $params]);
259
260
        $headers = [
261
            'Content-type'  => 'application/json',
262
            'Authorization' => 'apikey ' . $this->config['apikey'],
263
        ];
264
265
        try {
266
            $url = parse_url($this->prepareUrl());
267
268
            $config = collect([
269
                'headers'     => $headers,
270
                'body'        => $json,
271
                'http_errors' => false,
272
            ]);
273
274
            if ($url['scheme'] == 'https') {
275
                $config->put('verify', collect($this->config)->get('verify', false));
276
277
                if (collect($this->config)->get('ssl_key')) {
278
                    $config->put('ssl_key', collect($this->config)->get('ssl_key'));
279
                }
280
            }
281
282
            $response = $this->httpClient->post($this->prepareUrl(), $config->toArray());
283
284
            $result = json_decode((string)$response->getBody(), true);
285
        } catch (ClientException $e) {
286
            $result = [
287
                'method' => $method,
288
                'error'  => $e->getMessage(),
289
                'body'   => $params,
290
            ];
291
        }
292
293
        return $result;
294
    }
295
296
    /**
297
     * Prepare URL to send the http request.
298
     *
299
     * @return string
300
     */
301
    protected function prepareUrl()
302
    {
303
        $address = rtrim($this->config['url'], '/');
304
305
        if (substr_compare($address, static::API_PATH, -strlen(static::API_PATH)) !== 0) {
306
            $address .= static::API_PATH;
307
        }
308
        //$address .= '/';
309
310
        return $address;
311
    }
312
313
    /**
314
     * Safely encode string in base64.
315
     * @param string $input
316
     * @return string
317
     */
318
    private function urlsafeB64Encode($input)
319
    {
320
        return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
321
    }
322
323
    /**
324
     * Sign message with secret key.
325
     * @param string $msg
326
     * @param string $key
327
     * @return string
328
     */
329
    private function sign($msg, $key)
330
    {
331
        return hash_hmac('sha256', $msg, $key, true);
332
    }
333
}
334