From 47d3cd2ed79de2798b32f32e80cefab55effe92b Mon Sep 17 00:00:00 2001 From: Thierry Goettelmann Date: Thu, 6 Aug 2015 15:15:10 +0200 Subject: [PATCH 1/7] Update Guzzle to 6.0 Rewrite API for to support new Guzzle 6.0 --- composer.json | 2 +- src/Api.php | 200 ++++++++++++++++++++++++++++---------------------- 2 files changed, 113 insertions(+), 89 deletions(-) diff --git a/composer.json b/composer.json index dc36127..7ace00a 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "Wrapper for OVH APIs", "license": "BSD-3-Clause", "require": { - "guzzlehttp/guzzle": ">=4.0,<6.0" + "guzzlehttp/guzzle": "^6.0" }, "authors": [ { diff --git a/src/Api.php b/src/Api.php index ba28784..ef3de42 100644 --- a/src/Api.php +++ b/src/Api.php @@ -30,8 +30,9 @@ namespace Ovh; -use GuzzleHttp\Client as GClient; -use GuzzleHttp\Stream\Stream; +use GuzzleHttp\Client; +use GuzzleHttp\Psr7\Request; +use GuzzleHttp\Psr7\Response; /** * Wrapper to manage login and exchanges with simpliest Ovh API @@ -41,74 +42,90 @@ * Http connections use guzzle http client api and result of request are * object from this http wrapper * - * @package Ovh + * @package Ovh * @category Ovh - * @author Vincent Cassé + * @author Vincent Cassé + * @author Thierry Goettelmann */ class Api { - /** * Url to communicate with Ovh API + * + * @var array */ - private $endpoints = array( - 'ovh-eu' => 'https://api.ovh.com/1.0', - 'ovh-ca' => 'https://ca.api.ovh.com/1.0', - 'kimsufi-eu' => 'https://eu.api.kimsufi.com/1.0', - 'kimsufi-ca' => 'https://ca.api.kimsufi.com/1.0', + private $endpoints = [ + 'ovh-eu' => 'https://api.ovh.com/1.0', + 'ovh-ca' => 'https://ca.api.ovh.com/1.0', + 'kimsufi-eu' => 'https://eu.api.kimsufi.com/1.0', + 'kimsufi-ca' => 'https://ca.api.kimsufi.com/1.0', 'soyoustart-eu' => 'https://eu.api.soyoustart.com/1.0', 'soyoustart-ca' => 'https://ca.api.soyoustart.com/1.0', - 'runabove-ca' => 'https://api.runabove.com/1.0'); + 'runabove-ca' => 'https://api.runabove.com/1.0', + ]; /** * Contain endpoint selected to choose API + * + * @var string */ private $endpoint = null; /** * Contain key of the current application + * + * @var string */ private $application_key = null; /** * Contain secret of the current application + * + * @var string */ private $application_secret = null; /** * Contain consumer key of the current application + * + * @var string */ private $consumer_key = null; /** * Contain delta between local timestamp and api server timestamp + * + * @var string */ private $time_delta = null; /** * Contain http client connection + * + * @var Client */ private $http_client = null; /** * Construct a new wrapper instance * - * @param $application_key key of your application. - * For OVH APIs, you can create a application's credentials on https://api.ovh.com/createApp/ - * @param $application_secret secret of your application. - * @param $api_endpoint name of api selected - * @param $consumer_key If you have already a consumer key, this parameter prevent to do a - * new authentication - * @param $http_client instance of http client + * @param string $application_key key of your application. + * For OVH APIs, you can create a application's credentials on + * https://api.ovh.com/createApp/ + * @param string $application_secret secret of your application. + * @param string $api_endpoint name of api selected + * @param string $consumer_key If you have already a consumer key, this parameter prevent to do a + * new authentication + * @param Client $http_client instance of http client * - * @throws InvalidParameterException if one parameter is missing or with bad value + * @throws Exceptions\InvalidParameterException if one parameter is missing or with bad value */ public function __construct( $application_key, $application_secret, $api_endpoint, $consumer_key = null, - GClient $http_client = null + Client $http_client = null ) { if (!isset($application_key)) { throw new Exceptions\InvalidParameterException("Application key parameter is empty"); @@ -127,29 +144,31 @@ public function __construct( } if (!isset($http_client)) { - $http_client = new GClient(); + $http_client = new Client(); } - $this->application_key = $application_key; - $this->endpoint = $this->endpoints[$api_endpoint]; + $this->application_key = $application_key; + $this->endpoint = $this->endpoints[$api_endpoint]; $this->application_secret = $application_secret; - $this->http_client = $http_client; - $this->consumer_key = $consumer_key; - $this->time_delta = null; + $this->http_client = $http_client; + $this->consumer_key = $consumer_key; + $this->time_delta = null; } /** * Calculate time delta between local machine and API's server * * @throws \GuzzleHttp\Exception\ClientException if http request is an error + * @return int */ private function calculateTimeDelta() { if (!isset($this->time_delta)) { - $response = $this->http_client->get($this->endpoint . "/auth/time"); - $serverTimestamp = (int) (String) $response->getBody(); - $this->time_delta = $serverTimestamp - (int) \time(); + $response = $this->http_client->get($this->endpoint . "/auth/time"); + $serverTimestamp = (int)(String)$response->getBody(); + $this->time_delta = $serverTimestamp - (int)\time(); } + return $this->time_delta; } @@ -157,16 +176,17 @@ private function calculateTimeDelta() * Request a consumer key from the API and the validation link to * authorize user to validate this consumer key * - * @param $accessRules list of rules your application need. - * @param $redirection url to redirect on your website after authentication + * @param array $accessRules list of rules your application need. + * @param string $redirection url to redirect on your website after authentication * + * @return mixed * @throws \GuzzleHttp\Exception\ClientException if http request is an error */ public function requestCredentials( - $accessRules, + array $accessRules, $redirection = null ) { - $parameters = new \StdClass(); + $parameters = new \StdClass(); $parameters->accessRules = $accessRules; $parameters->redirection = $redirection; @@ -179,6 +199,7 @@ public function requestCredentials( ); $this->consumer_key = $response["consumerKey"]; + return $response; } @@ -186,42 +207,44 @@ public function requestCredentials( * This is the main method of this wrapper. It will * sign a given query and return its result. * - * @param $method HTTP method of request (GET,POST,PUT,DELETE) - * @param $path relative url of API request - * @param $content body of the request - * @param $is_authenticated if the request use authentication + * @param string $method HTTP method of request (GET,POST,PUT,DELETE) + * @param string $path relative url of API request + * @param \stdClass|array|null $content body of the request + * @param bool $is_authenticated if the request use authentication * + * @return array * @throws \GuzzleHttp\Exception\ClientException if http request is an error */ - private function rawCall( - $method, - $path, - $content = null, - $is_authenticated = true - ) { - $url = $this->endpoint . $path; - - $request = $this->http_client->createRequest( - $method, - $url - ); + private function rawCall($method, $path, $content = null, $is_authenticated = true) + { + $url = $this->endpoint . $path; + $request = new Request($method, $url); if (isset($content) && $method == 'GET') { - $query = $request->getQuery(); - foreach ($content as $key => $value) { - $query->set($key, $value); - } - $url .= '?'.$query; - $body = ""; + + $queryString = $request->getUri()->getQuery(); + + $query = false !== strpos($queryString, '&') + ? explode('&', $queryString) + : []; + + $query = array_merge($query, (array)$content); + $query = \GuzzleHttp\Psr7\build_query($query); + + $request = $request->withUri($request->getUri()->withQuery($query)); + $body = ""; } elseif (isset($content)) { $body = json_encode($content); - $request->setBody(Stream::factory($body)); + + $request->getBody()->write($body); } else { $body = ""; } - $request->setHeader('Content-Type', 'application/json; charset=utf-8'); - $request->setHeader('X-Ovh-Application', $this->application_key); + $headers = [ + 'Content-Type' => 'application/json; charset=utf-8', + 'X-Ovh-Application' => $this->application_key, + ]; if ($is_authenticated) { if (!isset($this->time_delta)) { @@ -229,75 +252,76 @@ private function rawCall( } $now = time() + $this->time_delta; - $request->setHeader('X-Ovh-Timestamp', $now); + $headers['X-Ovh-Timestamp'] = $now; if (isset($this->consumer_key)) { - $toSign = $this->application_secret.'+'.$this->consumer_key.'+'.$method.'+'.$url.'+'.$body.'+'.$now; - $signature = '$1$' . sha1($toSign); - $request->setHeader('X-Ovh-Consumer', $this->consumer_key); - $request->setHeader('X-Ovh-Signature', $signature); + $toSign = $this->application_secret . '+' . $this->consumer_key . '+' . $method + . '+' . $url . '+' . $body . '+' . $now; + $signature = '$1$' . sha1($toSign); + $headers['X-Ovh-Consumer'] = $this->consumer_key; + $headers['X-Ovh-Signature'] = $signature; } } - return $this->http_client->send($request)->json(); + + /** @var Response $response */ + $response = $this->http_client->send($request, ['headers' => $headers]); + + return json_decode($response->getBody(), true); } /** * Wrap call to Ovh APIs for GET requests * - * @param $path path ask inside api - * @param $content content to send inside body of request + * @param string $path path ask inside api + * @param array $content content to send inside body of request * + * @return array * @throws \GuzzleHttp\Exception\ClientException if http request is an error */ - public function get( - $path, - $content = null - ) { + public function get($path, $content = null) + { return $this->rawCall("GET", $path, $content); } /** * Wrap call to Ovh APIs for POST requests * - * @param $path path ask inside api - * @param $content content to send inside body of request + * @param string $path path ask inside api + * @param array $content content to send inside body of request * + * @return array * @throws \GuzzleHttp\Exception\ClientException if http request is an error */ - public function post( - $path, - $content = null - ) { + public function post($path, $content = null) + { return $this->rawCall("POST", $path, $content); } /** * Wrap call to Ovh APIs for PUT requests * - * @param $path path ask inside api - * @param $content content to send inside body of request + * @param string $path path ask inside api + * @param array $content content to send inside body of request * + * @return array * @throws \GuzzleHttp\Exception\ClientException if http request is an error */ - public function put( - $path, - $content - ) { + public function put($path, $content) + { return $this->rawCall("PUT", $path, $content); } /** * Wrap call to Ovh APIs for DELETE requests * - * @param $path path ask inside api - * @param $content content to send inside body of request + * @param string $path path ask inside api + * @param array $content content to send inside body of request * + * @return array * @throws \GuzzleHttp\Exception\ClientException if http request is an error */ - public function delete( - $path, - $content = null - ) { + public function delete($path, $content = null) + { return $this->rawCall("DELETE", $path, $content); } From 6ecf7c2773708c53f7df92a4ad4365e5566251bb Mon Sep 17 00:00:00 2001 From: Thierry Goettelmann Date: Thu, 6 Aug 2015 15:15:19 +0200 Subject: [PATCH 2/7] Added 100% Code Coverage Signed-off-by: Thierry Goettelmann --- tests/ApiFunctionalTest.php | 278 ++++++++++++++++++++----------- tests/ApiTest.php | 319 +++++++++++++++++++++++++----------- 2 files changed, 400 insertions(+), 197 deletions(-) diff --git a/tests/ApiFunctionalTest.php b/tests/ApiFunctionalTest.php index 415fd24..61ddb02 100644 --- a/tests/ApiFunctionalTest.php +++ b/tests/ApiFunctionalTest.php @@ -28,136 +28,220 @@ namespace Ovh\tests; use GuzzleHttp\Client; -use GuzzleHttp\Subscriber\Mock; use Ovh\Api; /** * Functional tests of Api class * - * @package Ovh + * @package Ovh * @category Ovh - * @author Vincent Cassé + * @author Vincent Cassé + * @author Thierry Goettelmann */ -class ApiFunctionalTest extends \PHPUnit_Framework_TestCase { +class ApiFunctionalTest extends \PHPUnit_Framework_TestCase +{ - /** - * Define id to create object - */ - protected function setUp() + /** + * @var string + */ + private $application_key; + + /** + * @var string + */ + private $application_secret; + + /** + * @var string + */ + private $consumer_key; + + /** + * @var string + */ + private $endpoint; + + /** + * @var string + */ + private $rangeIP; + + /** + * @var string + */ + private $alternativeRangeIP; + + /** + * @var Client + */ + private $client; + + /** + * @var Api + */ + private $api; + + /** + * Define id to create object + */ + protected function setUp() { - $this->application_key = getenv('APP_KEY'); - $this->application_secret = getenv('APP_SECRET'); - $this->consumer_key = getenv('CONSUMER'); - $this->endpoint = getenv('ENDPOINT'); - $this->rangeIP = '127.0.0.20/32'; + $this->application_key = getenv('APP_KEY'); + $this->application_secret = getenv('APP_SECRET'); + $this->consumer_key = getenv('CONSUMER'); + $this->endpoint = getenv('ENDPOINT'); + $this->rangeIP = '127.0.0.20/32'; + $this->alternativeRangeIP = '127.0.0.30/32'; $this->client = new Client(); - $this->api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); - + $this->api = new Api( + $this->application_key, + $this->application_secret, + $this->endpoint, + $this->consumer_key, + $this->client + ); } /** * Get private and protected method to unit test it + * + * @param string $name + * + * @return \ReflectionMethod */ protected static function getPrivateMethod($name) { - $class = new \ReflectionClass('Ovh\Api'); + $class = new \ReflectionClass('Ovh\Api'); $method = $class->getMethod($name); $method->setAccessible(true); + return $method; } + /** + * Get private and protected property to unit test it + * + * @param string $name + * + * @return \ReflectionProperty + */ protected static function getPrivateProperty($name) { - $class = new \ReflectionClass('Ovh\Api'); + $class = new \ReflectionClass('Ovh\Api'); $property = $class->getProperty($name); $property->setAccessible(true); + return $property; } - /** - * Test if result contains consumerKey and validationUrl - */ - public function testIfConsumerKeyIsReplace() - { - $property = self::getPrivateProperty('consumer_key'); - $accessRules = json_decode(' [ + /** + * Test if result contains consumerKey and validationUrl + */ + public function testIfConsumerKeyIsReplace() + { + $property = self::getPrivateProperty('consumer_key'); + $accessRules = json_decode(' [ { "method": "GET", "path": "/*" }, { "method": "POST", "path": "/*" }, { "method": "PUT", "path": "/*" }, { "method": "DELETE", "path": "/*" } - ] ') ; - - $credentials = $this->api->requestCredentials($accessRules); - $consumer_key = $property->getValue($this->api); - - $this->assertEquals( $consumer_key , $credentials["consumerKey"]); - $this->assertNotEquals( $consumer_key, $this->consumer_key ); - } - - /** - * Test if put request on me - */ - public function testPutRestrictionAccessIp() - { - $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); - $invoker = self::getPrivateMethod('rawCall'); - $params = new \StdClass(); - $params->ip = $this->rangeIP; - $params->rule = "deny"; - $params->warning = true; - - $result = $invoker->invokeArgs($api, array('POST', '/me/accessRestriction/ip', $params)) ; - $this->assertNull( $result ); - } - - /** - * Test if get request on /me - */ - public function testGetRestrictionAccessIP() - { - $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); - $invoker = self::getPrivateMethod('rawCall'); - $result = $invoker->invokeArgs($api, array('GET', '/me/accessRestriction/ip')) ; - foreach ($result as $restrictionId) { - $restriction = $invoker->invokeArgs($api, array('GET', '/me/accessRestriction/ip/' . $restrictionId)) ; - - if ($restriction["ip"] == $this->rangeIP) { - $this->assertTrue(true); - break; - } - } - } - - /** - * Test if delete request on /me - */ - public function testDeleteRestrictionAccessIP() - { - $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); - $invoker = self::getPrivateMethod('rawCall'); - - $result = $invoker->invokeArgs($api, array('GET', '/me/accessRestriction/ip')) ; - foreach ($result as $restrictionId) { - $restriction = $invoker->invokeArgs($api, array('GET', '/me/accessRestriction/ip/' . $restrictionId)) ; - - if ($restriction["ip"] == $this->rangeIP) { - $result = $invoker->invokeArgs($api, array('DELETE', '/me/accessRestriction/ip/'. $restrictionId)) ; - $this->assertNull( $result ); - break; - } - } - } - - /** - * Test if request without authentication works - */ - public function testIfRequestWithoutAuthenticationWorks() - { - $api = new Api($this->application_key, $this->application_secret, $this->endpoint, NULL, $this->client); - $invoker = self::getPrivateMethod('rawCall'); - $result = $invoker->invokeArgs($api, array('GET', '/xdsl/incidents')) ; - } + ] '); -} + $credentials = $this->api->requestCredentials($accessRules); + $consumer_key = $property->getValue($this->api); + + $this->assertEquals($consumer_key, $credentials["consumerKey"]); + $this->assertNotEquals($consumer_key, $this->consumer_key); + } + /** + * Test if post request on me + */ + public function testPostRestrictionAccessIp() + { + $this->assertNull( + $this->api->post('/me/accessRestriction/ip', ['ip' => $this->rangeIP, 'rule' => 'deny', 'warning' => true]) + ); + + $this->assertNull( + $this->api->post('/me/accessRestriction/ip', ['ip' => $this->alternativeRangeIP, + 'rule' => 'deny', + 'warning' => true, + ]) + ); + } + + /** + * Test if get request on /me + */ + public function testGetRestrictionAccessIP() + { + $result = $this->api->get('/me/accessRestriction/ip'); + + $restrictionIps = []; + + foreach ($result as $restrictionId) { + $restriction = $this->api->get('/me/accessRestriction/ip/' . $restrictionId); + + $restrictionIps[] = $restriction['ip']; + } + + $this->assertContains($this->rangeIP, $restrictionIps); + $this->assertContains($this->alternativeRangeIP, $restrictionIps); + } + + /** + * Test if delete request on /me + */ + public function testPutRestrictionAccessIP() + { + $result = $this->api->get('/me/accessRestriction/ip'); + + $restrictionId = array_pop($result); + + $this->assertNull( + $this->api->put('/me/accessRestriction/ip/' . $restrictionId, ['rule' => 'accept', 'warning' => true]) + ); + + $restriction = $this->api->get('/me/accessRestriction/ip/' . $restrictionId); + $this->assertEquals('accept', $restriction['rule']); + } + + /** + * Test if delete request on /me + */ + public function testDeleteRestrictionAccessIP() + { + $result = $this->api->get('/me/accessRestriction/ip'); + foreach ($result as $restrictionId) { + $restriction = $this->api->get('/me/accessRestriction/ip/' . $restrictionId); + + if (in_array($restriction["ip"], [$this->rangeIP, $this->alternativeRangeIP])) { + $result = $this->api->delete('/me/accessRestriction/ip/' . $restrictionId); + $this->assertNull($result); + break; + } + } + } + + /** + * Test if request without authentication works + */ + public function testIfRequestWithoutAuthenticationWorks() + { + $api = new Api($this->application_key, $this->application_secret, $this->endpoint, null, $this->client); + $invoker = self::getPrivateMethod('rawCall'); + $invoker->invokeArgs($api, ['GET', '/xdsl/incidents']); + } + + /** + * Test Api::get + */ + public function testApiGetWithParameters() + { + $this->setExpectedException('\\GuzzleHttp\\Exception\\ClientException', '400'); + + $this->api->get('/me/accessRestriction/ip', ['foo' => 'bar']); + } +} diff --git a/tests/ApiTest.php b/tests/ApiTest.php index 4788124..6a4c8da 100644 --- a/tests/ApiTest.php +++ b/tests/ApiTest.php @@ -27,140 +27,259 @@ namespace Ovh\tests; -use Ovh\Api; - use GuzzleHttp\Client; -use GuzzleHttp\Subscriber\Mock; +use GuzzleHttp\Middleware; +use GuzzleHttp\Psr7\Response; +use Ovh\Api; /** * Test Api class * - * @package Ovh + * @package Ovh * @category Ovh - * @author Vincent Cassé + * @author Vincent Cassé + * @author Thierry Goettelmann */ -class ApiTest extends \PHPUnit_Framework_TestCase { +class ApiTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Client + */ + private $client; + + /** + * @var string + */ + private $application_key; + + /** + * @var string + */ + private $consumer_key; - /** - * Define id to create object - */ - protected function setUp() + /** + * @var string + */ + private $endpoint; + + /** + * @var string + */ + private $application_secret; + + /** + * Define id to create object + */ + protected function setUp() { - $this->application_key = 'app_key'; - $this->application_secret = 'app_secret'; - $this->consumer_key = 'consumer'; - $this->endpoint = 'ovh-eu'; + $this->application_key = 'app_key'; + $this->application_secret = 'app_secret'; + $this->consumer_key = 'consumer'; + $this->endpoint = 'ovh-eu'; $this->client = new Client(); } /** * Get private and protected method to unit test it + * + * @param string $name + * + * @return \ReflectionMethod */ protected static function getPrivateMethod($name) { - $class = new \ReflectionClass('Ovh\Api'); + $class = new \ReflectionClass('Ovh\Api'); $method = $class->getMethod($name); $method->setAccessible(true); + return $method; } + /** + * Get private and protected property to unit test it + * + * @param string $name + * + * @return \ReflectionProperty + */ protected static function getPrivateProperty($name) { - $class = new \ReflectionClass('Ovh\Api'); + $class = new \ReflectionClass('Ovh\Api'); $property = $class->getProperty($name); $property->setAccessible(true); + return $property; } - /** - * Test the compute of time delta - */ - public function testTimeDeltaCompute() - { - $delay = 10; - $mock = new Mock([ - "HTTP/1.1 200 OK\r\n\r\n". (time()-$delay), - ]); - $this->client->getEmitter()->attach($mock); - - $invoker = self::getPrivateMethod('calculateTimeDelta'); - $property = self::getPrivateProperty('time_delta'); - $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); - $invoker->invokeArgs($api, array()) ; - - $time_delta = $property->getValue($api); - $this->assertNotNull($time_delta); - $this->assertEquals($time_delta, $delay * -1 ); - } - - /** - * Test if consumer key is replaced - */ - public function testIfConsumerKeyIsReplace() - { - $delay = 10; - $mock = new Mock([ - "HTTP/1.1 200 OK\r\n\r\n". '{"validationUrl":"https://api.ovh.com/login/?credentialToken=token","consumerKey":"consumer_remote","state":"pendingValidation"}' - ]); - $this->client->getEmitter()->attach($mock); - - $property = self::getPrivateProperty('consumer_key'); - $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); - $accessRules = array( json_decode(' { "method": "GET", "path": "/*" } ') ); - - $credentials = $api->requestCredentials($accessRules); - $consumer_key = $property->getValue($api); - - $this->assertEquals( $consumer_key , $credentials["consumerKey"]); - $this->assertNotEquals( $consumer_key, $this->consumer_key ); - } - - /** - * Test invalid applicationKey - */ - public function testInvalidApplicationKey() - { - $this->setExpectedException( - '\GuzzleHttp\Exception\ClientException' + /** + * Test missing $application_key + */ + public function testMissingApplicationKey() + { + $this->setExpectedException('\\Ovh\\Exceptions\\InvalidParameterException', 'Application key'); + new Api(null, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); + } + + /** + * Test missing $application_secret + */ + public function testMissingApplicationSecret() + { + $this->setExpectedException('\\Ovh\\Exceptions\\InvalidParameterException', 'Application secret'); + new Api($this->application_key, null, $this->endpoint, $this->consumer_key, $this->client); + } + + /** + * Test missing $api_endpoint + */ + public function testMissingApiEndpoint() + { + $this->setExpectedException('\\Ovh\\Exceptions\\InvalidParameterException', 'Endpoint'); + new Api($this->application_key, $this->application_secret, null, $this->consumer_key, $this->client); + } + + /** + * Test bad $api_endpoint + */ + public function testBadApiEndpoint() + { + $this->setExpectedException('\\Ovh\\Exceptions\\InvalidParameterException', 'Unknown'); + new Api($this->application_key, $this->application_secret, 'i_am_invalid', $this->consumer_key, $this->client); + } + + /** + * Test creating Client if none is provided + */ + public function testClientCreation() + { + $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key); + + $this->assertInstanceOf('\\GuzzleHttp\\Client', $api->getHttpClient()); + } + + /** + * Test the compute of time delta + */ + public function testTimeDeltaCompute() + { + $delay = 10; + + $handlerStack = $this->client->getConfig('handler'); + $handlerStack->push(Middleware::mapResponse(function (Response $response) { + + $body = $response->getBody(); + $body->write(time() - 10); + + return $response + ->withStatus(200) + ->withBody($body); + })); + + $invoker = self::getPrivateMethod('calculateTimeDelta'); + $property = self::getPrivateProperty('time_delta'); + + $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); + $invoker->invokeArgs($api, []); + + $time_delta = $property->getValue($api); + $this->assertNotNull($time_delta); + $this->assertEquals($time_delta, $delay * -1); + } + + /** + * Test if consumer key is replaced + */ + public function testIfConsumerKeyIsReplace() + { + $handlerStack = $this->client->getConfig('handler'); + $handlerStack->push(Middleware::mapResponse(function (Response $response) { + + $body = $response->getBody(); + $body->write('{"validationUrl":"https://api.ovh.com/login/?credentialToken=token","consumerKey":"consumer_remote","state":"pendingValidation"}'); + + return $response + ->withStatus(200) + ->withBody($body); + })); + + $property = self::getPrivateProperty('consumer_key'); + + $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); + $accessRules = [json_decode(' { "method": "GET", "path": "/*" } ')]; + + $credentials = $api->requestCredentials($accessRules); + + $consumer_key = $property->getValue($api); + + $this->assertEquals($consumer_key, $credentials["consumerKey"]); + $this->assertNotEquals($consumer_key, $this->consumer_key); + } + + /** + * Test invalid applicationKey + */ + public function testInvalidApplicationKey() + { + $this->setExpectedException( + '\GuzzleHttp\Exception\ClientException' ); - $delay = 10; - $mock = new Mock([ - "HTTP/1.1 401 Unauthorized\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: 37\r\n\r\n{\"message\":\"Invalid application key\"}" - ]); - $this->client->getEmitter()->attach($mock); - - $property = self::getPrivateProperty('consumer_key'); - $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); - $accessRules = array( json_decode(' { "method": "GET", "path": "/*" } ') ); - - $credentials = $api->requestCredentials($accessRules); - $consumer_key = $property->getValue($api); - - $this->assertEquals( $consumer_key , $credentials["consumerKey"]); - $this->assertNotEquals( $consumer_key, $this->consumer_key ); - } - - /** - * Test invalid rights - */ - public function testInvalidRight() - { - $this->setExpectedException( - '\GuzzleHttp\Exception\ClientException' + $handlerStack = $this->client->getConfig('handler'); + $handlerStack->push(Middleware::mapResponse(function (Response $response) { + + $body = $response->getBody(); + $body->write('{\"message\":\"Invalid application key\"}'); + + return $response + ->withStatus(401, 'POUET') + ->withHeader('Content-Type', 'application/json; charset=utf-8') + ->withHeader('Content-Length', 37) + ->withBody($body); + })); + + $property = self::getPrivateProperty('consumer_key'); + $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); + $accessRules = [json_decode(' { "method": "GET", "path": "/*" } ')]; + + $credentials = $api->requestCredentials($accessRules); + $consumer_key = $property->getValue($api); + + $this->assertEquals($consumer_key, $credentials["consumerKey"]); + $this->assertNotEquals($consumer_key, $this->consumer_key); + } + + /** + * Test invalid rights + */ + public function testInvalidRight() + { + $this->setExpectedException( + '\GuzzleHttp\Exception\ClientException' ); - $delay = 10; - $mock = new Mock([ - "HTTP/1.1 403 Forbidden\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: 37\r\n\r\n{\"message\":\"Invalid credentials\"}" - ]); - $this->client->getEmitter()->attach($mock); + $handlerStack = $this->client->getConfig('handler'); + $handlerStack->push(Middleware::mapResponse(function (Response $response) { - $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); + $body = $response->getBody(); + $body->write('{\"message\":\"Invalid credentials\"}'); - $invoker = self::getPrivateMethod('rawCall'); - $invoker->invokeArgs($api, array('GET', '/me')) ; - } -} + return $response + ->withStatus(403) + ->withHeader('Content-Type', 'application/json; charset=utf-8') + ->withHeader('Content-Length', 37) + ->withBody($body); + })); + + $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); + $invoker = self::getPrivateMethod('rawCall'); + $invoker->invokeArgs($api, ['GET', '/me']); + } + + public function testGetConsumerKey() + { + $api = new Api($this->application_key, $this->application_secret, $this->endpoint, $this->consumer_key, $this->client); + $this->assertEquals($this->consumer_key, $api->getConsumerKey()); + } +} From f1047d23f9804f1ec103f27b7ed81b0ebcc26962 Mon Sep 17 00:00:00 2001 From: Thierry Goettelmann Date: Thu, 6 Aug 2015 15:31:29 +0200 Subject: [PATCH 3/7] Migrate to new Travis infrastructure Signed-off-by: Thierry Goettelmann --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 89eacd8..fc9d420 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +sudo: false language: php php: - hhvm From d54f99ac5e72c9311b2d9743dc8a309aaff7240e Mon Sep 17 00:00:00 2001 From: Thierry Goettelmann Date: Thu, 6 Aug 2015 15:34:43 +0200 Subject: [PATCH 4/7] Do a composer self-update before install. Remove deprecated --dev option Signed-off-by: Thierry Goettelmann --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fc9d420..2724a06 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ php: - 5.4 before_script: - - composer install --dev + - composer self-update + - composer install script: phpunit tests/ApiTest.php From 37b5f740ab857197934ca58e16cec8be70475864 Mon Sep 17 00:00:00 2001 From: Thierry Goettelmann Date: Thu, 6 Aug 2015 15:39:34 +0200 Subject: [PATCH 5/7] Remove Php 5.4 from travis since Guzzle 6.0 require Php >=5.5 Signed-off-by: Thierry Goettelmann --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2724a06..ad1846f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ php: - hhvm - 5.6 - 5.5 - - 5.4 before_script: - composer self-update From 9aa7df73bfee5bb776410d1b00f66114729785ad Mon Sep 17 00:00:00 2001 From: Vincent Casse Date: Thu, 17 Dec 2015 18:14:11 +0100 Subject: [PATCH 6/7] Fix timeout and guzzle 6 Fix copyrights Signed-off-by: Vincent Casse --- composer.json | 5 ----- src/Api.php | 11 +++++------ src/Exceptions/ApiException.php | 3 +-- src/Exceptions/InvalidParameterException.php | 3 +-- src/Exceptions/NotLoggedException.php | 3 +-- tests/ApiFunctionalTest.php | 4 +--- tests/ApiTest.php | 4 +--- 7 files changed, 10 insertions(+), 23 deletions(-) diff --git a/composer.json b/composer.json index 7ace00a..8edcdb1 100644 --- a/composer.json +++ b/composer.json @@ -5,11 +5,6 @@ "require": { "guzzlehttp/guzzle": "^6.0" }, - "authors": [ - { - "name": "Vincent Cassé" - } - ], "autoload": { "psr-4": {"Ovh\\": "src/"} }, diff --git a/src/Api.php b/src/Api.php index 6b4a5c6..9179113 100644 --- a/src/Api.php +++ b/src/Api.php @@ -1,5 +1,5 @@ - * @author Thierry Goettelmann */ class Api { @@ -144,9 +142,10 @@ public function __construct( } if (!isset($http_client)) { - $http_client = new Client(); - $http_client->setDefaultOption('timeout', 30); - $http_client->setDefaultOption('connect_timeout', 5); + $http_client = new Client([ + 'timeout' => 30, + 'connect_timeout' => 5, + ]); } $this->application_key = $application_key; diff --git a/src/Exceptions/ApiException.php b/src/Exceptions/ApiException.php index 5b902bc..7411528 100644 --- a/src/Exceptions/ApiException.php +++ b/src/Exceptions/ApiException.php @@ -1,5 +1,5 @@ */ class ApiException extends Exception { diff --git a/src/Exceptions/InvalidParameterException.php b/src/Exceptions/InvalidParameterException.php index 97f0322..7b10bdf 100644 --- a/src/Exceptions/InvalidParameterException.php +++ b/src/Exceptions/InvalidParameterException.php @@ -1,5 +1,5 @@ */ class InvalidParameterException extends Exception { diff --git a/src/Exceptions/NotLoggedException.php b/src/Exceptions/NotLoggedException.php index f8a2908..6107a9a 100644 --- a/src/Exceptions/NotLoggedException.php +++ b/src/Exceptions/NotLoggedException.php @@ -1,5 +1,5 @@ */ class NotLoggedException extends Exception { diff --git a/tests/ApiFunctionalTest.php b/tests/ApiFunctionalTest.php index 61ddb02..651dd8c 100644 --- a/tests/ApiFunctionalTest.php +++ b/tests/ApiFunctionalTest.php @@ -1,5 +1,5 @@ - * @author Thierry Goettelmann */ class ApiFunctionalTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/ApiTest.php b/tests/ApiTest.php index 6a4c8da..a1375bc 100644 --- a/tests/ApiTest.php +++ b/tests/ApiTest.php @@ -1,5 +1,5 @@ - * @author Thierry Goettelmann */ class ApiTest extends \PHPUnit_Framework_TestCase { From cc0ba042ca3c6ddd27cea9ac0fd083cc92a6a77f Mon Sep 17 00:00:00 2001 From: Vincent Casse Date: Thu, 17 Dec 2015 18:38:51 +0100 Subject: [PATCH 7/7] Fix tls issue into travis Signed-off-by: Vincent Casse --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f67a6af..c22c542 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,8 @@ -sudo: false +addons: + apt: + packages: + - libcurl4-openssl-dev + language: php php: - hhvm