diff --git a/src/Core/ServiceBuilder.php b/src/Core/ServiceBuilder.php index 83a8a56aa94..e4ce6a2a57c 100644 --- a/src/Core/ServiceBuilder.php +++ b/src/Core/ServiceBuilder.php @@ -54,7 +54,7 @@ class ServiceBuilder /** * @var array Configuration options to be used between clients. */ - private $config; + private $config = []; /** * Pass in an array of configuration options which will be shared between @@ -396,10 +396,17 @@ public function translate(array $config = []) return $this->createClient(TranslateClient::class, 'translate', $config); } + /** + * Create the client library, or error if not installed. + * + * @param string $class The class to create. + * @param string $packageName The name of the package + * @param array $config Configuration options. + */ private function createClient($class, $packageName, array $config = []) { if (class_exists($class)) { - return new $class($config ? $this->resolveConfig($config) : $this->config); + return new $class($this->resolveConfig($config)); } throw new \Exception(sprintf( 'The google/cloud-%s package is missing and must be installed.', @@ -419,6 +426,6 @@ private function resolveConfig(array $config) $config['httpHandler'] = HttpHandlerFactory::build(); } - return $config; + return array_merge($this->config, $config); } } diff --git a/tests/unit/Core/ServiceBuilderTest.php b/tests/unit/Core/ServiceBuilderTest.php index 9e37e544df5..a6528293859 100644 --- a/tests/unit/Core/ServiceBuilderTest.php +++ b/tests/unit/Core/ServiceBuilderTest.php @@ -29,7 +29,9 @@ use Google\Cloud\Tests\GrpcTestTrait; use Google\Cloud\Translate\TranslateClient; use Google\Cloud\Vision\VisionClient; +use GuzzleHttp\Psr7\Response; use PHPUnit\Framework\TestCase; +use Psr\Http\Message\RequestInterface; /** * @group servicebuilder @@ -44,8 +46,7 @@ class ServiceBuilderTest extends TestCase */ public function testBuildsClients($serviceName, $expectedClient, array $args = [], callable $beforeCallable = null) { - if ($beforeCallable) - { + if ($beforeCallable) { call_user_func($beforeCallable); } @@ -56,14 +57,14 @@ public function testBuildsClients($serviceName, $expectedClient, array $args = [ 'httpHandler' => function() { return; } - ] + $args; + ] + $args; $localConfigClient = $serviceBuilder->$serviceName($config); $this->assertInstanceOf($expectedClient, $localConfigClient); } - public function testBuildsTranslateClient() + public function testTranslateClientWithApiKey() { $config = ['key' => 'test_key']; $serviceBuilder = new ServiceBuilder($config); @@ -72,6 +73,77 @@ public function testBuildsTranslateClient() $this->assertInstanceOf(TranslateClient::class, $serviceBuilder->translate($config)); } + /** + * @dataProvider serviceProvider + */ + public function testKeyfilePathAuthPassthrough( + $serviceName, + $expectedClient, + array $args = [], + callable $beforeCallable = null + ) { + if ($beforeCallable) { + call_user_func($beforeCallable); + } + + $kfPath = __DIR__ .'/../fixtures/json-key-fixture.json'; + $kf = json_decode(file_get_contents($kfPath), true); + + $adc = getenv('GOOGLE_APPLICATION_CREDENTIALS'); + putenv('GOOGLE_APPLICATION_CREDENTIALS='); + + $serviceBuilder = new ServiceBuilder([ + 'keyFilePath' => $kfPath + ]); + + $client = $serviceBuilder->$serviceName($args); + + $ref = new \ReflectionClass($client); + $prop = $ref->getProperty('connection'); + $prop->setAccessible(true); + $conn = $prop->getValue($client); + $conn->requestWrapper() + ->getCredentialsFetcher() + ->fetchAuthToken($this->stub($kf)); + + putenv('GOOGLE_APPLICATION_CREDENTIALS='. $adc); + } + + /** + * @dataProvider serviceProvider + */ + public function testKeyfileAuthPassthrough( + $serviceName, $expectedClient, + array $args = [], + callable $beforeCallable = null + ) { + if ($beforeCallable) { + call_user_func($beforeCallable); + } + + $kfPath = __DIR__ .'/../fixtures/json-key-fixture.json'; + $kf = json_decode(file_get_contents($kfPath), true); + + $adc = getenv('GOOGLE_APPLICATION_CREDENTIALS'); + putenv('GOOGLE_APPLICATION_CREDENTIALS='); + + $serviceBuilder = new ServiceBuilder([ + 'keyFile' => $kf + ]); + + $client = $serviceBuilder->$serviceName($args); + + $ref = new \ReflectionClass($client); + $prop = $ref->getProperty('connection'); + $prop->setAccessible(true); + $conn = $prop->getValue($client); + $conn->requestWrapper() + ->getCredentialsFetcher() + ->fetchAuthToken($this->stub($kf)); + + putenv('GOOGLE_APPLICATION_CREDENTIALS='. $adc); + } + public function serviceProvider() { return [ @@ -107,6 +179,9 @@ public function serviceProvider() ], [ 'storage', StorageClient::class + ], [ + 'translate', + TranslateClient::class ], [ 'vision', VisionClient::class @@ -114,4 +189,23 @@ public function serviceProvider() ]; } + public function stub($kf) + { + return function (RequestInterface $request) use ($kf) { + parse_str((string)$request->getBody(), $result); + + $exp = [ + 'grant_type' => 'refresh_token', + 'refresh_token' => $kf['refresh_token'], + 'client_id' => $kf['client_id'], + 'client_secret' => $kf['client_secret'] + ]; + + $this->assertEquals($result, $exp); + + return new Response(200, [], json_encode([ + 'access_token' => 'foo' + ])); + }; + } } diff --git a/tests/unit/fixtures/json-key-fixture.json b/tests/unit/fixtures/json-key-fixture.json index 032cca3a887..a23a62427ca 100644 --- a/tests/unit/fixtures/json-key-fixture.json +++ b/tests/unit/fixtures/json-key-fixture.json @@ -1 +1,7 @@ -{"type":"authorized_user","client_id":"example@example.com","client_secret":"example","refresh_token":"abc","project_id":"example_project"} +{ + "type": "authorized_user", + "client_id": "example@example.com", + "client_secret": "example", + "refresh_token": "abc", + "project_id": "example_project" +}