From 77e61847e1f39c95433e8c1947af5f3e0db25a5d Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Tue, 21 Jan 2020 18:35:41 +0100 Subject: [PATCH 01/12] Update to php74 --- composer.json | 6 ++-- examples/clientApi.php | 2 +- examples/popupLogin.php | 2 +- examples/userApi.php | 2 +- src/Api.php | 9 ++--- src/UserApi.php | 24 ++++++------- tests/ApiTest.phpt | 4 +-- tests/ClientApiTest.phpt | 18 +++++----- tests/UserApiTest.phpt | 74 ++++++++++++++++++++++------------------ 9 files changed, 74 insertions(+), 67 deletions(-) diff --git a/composer.json b/composer.json index c005229..fcaf3d1 100644 --- a/composer.json +++ b/composer.json @@ -10,13 +10,13 @@ } ], "require": { - "php": ">=5.4", - "guzzlehttp/guzzle": "^5.3" + "php": ">=7.4", + "guzzlehttp/guzzle": "^6.2" }, "require-dev": { "tracy/tracy": "^2.4", "nette/tester": "^1.7", - "mockery/mockery": "^0.9.9", + "mockery/mockery": "dev-master", "latte/latte": "^2.4" }, "autoload": { diff --git a/examples/clientApi.php b/examples/clientApi.php index c0da779..44975ec 100644 --- a/examples/clientApi.php +++ b/examples/clientApi.php @@ -3,7 +3,7 @@ require __DIR__ . '/bootstrap.php'; use GuzzleHttp\Exception\BadResponseException; -use GuzzleHttp\Message\Request; +use GuzzleHttp\Psr7\Request; use SizeID\OAuth2\ClientApi; diff --git a/examples/popupLogin.php b/examples/popupLogin.php index cd77550..4b76b79 100644 --- a/examples/popupLogin.php +++ b/examples/popupLogin.php @@ -1,6 +1,6 @@ addHeader('Authorization', 'Bearer ' . $this->getAccessToken()->getAccessToken()); - $request->setUrl($this->apiBaseUrl . '/' . $request->getUrl()); + $request->withAddedHeader('Authorization', 'Bearer ' . $this->getAccessToken()->getAccessToken()); + $request->withUri(new Uri($this->apiBaseUrl . '/' . $request->getUri())); return $request; } } \ No newline at end of file diff --git a/src/UserApi.php b/src/UserApi.php index a740994..2a96194 100644 --- a/src/UserApi.php +++ b/src/UserApi.php @@ -4,8 +4,9 @@ use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\ClientException; -use GuzzleHttp\Message\ResponseInterface; -use GuzzleHttp\Url; +use Psr\Http\Message\ResponseInterface; +use GuzzleHttp\Psr7\Uri; +use Psr\Http\Message\UriInterface; use SizeID\OAuth2\Entities\AccessToken; use SizeID\OAuth2\Exceptions\InvalidCSRFTokenException; use SizeID\OAuth2\Exceptions\InvalidStateException; @@ -69,16 +70,13 @@ public function __construct( */ public function getAuthorizationUrl() { - $url = Url::fromString($this->authorizationServerUrl); - $url->setQuery( - [ - 'response_type' => 'code', - 'client_id' => $this->clientId, - 'redirect_uri' => $this->redirectUri, - 'state' => $this->csrfTokenRepository->generateCSRFToken(), - ] - ); - return $url; + $url = new Uri($this->authorizationServerUrl); + return Uri::withQueryValues($url, [ + 'response_type' => 'code', + 'client_id' => $this->clientId, + 'redirect_uri' => $this->redirectUri, + 'state' => $this->csrfTokenRepository->generateCSRFToken(), + ]); } /** @@ -149,7 +147,7 @@ public function refreshAccessToken() $this->saveTokenFromResponse($response); } catch (ClientException $ex) { $response = $ex->getResponse(); - $sizeIdErrorCode = (int)$response->getHeader(self::SIZEID_ERROR_CODE_HEADER); + $sizeIdErrorCode = (int)$response->getHeaderLine(self::SIZEID_ERROR_CODE_HEADER); if ($response->getStatusCode() === 400 && $sizeIdErrorCode === 108) { //refresh token expired throw RedirectException::create( diff --git a/tests/ApiTest.phpt b/tests/ApiTest.phpt index 94f383a..aea4fb1 100644 --- a/tests/ApiTest.phpt +++ b/tests/ApiTest.phpt @@ -2,8 +2,8 @@ namespace SizeID\OAuth2\Tests; -use GuzzleHttp\Message\Request; -use GuzzleHttp\Message\Response; +use GuzzleHttp\Psr7\Request; +use GuzzleHttp\Psr7\Response; use Mockery as m; use SizeID\OAuth2\ClientApi; use SizeID\OAuth2\Entities\AccessToken; diff --git a/tests/ClientApiTest.phpt b/tests/ClientApiTest.phpt index ff59a28..bf3f0f8 100644 --- a/tests/ClientApiTest.phpt +++ b/tests/ClientApiTest.phpt @@ -2,12 +2,14 @@ namespace SizeID\OAuth2\Tests; -use GuzzleHttp\Message\Request; -use GuzzleHttp\Message\Response; +use GuzzleHttp\Psr7\Request; +use GuzzleHttp\Psr7\Response; use Mockery as m; +use Psr\Http\Message\StreamInterface; use SizeID\OAuth2\Api; use SizeID\OAuth2\ClientApi; use SizeID\OAuth2\Entities\AccessToken; +use SizeID\OAuth2\Repositories\SessionAccessTokenRepository; use Tester\Assert; use Tester\TestCase; @@ -27,7 +29,7 @@ class ClientApiTest extends TestCase public function testAcquireToken() { - $tokenRepository = m::mock('SizeID\OAuth2\Repositories\SessionAccessTokenRepository'); + $tokenRepository = m::mock(SessionAccessTokenRepository::class); $tokenRepository ->shouldReceive('hasAccessToken') ->andReturn(FALSE); @@ -38,7 +40,7 @@ class ClientApiTest extends TestCase ->shouldReceive('getAccessToken') ->andReturn($accessToken); $httpClient = m::mock('GuzzleHttp\Client'); - $stream = m::mock('GuzzleHttp\Stream\StreamInterface'); + $stream = m::mock(StreamInterface::class); $stream ->shouldReceive('getContents') ->andReturn('{"access_token":"token", "expires_in": 60}'); @@ -57,13 +59,13 @@ class ClientApiTest extends TestCase NULL, $httpClient ); - Assert::type('SizeID\OAuth2\ClientApi', $clientApi); + Assert::type(ClientApi::class, $clientApi); $clientApi->send(new Request('get', 'client')); } public function testRefreshToken() { - $tokenRepository = m::mock('SizeID\OAuth2\Repositories\SessionAccessTokenRepository'); + $tokenRepository = m::mock(SessionAccessTokenRepository::class); $tokenRepository ->shouldReceive('hasAccessToken') ->andReturn(TRUE); @@ -97,8 +99,8 @@ class ClientApiTest extends TestCase NULL, $httpClient ); - Assert::type('SizeID\OAuth2\ClientApi', $clientApi); - Assert::type('GuzzleHttp\Message\Response', $clientApi->send(new Request('POST', 'client'))); + Assert::type(ClientApi::class, $clientApi); + Assert::type(Response::class, $clientApi->send(new Request('POST', 'client'))); } } diff --git a/tests/UserApiTest.phpt b/tests/UserApiTest.phpt index f6bc07d..5789437 100644 --- a/tests/UserApiTest.phpt +++ b/tests/UserApiTest.phpt @@ -2,12 +2,19 @@ namespace SizeID\OAuth2\Tests; -use GuzzleHttp\Message\Request; -use GuzzleHttp\Message\Response; +use GuzzleHttp\ClientInterface; +use GuzzleHttp\Exception\ClientException; +use GuzzleHttp\Psr7\Request; +use GuzzleHttp\Psr7\Response; use Mockery as m; +use Psr\Http\Message\StreamInterface; use SizeID\OAuth2\Api; use SizeID\OAuth2\Entities\AccessToken; +use SizeID\OAuth2\Exceptions\InvalidCSRFTokenException; +use SizeID\OAuth2\Exceptions\InvalidStateException; use SizeID\OAuth2\Exceptions\RedirectException; +use SizeID\OAuth2\Repositories\AccessTokenRepositoryInterface; +use SizeID\OAuth2\Repositories\CsrfTokenRepositoryInterface; use SizeID\OAuth2\UserApi; use Tester\Assert; use Tester\TestCase; @@ -24,26 +31,26 @@ class UserApiTest extends TestCase 'clientSecret', 'http://9gag.com' ); - Assert::type('SizeID\OAuth2\UserApi', $clientApi); + Assert::type(UserApi::class, $clientApi); } public function testAuthorize() { - $tokenRepository = m::mock('SizeID\OAuth2\Repositories\AccessTokenRepositoryInterface'); + $tokenRepository = m::mock(AccessTokenRepositoryInterface::class); $tokenRepository ->shouldReceive('hasAccessToken') ->once() - ->andReturn(FALSE); + ->andReturn(false); $tokenRepository ->shouldReceive('saveAccessToken'); - $stateRepository = m::mock('SizeID\OAuth2\Repositories\CsrfTokenRepositoryInterface'); + $stateRepository = m::mock(CsrfTokenRepositoryInterface::class); $stateRepository ->shouldReceive('generateCSRFToken') ->andReturn('csrfToken'); $stateRepository ->shouldReceive('loadTokenCSRFToken') ->andReturn('csrfToken'); - $httpClient = m::mock('GuzzleHttp\ClientInterface'); + $httpClient = m::mock(ClientInterface::class); $userApi = new UserApi( 'clientId', 'clientSecret', @@ -56,7 +63,7 @@ class UserApiTest extends TestCase ); try { $userApi->send(new Request('get', 'user')); - Assert::fail('SizeID\OAuth2\Exceptions\RedirectException' . ' should be thrown'); + Assert::fail(RedirectException::class . ' should be thrown'); } catch (RedirectException $ex) { Assert::equal(RedirectException::CODE_MISSING_TOKEN, $ex->getCode()); Assert::equal( @@ -64,7 +71,7 @@ class UserApiTest extends TestCase (string)$ex->getRedirectUrl() ); } - $stream = m::mock('GuzzleHttp\Stream\StreamInterface'); + $stream = m::mock(StreamInterface::class); $stream ->shouldReceive('getContents') ->andReturn('{"access_token":"token", "expires_in": 60, "refresh_token": "refresh_token"}'); @@ -75,7 +82,7 @@ class UserApiTest extends TestCase $userApi->completeAuthorization("authCode", "csrfToken"); $tokenRepository ->shouldReceive('hasAccessToken') - ->andReturn(TRUE); + ->andReturn(true); $tokenRepository ->shouldReceive('deleteAccessToken'); $tokenRepository @@ -86,7 +93,7 @@ class UserApiTest extends TestCase function () use ($userApi) { $userApi->send(new Request('get', 'user')); }, - 'SizeID\OAuth2\Exceptions\InvalidStateException' + InvalidStateException::class ); $tokenRepository ->shouldReceive('getAccessToken') @@ -94,30 +101,30 @@ class UserApiTest extends TestCase $httpClient ->shouldReceive('send') ->andReturn(new Response(200)); - Assert::type('GuzzleHttp\Message\Response', $userApi->send(new Request('get', 'user'))); + Assert::type(Response::class, $userApi->send(new Request('get', 'user'))); } public function testRefreshToken() { - $tokenRepository = m::mock('SizeID\OAuth2\Repositories\AccessTokenRepositoryInterface'); + $tokenRepository = m::mock(AccessTokenRepositoryInterface::class); $tokenRepository ->shouldReceive('getAccessToken') - ->andReturn(new AccessToken('acessToken', 'refreshToken')); + ->andReturn(new AccessToken('accessToken', 'refreshToken')); $tokenRepository ->shouldReceive('saveAccessToken') ->with( m::on( function (AccessToken $accessToken) { Assert::equal('newRefreshToken', $accessToken->getRefreshToken()); - return TRUE; + return true; } ) ); - $stream = m::mock('GuzzleHttp\Stream\StreamInterface'); + $stream = m::mock(StreamInterface::class); $stream ->shouldReceive('getContents') ->andReturn('{"access_token":"token", "expires_in": 60, "refresh_token": "newRefreshToken"}'); - $httpClient = m::mock('GuzzleHttp\ClientInterface'); + $httpClient = m::mock(ClientInterface::class); $httpClient ->shouldReceive('post') ->andReturn(new Response(200, [], $stream)); @@ -129,18 +136,18 @@ class UserApiTest extends TestCase 'authServer', 'apiUrl', $httpClient, - NULL + null ); $userApi->refreshAccessToken(); } public function testInvalidRefreshToken() { - $tokenRepository = m::mock('SizeID\OAuth2\Repositories\AccessTokenRepositoryInterface'); + $tokenRepository = m::mock(AccessTokenRepositoryInterface::class); $tokenRepository ->shouldReceive('getAccessToken') - ->andReturn(new AccessToken('acessToken', 'refreshToken')); - $responseException = m::mock('GuzzleHttp\Exception\ClientException'); + ->andReturn(new AccessToken('accessToken', 'refreshToken')); + $responseException = m::mock(ClientException::class); $errorResponse = new Response( 400, [Api::SIZEID_ERROR_CODE_HEADER => "108"] @@ -148,7 +155,7 @@ class UserApiTest extends TestCase $responseException ->shouldReceive('getResponse') ->andReturn($errorResponse); - $httpClient = m::mock('GuzzleHttp\ClientInterface'); + $httpClient = m::mock(ClientInterface::class); $httpClient ->shouldReceive('post') ->once() @@ -161,18 +168,17 @@ class UserApiTest extends TestCase 'authServer', 'apiUrl', $httpClient, - NULL + null ); Assert::exception( function () use ($userApi) { $userApi->refreshAccessToken(); - } - , - 'SizeID\OAuth2\Exceptions\RedirectException', - NULL, + }, + RedirectException::class, + null, RedirectException::CODE_EXPIRED_REFRESH_TOKEN ); - $responseException = m::mock('GuzzleHttp\Exception\ClientException'); + $responseException = m::mock(ClientException::class); $errorResponse = new Response( 400 ); @@ -188,7 +194,7 @@ class UserApiTest extends TestCase $userApi->refreshAccessToken(); } , - 'GuzzleHttp\Exception\ClientException' + ClientException::class ); } @@ -196,7 +202,7 @@ class UserApiTest extends TestCase { $_GET['code'] = 'code'; $_GET['state'] = 'state1'; - $csrfTokenRepository = m::mock('SizeID\OAuth2\Repositories\CsrfTokenRepositoryInterface'); + $csrfTokenRepository = m::mock(CsrfTokenRepositoryInterface::class); $csrfTokenRepository ->shouldReceive('loadTokenCSRFToken') ->andReturn('state2'); @@ -204,17 +210,17 @@ class UserApiTest extends TestCase 'clientId', 'clientSecret', 'redirectUri', - NULL, + null, 'authServer', 'apiUrl', - NULL, - NULL + null, + null ); Assert::exception( function () use ($userApi) { $userApi->completeAuthorization(); }, - 'SizeID\OAuth2\Exceptions\InvalidCSRFTokenException', + InvalidCSRFTokenException::class, 'Invalid CSRF token.' ); } From 1a7a14b0ddd0906488743dd1d88d798ef311e760 Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Wed, 22 Jan 2020 11:33:46 +0100 Subject: [PATCH 02/12] Fix some of the old version bugs --- composer.json | 2 +- src/Api.php | 6 ++---- src/ClientApi.php | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index fcaf3d1..cd33ff6 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "php": ">=7.4", + "php": ">=5.4", "guzzlehttp/guzzle": "^6.2" }, "require-dev": { diff --git a/src/Api.php b/src/Api.php index 8045431..e5396ae 100644 --- a/src/Api.php +++ b/src/Api.php @@ -177,9 +177,7 @@ private function callApi(RequestInterface $request) */ private function buildRequest(RequestInterface $request) { - $request = clone $request; - $request->withAddedHeader('Authorization', 'Bearer ' . $this->getAccessToken()->getAccessToken()); - $request->withUri(new Uri($this->apiBaseUrl . '/' . $request->getUri())); - return $request; + return $request->withAddedHeader('Authorization', 'Bearer ' . $this->getAccessToken()->getAccessToken()) + ->withUri(new Uri($this->apiBaseUrl . '/' . $request->getUri())); } } \ No newline at end of file diff --git a/src/ClientApi.php b/src/ClientApi.php index 7b8519e..9c6648d 100644 --- a/src/ClientApi.php +++ b/src/ClientApi.php @@ -46,7 +46,7 @@ public function acquireNewAccessToken() $response = $this->httpClient->post( $this->authorizationServerUrl . '/access-token', [ - 'body' => [ + 'form_params' => [ 'grant_type' => 'client_credentials', 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, From 54d07eb746b19c575f8f2dde0160c60808d92f04 Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Wed, 22 Jan 2020 11:40:28 +0100 Subject: [PATCH 03/12] Use the trusty version of ubuntu because of ^php5 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8e60692..8575949 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: php - +dist: trusty sudo: required php: From 42d700e44866f5832ccab5b602dae0b00e5d0303 Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Wed, 22 Jan 2020 11:43:28 +0100 Subject: [PATCH 04/12] Change the php version to support guzzlehttp lib --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index cd33ff6..9755b1f 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "php": ">=5.4", + "php": ">=5.5", "guzzlehttp/guzzle": "^6.2" }, "require-dev": { From 08500bbd61438e738f931ad8a2ea67e52e47b404 Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Wed, 22 Jan 2020 11:50:56 +0100 Subject: [PATCH 05/12] Use older mockery, add newer versions of php to travis --- .travis.yml | 4 ++++ composer.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8575949..a997cbb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,10 @@ php: - 5.4 - 5.5 - 5.6 + - 7.1 + - 7.2 + - 7.3 + - 7.4 env: TEST_PARAMS='-c tests/php.ini' diff --git a/composer.json b/composer.json index 9755b1f..f61386b 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "require-dev": { "tracy/tracy": "^2.4", "nette/tester": "^1.7", - "mockery/mockery": "dev-master", + "mockery/mockery": "^0.9", "latte/latte": "^2.4" }, "autoload": { From 223307fa20e7cecfe50048ef448d72ec7bfe4810 Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Wed, 22 Jan 2020 11:52:58 +0100 Subject: [PATCH 06/12] Remove 5.4 from travis tested versions of php --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a997cbb..222ae02 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ dist: trusty sudo: required php: - - 5.4 - 5.5 - 5.6 - 7.1 From c48808691228130433d4d21a4e7547000bce156a Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Wed, 22 Jan 2020 12:03:01 +0100 Subject: [PATCH 07/12] Drop support for php5.5 because of mockery --- .travis.yml | 1 - composer.json | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 222ae02..edb8a09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ dist: trusty sudo: required php: - - 5.5 - 5.6 - 7.1 - 7.2 diff --git a/composer.json b/composer.json index f61386b..6645a5c 100644 --- a/composer.json +++ b/composer.json @@ -10,13 +10,13 @@ } ], "require": { - "php": ">=5.5", + "php": ">=5.6", "guzzlehttp/guzzle": "^6.2" }, "require-dev": { "tracy/tracy": "^2.4", "nette/tester": "^1.7", - "mockery/mockery": "^0.9", + "mockery/mockery": "^1.3", "latte/latte": "^2.4" }, "autoload": { From 392780d119d6df0a35f670ae6d15ad3212814411 Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Wed, 22 Jan 2020 12:12:35 +0100 Subject: [PATCH 08/12] Fix test coverage --- src/Api.php | 2 +- tests/ClientApiTest.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Api.php b/src/Api.php index e5396ae..7c08f19 100644 --- a/src/Api.php +++ b/src/Api.php @@ -155,7 +155,7 @@ protected function parseToken(ResponseInterface $response) private function createResponse(RequestInterface $request) { $response = $this->callApi($this->buildRequest($request)); - if ($response->getStatusCode() === 401 && $response->getHeader(self::SIZEID_ERROR_CODE_HEADER) == 109) { + if ($response->getStatusCode() === 401 && $response->getHeaderLine(self::SIZEID_ERROR_CODE_HEADER) == 109) { $this->refreshAccessToken(); return $this->callApi($this->buildRequest($request)); } diff --git a/tests/ClientApiTest.phpt b/tests/ClientApiTest.phpt index bf3f0f8..7b342ee 100644 --- a/tests/ClientApiTest.phpt +++ b/tests/ClientApiTest.phpt @@ -80,7 +80,7 @@ class ClientApiTest extends TestCase $httpClient ->shouldReceive('send') ->andReturn($response); - $stream = m::mock('GuzzleHttp\Stream\StreamInterface'); + $stream = m::mock(StreamInterface::class); $stream ->shouldReceive('getContents') ->andReturn('{"access_token":"token", "expires_in": 60}'); From 628f15de51b36e2b1b84d06cec51f34b092c5242 Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Mon, 27 Jan 2020 08:59:28 +0100 Subject: [PATCH 09/12] Fix issue with guzzlehttp throwing exception --- src/Api.php | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/Api.php b/src/Api.php index 7c08f19..ba35749 100644 --- a/src/Api.php +++ b/src/Api.php @@ -88,12 +88,6 @@ public function __construct( */ public function send(RequestInterface $request) { - $hasToken = $this->hasAccessToken(); - if (!is_bool($hasToken)) { - throw new InvalidStateException( - "Method 'AccessTokenRepositoryInterface:hasAccessToken' should return boolean." - ); - } if (!$this->hasAccessToken()) { $this->acquireNewAccessToken(); } @@ -113,7 +107,7 @@ public abstract function refreshAccessToken(); /** * @return bool */ - protected function hasAccessToken() + protected function hasAccessToken(): bool { return $this->accessTokenRepository->hasAccessToken(); } @@ -154,12 +148,16 @@ protected function parseToken(ResponseInterface $response) */ private function createResponse(RequestInterface $request) { - $response = $this->callApi($this->buildRequest($request)); - if ($response->getStatusCode() === 401 && $response->getHeaderLine(self::SIZEID_ERROR_CODE_HEADER) == 109) { - $this->refreshAccessToken(); - return $this->callApi($this->buildRequest($request)); + try { + $response = $this->callApi($this->buildRequest($request)); + } catch (ClientException $exception) { + $response = $exception->getResponse(); + if ($response->getStatusCode() === 401 && $response->getHeaderLine(self::SIZEID_ERROR_CODE_HEADER) == 109) { + $this->refreshAccessToken(); + return $this->callApi($this->buildRequest($request)); + } + return $response; } - return $response; } /** @@ -177,7 +175,8 @@ private function callApi(RequestInterface $request) */ private function buildRequest(RequestInterface $request) { - return $request->withAddedHeader('Authorization', 'Bearer ' . $this->getAccessToken()->getAccessToken()) + return $request + ->withAddedHeader('Authorization', 'Bearer ' . $this->getAccessToken()->getAccessToken()) ->withUri(new Uri($this->apiBaseUrl . '/' . $request->getUri())); } } \ No newline at end of file From a3ecfe511b7a04769e3b14d06fca30c46194b18e Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Mon, 27 Jan 2020 09:19:02 +0100 Subject: [PATCH 10/12] Always return response or throw exception --- src/Api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api.php b/src/Api.php index ba35749..3f4721b 100644 --- a/src/Api.php +++ b/src/Api.php @@ -156,8 +156,8 @@ private function createResponse(RequestInterface $request) $this->refreshAccessToken(); return $this->callApi($this->buildRequest($request)); } - return $response; } + return $response; } /** From f7fe4d84d729c895e1574a0ab518dd0abc188176 Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Mon, 27 Jan 2020 10:21:44 +0100 Subject: [PATCH 11/12] Fix a inconsistency in guzzle version --- src/Api.php | 38 +++++++++++++++++++++----------------- tests/ApiTest.phpt | 2 +- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/Api.php b/src/Api.php index 3f4721b..51cc3bf 100644 --- a/src/Api.php +++ b/src/Api.php @@ -60,19 +60,22 @@ public function __construct( $authorizationServerUrl, $apiBaseUrl, $httpClient - ) - { + ) { $this->clientId = $clientId; $this->clientSecret = $clientSecret; $this->accessTokenRepository = $accessTokenRepository; - if ($authorizationServerUrl === NULL) { + if ($authorizationServerUrl === null) { $authorizationServerUrl = Config::AUTHORIZATION_SERVER_URL; } - if ($apiBaseUrl === NULL) { + if ($apiBaseUrl === null) { $apiBaseUrl = Config::API_URL; } - if ($httpClient === NULL) { - $httpClient = new Client(); + if ($httpClient === null) { + $httpClient = new Client( + [ + RequestOptions::HTTP_ERRORS => false, + ] + ); } $this->authorizationServerUrl = $authorizationServerUrl; $this->apiBaseUrl = $apiBaseUrl; @@ -88,6 +91,12 @@ public function __construct( */ public function send(RequestInterface $request) { + $hasToken = $this->hasAccessToken(); + if (!is_bool($hasToken)) { + throw new InvalidStateException( + "Method 'AccessTokenRepositoryInterface:hasAccessToken' should return boolean." + ); + } if (!$this->hasAccessToken()) { $this->acquireNewAccessToken(); } @@ -107,7 +116,7 @@ public abstract function refreshAccessToken(); /** * @return bool */ - protected function hasAccessToken(): bool + protected function hasAccessToken() { return $this->accessTokenRepository->hasAccessToken(); } @@ -148,14 +157,10 @@ protected function parseToken(ResponseInterface $response) */ private function createResponse(RequestInterface $request) { - try { - $response = $this->callApi($this->buildRequest($request)); - } catch (ClientException $exception) { - $response = $exception->getResponse(); - if ($response->getStatusCode() === 401 && $response->getHeaderLine(self::SIZEID_ERROR_CODE_HEADER) == 109) { - $this->refreshAccessToken(); - return $this->callApi($this->buildRequest($request)); - } + $response = $this->callApi($this->buildRequest($request)); + if ($response->getStatusCode() === 401 && $response->getHeaderLine(self::SIZEID_ERROR_CODE_HEADER) == 109) { + $this->refreshAccessToken(); + return $this->callApi($this->buildRequest($request)); } return $response; } @@ -175,8 +180,7 @@ private function callApi(RequestInterface $request) */ private function buildRequest(RequestInterface $request) { - return $request - ->withAddedHeader('Authorization', 'Bearer ' . $this->getAccessToken()->getAccessToken()) + return $request->withAddedHeader('Authorization', 'Bearer ' . $this->getAccessToken()->getAccessToken()) ->withUri(new Uri($this->apiBaseUrl . '/' . $request->getUri())); } } \ No newline at end of file diff --git a/tests/ApiTest.phpt b/tests/ApiTest.phpt index aea4fb1..240e9bb 100644 --- a/tests/ApiTest.phpt +++ b/tests/ApiTest.phpt @@ -20,7 +20,7 @@ class ApiTest extends TestCase $tokenRepository = m::mock('SizeID\OAuth2\Repositories\SessionAccessTokenRepository'); $tokenRepository ->shouldReceive('hasAccessToken') - ->andReturn(NULL); + ->andReturn(null); $clientApi = new ClientApi( 'clientId', 'clientSecret', From d5c39842b07bea49237cff184ac9030ee02e3850 Mon Sep 17 00:00:00 2001 From: Tomas Rokos Date: Mon, 27 Jan 2020 10:25:26 +0100 Subject: [PATCH 12/12] Use request options --- src/Api.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Api.php b/src/Api.php index 51cc3bf..0ef86dc 100644 --- a/src/Api.php +++ b/src/Api.php @@ -11,6 +11,7 @@ use SizeID\OAuth2\Entities\AccessToken; use SizeID\OAuth2\Exceptions\InvalidStateException; use SizeID\OAuth2\Repositories\AccessTokenRepositoryInterface; +use GuzzleHttp\RequestOptions; /** * Shared functionality of API calls