Notification Setup Error

We have detected an error in your notification set-up (Event-ID dab39dc24f564ec7bd4628d1305fd03c). Currently, we cannot inform you about inspection progress. Please check that the user 557058:bca11929-8c2d-43f2-8a82-c5416880d395 still has access to your repository or update the API account.

Completed
Pull Request — develop ( #41 )
by
unknown
27:26 queued 12:27
created

OAuth2Plugin   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 7
dl 0
loc 109
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 2
A handleRequest() 0 30 5
A getAccessToken() 0 34 4
1
<?php
2
/**
3
 * This file is part of the bitbucket-api package.
4
 *
5
 * (c) Alexandru Guzinschi <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Bitbucket\API\Http\Plugin;
12
13
use Bitbucket\API\Exceptions\ForbiddenAccessException;
14
use Bitbucket\API\Exceptions\HttpResponseException;
15
use Bitbucket\API\Http\Client;
16
use Bitbucket\API\Http\ClientInterface;
17
use Http\Client\Common\Plugin;
18
use Psr\Http\Message\RequestInterface;
19
20
/**
21
 * @author Alexandru Guzinschi <[email protected]>
22
 */
23
class OAuth2Plugin implements Plugin
24
{
25
    const ENDPOINT_ACCESS_TOKEN     = 'access_token';
26
    const ENDPOINT_AUTHORIZE        = 'authorize';
27
28
    /** @var array */
29
    private $config = array(
30
        'oauth_client_id'       => 'anon',
31
        'oauth_client_secret'   => 'anon',
32
        'token_type'            => 'bearer',
33
        'scopes'                => array()
34
    );
35
36
    /** @var ClientInterface */
37
    private $httpClient;
38
39
    public function __construct(array $config, ClientInterface $client = null)
40
    {
41
        $this->config       = array_merge($this->config, $config);
42
        $this->httpClient   = (null !== $client) ? $client : new Client(
43
            array(
44
                'base_url'      => 'https://bitbucket.org/site',
45
                'api_version'   => 'oauth2',
46
                'api_versions'  => array('oauth2')
47
            )
48
        );
49
    }
50
51
    /**
52
     * {@inheritDoc}
53
     *
54
     * @throws ForbiddenAccessException
55
     * @throws \InvalidArgumentException
56
     */
57
    public function handleRequest(RequestInterface $request, callable $next, callable $first)
58
    {
59
        $oauth2Header = $request->getHeader('Authorization');
60
        foreach ($oauth2Header as $header) {
61
            if (strpos($header, 'Bearer') !== false) {
62
                return $next($request);
63
            }
64
        }
65
66
        if (false === array_key_exists('access_token', $this->config)) {
67
            try {
68
                $data = $this->getAccessToken();
69
                $this->config['token_type']     = $data['token_type'];
70
                $this->config['access_token']   = $data['access_token'];
71
            } catch (HttpResponseException $e) {
72
                throw new ForbiddenAccessException("Can't fetch access_token.", 0, $e);
73
            }
74
        }
75
76
        $request = $request->withHeader(
77
            'Authorization',
78
            sprintf(
79
                '%s %s',
80
                ucfirst(strtolower($this->config['token_type'])),
81
                $this->config['access_token']
82
            )
83
        );
84
85
        return $next($request);
86
    }
87
88
    /**
89
     * Fetch access token with a grant_type of client_credentials
90
     *
91
     * @access public
92
     * @return array
93
     *
94
     * throws \InvalidArgumentException
95
     * @throws HttpResponseException
96
     */
97
    protected function getAccessToken()
98
    {
99
        $response = $this->httpClient
100
            ->post(
101
                self::ENDPOINT_ACCESS_TOKEN,
102
                array(
103
                    'grant_type'    => 'client_credentials',
104
                    'client_id'     => $this->config['client_id'],
105
                    'client_secret' => $this->config['client_secret'],
106
                    'scope'         => implode(',', $this->config['scopes'])
107
                )
108
            )
109
        ;
110
111
        $contents = $response->getBody()->getContents();
112
        $data = json_decode($contents, true);
113
114
        if (json_last_error() !== JSON_ERROR_NONE) {
115
            $ex = new HttpResponseException('[access_token] Invalid JSON: '. json_last_error_msg());
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $ex. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
116
            $request = $this->httpClient instanceof Client ? $this->httpClient->getLastRequest() : null;
117
            $ex
118
                ->setResponse($response)
0 ignored issues
show
Documentation introduced by
$response is of type object<Psr\Http\Message\ResponseInterface>, but the function expects a object<Buzz\Message\MessageInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
119
                ->setRequest($request)
0 ignored issues
show
Documentation introduced by
$request is of type object<Psr\Http\Message\RequestInterface>|null, but the function expects a object<Buzz\Message\RequestInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
120
            ;
121
122
            throw $ex;
123
        }
124
125
        if (false === array_key_exists('access_token', $data)) {
126
            throw new HttpResponseException('access_token is missing from response. '. $contents);
127
        }
128
129
        return $data;
130
    }
131
}
132