Passed
Push — master ( 84c7f1...946eed )
by Ehsan
03:42
created

OAuth::doOauth()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 6.0359

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 9
cts 10
cp 0.9
rs 8.6737
c 0
b 0
f 0
cc 6
eloc 11
nc 8
nop 2
crap 6.0359
1
<?php
2
3
namespace Botonomous;
4
5
use Botonomous\client\ApiClient;
6
use Botonomous\utility\RequestUtility;
7
use Botonomous\utility\SecurityUtility;
8
use Botonomous\utility\SessionUtility;
9
10
/**
11
 * Class OAuth.
12
 */
13
class OAuth
14
{
15
    const AUTHORIZATION_URL = 'https://slack.com/oauth/authorize';
16
    const SESSION_STATE_KEY = 'state';
17
18
    private $clientId;
19
    private $clientSecret;
20
    private $scopes;
21
    private $redirectUri;
22
    private $state;
23
    private $teamId;
24
    private $apiClient;
25
    private $sessionUtility;
26
    private $requestUtility;
27
28
    /**
29
     * @var string configuration_url will be the URL that you can point your user to if they'd like to edit
30
     *             or remove this integration in Slack
31
     */
32
    private $configurationUrl;
33
34
    /**
35
     * @var string The team_name field will be the name of the team that installed your app
36
     */
37
    private $teamName;
38
    private $accessToken;
39
40
    /**
41
     * @var string the channel will be the channel name that they have chosen to post to
42
     */
43
    private $channel;
44
45
    /**
46
     * @var string you will need to use bot_user_id and bot_access_token whenever you are acting on behalf of
47
     *             that bot user for that team context.
48
     *             Use the top-level access_token value for other integration points.
49
     */
50
    private $botUserId;
51
    private $botAccessToken;
52
53
    private $config;
54
55
    /**
56
     * OAuth constructor.
57
     *
58
     * @param       $clientId
59
     * @param       $clientSecret
60
     * @param array $scopes
61
     */
62 25
    public function __construct($clientId = '', $clientSecret = '', array $scopes = [])
63
    {
64 25
        $this->setClientId($clientId);
65 25
        $this->setClientSecret($clientSecret);
66 25
        $this->setScopes($scopes);
67 25
    }
68
69
    /**
70
     * @return string
71
     */
72 6
    public function getClientId()
73
    {
74 6
        if (empty($this->clientId)) {
75 3
            $this->setClientId($this->getConfig()->get('clientId'));
76
        }
77
78 6
        return $this->clientId;
79
    }
80
81
    /**
82
     * @param string $clientId
83
     */
84 25
    public function setClientId($clientId)
85
    {
86 25
        $this->clientId = $clientId;
87 25
    }
88
89
    /**
90
     * @return array
91
     */
92 2
    public function getScopes()
93
    {
94 2
        if (empty($this->scopes)) {
95 1
            $this->setScopes($this->getConfig()->get('scopes'));
96
        }
97
98 2
        return $this->scopes;
99
    }
100
101
    /**
102
     * @param array $scopes
103
     */
104 25
    public function setScopes(array $scopes)
105
    {
106 25
        $this->scopes = $scopes;
107 25
    }
108
109
    /**
110
     * @return string
111
     */
112 1
    public function getRedirectUri()
113
    {
114 1
        return $this->redirectUri;
115
    }
116
117
    /**
118
     * @param string $redirectUri
119
     */
120 1
    public function setRedirectUri($redirectUri)
121
    {
122 1
        $this->redirectUri = $redirectUri;
123 1
    }
124
125
    /**
126
     * @return string
127
     */
128 2
    public function getState()
129
    {
130 2
        if (!isset($this->state)) {
131 2
            $this->setState((new SecurityUtility())->generateToken());
132
        }
133
134 2
        return $this->state;
135
    }
136
137
    /**
138
     * @param string $state
139
     */
140 2
    public function setState($state)
141
    {
142 2
        $this->getSessionUtility()->set(self::SESSION_STATE_KEY, $state);
143 2
        $this->state = $state;
144 2
    }
145
146
    /**
147
     * @param $state
148
     *
149
     * @return bool
150
     */
151 5
    public function verifyState($state)
152
    {
153 5
        if (empty($state)) {
154 2
            return false;
155
        }
156
157 3
        return $state === $this->getSessionUtility()->get(self::SESSION_STATE_KEY) ? true : false;
158
    }
159
160
    /**
161
     * @return int
162
     */
163 1
    public function getTeamId()
164
    {
165 1
        return $this->teamId;
166
    }
167
168
    /**
169
     * @param int $teamId
170
     */
171 2
    public function setTeamId($teamId)
172
    {
173 2
        $this->teamId = $teamId;
174 2
    }
175
176
    /**
177
     * @param string $height
178
     * @param string $weight
179
     * @param string $cssClass
180
     *
181
     * @return string
182
     */
183 1
    public function generateAddButton($height = '40', $weight = '139', $cssClass = '')
184
    {
185 1
        $authorizationUrl = self::AUTHORIZATION_URL;
186 1
        $scope = implode(',', $this->getScopes());
187 1
        $clientId = $this->getClientId();
188
189 1
        $stateQueryString = '';
190 1
        if (!empty($this->getState())) {
191 1
            $state = $this->getState();
192 1
            $stateQueryString = "&state={$state}";
193
        }
194
195 1
        $href = "{$authorizationUrl}?scope={$scope}&client_id={$clientId}{$stateQueryString}";
196
197 1
        $html = "<a href='{$href}'>
198 1
<img alt='Add to Slack' class='{$cssClass}' height='{$height}' width='{$weight}'
199
src='https://platform.slack-edge.com/img/add_to_slack.png'
200
srcset='https://platform.slack-edge.com/img/add_to_slack.png 1x,
201 1
https://platform.slack-edge.com/img/[email protected] 2x' /></a>";
202
203 1
        return $html;
204
    }
205
206
    /**
207
     * @param      $code
208
     * @param bool $verifyState State is checked against the value in the session
209
     * @param null $state
210
     *
211
     * @throws \Exception
212
     *
213
     * @return mixed
214
     */
215 10
    public function getAccessToken($code, $verifyState = true, $state = null)
216
    {
217 10
        if (!isset($this->accessToken)) {
218 7
            if ($verifyState === true && $this->verifyState($state) !== true) {
219 3
                throw new \Exception("State: '{$state}' is not valid");
220
            }
221
222
            try {
223 4
                $this->handleRequestAccessTokenResponse($this->requestAccessToken($code));
224 3
            } catch (\Exception $e) {
225 3
                throw $e;
226
            }
227
        }
228
229 4
        return $this->accessToken;
230
    }
231
232
    /**
233
     * @param $response
234
     *
235
     * @throws \Exception
236
     */
237 2
    private function handleRequestAccessTokenResponse($response)
238
    {
239 2
        if ($response['ok'] !== true) {
240 1
            throw new \Exception($response['error']);
241
        }
242
243 1
        $this->setAccessToken($response['access_token']);
244 1
        $this->setTeamId($response['team_id']);
245 1
        $this->setBotUserId($response['bot']['bot_user_id']);
246 1
        $this->setBotAccessToken($response['bot']['bot_access_token']);
247
248 1
        $channel = '';
249 1
        if (isset($response['incoming_webhook']['channel'])) {
250 1
            $channel = $response['incoming_webhook']['channel'];
251
        }
252
253 1
        $this->setChannel($channel);
254 1
    }
255
256
    /**
257
     * @param $code
258
     *
259
     * @throws \Exception
260
     *
261
     * @return mixed
262
     */
263 4
    private function requestAccessToken($code)
264
    {
265 4
        if (empty($code)) {
266 1
            throw new \Exception('Code must be provided to get the access token');
267
        }
268
269
        try {
270 3
            return $this->getApiClient()->oauthAccess([
271 3
                'client_id'     => $this->getClientId(),
272 3
                'client_secret' => $this->getClientSecret(),
273 3
                'code'          => $code,
274
            ]);
275 1
        } catch (\Exception $e) {
276 1
            throw $e;
277
        }
278
    }
279
280
    /**
281
     * @param $accessToken
282
     */
283 4
    public function setAccessToken($accessToken)
284
    {
285 4
        $this->accessToken = $accessToken;
286 4
    }
287
288
    /**
289
     * @return string
290
     */
291 4
    public function getClientSecret()
292
    {
293 4
        if (empty($this->clientSecret)) {
294 3
            $this->setClientSecret($this->getConfig()->get('clientSecret'));
295
        }
296
297 4
        return $this->clientSecret;
298
    }
299
300
    /**
301
     * @param string $clientSecret
302
     */
303 25
    public function setClientSecret($clientSecret)
304
    {
305 25
        $this->clientSecret = $clientSecret;
306 25
    }
307
308
    /**
309
     * @return string
310
     */
311 1
    public function getBotUserId()
312
    {
313 1
        return $this->botUserId;
314
    }
315
316
    /**
317
     * @param string $botUserId
318
     */
319 2
    public function setBotUserId($botUserId)
320
    {
321 2
        $this->botUserId = $botUserId;
322 2
    }
323
324
    /**
325
     * @return string
326
     */
327 1
    public function getBotAccessToken()
328
    {
329 1
        return $this->botAccessToken;
330
    }
331
332
    /**
333
     * @param string $botAccessToken
334
     */
335 2
    public function setBotAccessToken($botAccessToken)
336
    {
337 2
        $this->botAccessToken = $botAccessToken;
338 2
    }
339
340
    /**
341
     * @return string
342
     */
343 1
    public function getChannel()
344
    {
345 1
        return $this->channel;
346
    }
347
348
    /**
349
     * @param string $channel
350
     */
351 2
    public function setChannel($channel)
352
    {
353 2
        $this->channel = $channel;
354 2
    }
355
356
    /**
357
     * @return string
358
     */
359 1
    public function getTeamName()
360
    {
361 1
        return $this->teamName;
362
    }
363
364
    /**
365
     * @param string $teamName
366
     */
367 1
    public function setTeamName($teamName)
368
    {
369 1
        $this->teamName = $teamName;
370 1
    }
371
372
    /**
373
     * @return string
374
     */
375 1
    public function getConfigurationUrl()
376
    {
377 1
        return $this->configurationUrl;
378
    }
379
380
    /**
381
     * @param string $configurationUrl
382
     */
383 1
    public function setConfigurationUrl($configurationUrl)
384
    {
385 1
        $this->configurationUrl = $configurationUrl;
386 1
    }
387
388
    /**
389
     * @return ApiClient
390
     */
391 4
    public function getApiClient()
392
    {
393 4
        if (!isset($this->apiClient)) {
394 2
            $this->setApiClient(new ApiClient());
395
        }
396
397 4
        return $this->apiClient;
398
    }
399
400
    /**
401
     * @param ApiClient $apiClient
402
     */
403 4
    public function setApiClient(ApiClient $apiClient)
404
    {
405 4
        $this->apiClient = $apiClient;
406 4
    }
407
408
    /**
409
     * @param SessionUtility $sessionUtility
410
     */
411 4
    public function setSessionUtility(SessionUtility $sessionUtility)
412
    {
413 4
        $this->sessionUtility = $sessionUtility;
414 4
    }
415
416
    /**
417
     * @return SessionUtility|null
418
     */
419 4
    public function getSessionUtility()
420
    {
421 4
        if (!isset($this->sessionUtility)) {
422 2
            $this->setSessionUtility(new SessionUtility());
423
        }
424
425 4
        return $this->sessionUtility;
426
    }
427
428
    /**
429
     * @return Config
430
     */
431 5
    public function getConfig()
432
    {
433 5
        if (!isset($this->config)) {
434 4
            $this->setConfig(new Config());
435
        }
436
437 5
        return $this->config;
438
    }
439
440
    /**
441
     * @param Config $config
442
     */
443 5
    public function setConfig(Config $config)
444
    {
445 5
        $this->config = $config;
446 5
    }
447
448
    /**
449
     * @param null $code
450
     * @param null $state
451
     *
452
     * @throws \Exception
453
     *
454
     * @return bool
455
     */
456 4
    public function doOauth($code = null, $state = null)
457
    {
458 4
        $getRequest = $this->getRequestUtility()->getGet();
459
460
        // get code from GET request
461 4
        if ($code === null && isset($getRequest['code'])) {
462 3
            $code = $getRequest['code'];
463
        }
464
465
        // get state from GET request
466 4
        if ($state === null && isset($getRequest['state'])) {
467 3
            $state = $getRequest['state'];
468
        }
469
470
        try {
471 4
            $this->processAccessToken($this->getAccessToken($code, true, $state));
472 4
        } catch (\Exception $e) {
473 4
            throw $e;
474
        }
475
476
        return true;
477
    }
478
479
    /**
480
     * @param $accessToken
481
     *
482
     * @throws \Exception
483
     */
484 1
    private function processAccessToken($accessToken)
485
    {
486 1
        if (empty($accessToken)) {
487 1
            throw new \Exception('Access token is not provided');
488
        }
489
490
        // do whatever you want with the access token
491
    }
492
493
    /**
494
     * @return RequestUtility
495
     */
496 5
    public function getRequestUtility()
497
    {
498 5
        if (!isset($this->requestUtility)) {
499 1
            $this->setRequestUtility((new RequestUtility()));
500
        }
501
502 5
        return $this->requestUtility;
503
    }
504
505
    /**
506
     * @param RequestUtility $requestUtility
507
     */
508 5
    public function setRequestUtility(RequestUtility $requestUtility)
509
    {
510 5
        $this->requestUtility = $requestUtility;
511 5
    }
512
}
513