From 18569d423160bdf9304b22132458dd69ce19afaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fuzhan=20Durgun?= Date: Tue, 12 Dec 2023 17:29:47 +0300 Subject: [PATCH] enhancement: Metadata (headers) support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Oğuzhan Durgun --- src/Sdk/Builder/CerbosClientBuilder.php | 26 +++++++++++- src/Sdk/CerbosClient.php | 30 +++++--------- src/Sdk/Utility/Metadata.php | 53 +++++++++++++++++++++++++ tests/CerbosClientTest.php | 14 +++---- tests/TestCase.php | 12 ++++-- 5 files changed, 105 insertions(+), 30 deletions(-) create mode 100644 src/Sdk/Utility/Metadata.php diff --git a/src/Sdk/Builder/CerbosClientBuilder.php b/src/Sdk/Builder/CerbosClientBuilder.php index 227da70..bf705be 100644 --- a/src/Sdk/Builder/CerbosClientBuilder.php +++ b/src/Sdk/Builder/CerbosClientBuilder.php @@ -8,10 +8,13 @@ namespace Cerbos\Sdk\Builder; use Cerbos\Sdk\CerbosClient; +use Cerbos\Sdk\Utility\Metadata; use Cerbos\Svc\V1\CerbosServiceClient; use Exception; use Grpc\ChannelCredentials; +const playgroundInstanceHeader = "playground-instance"; + class CerbosClientBuilder { private string $hostname; @@ -20,6 +23,7 @@ class CerbosClientBuilder private ?string $caCertificate; private ?string $tlsCertificate; private ?string $tlsKey; + private ?array $metadata; /** * @param string $hostname @@ -31,6 +35,7 @@ private function __construct(string $hostname) { $this->caCertificate = null; $this->tlsCertificate = null; $this->tlsKey = null; + $this->metadata = null; } /** @@ -41,6 +46,15 @@ public static function newInstance(string $hostname): CerbosClientBuilder { return new CerbosClientBuilder($hostname); } + /** + * @param array $headers + * @return CerbosClientBuilder + */ + public function withMetadata(array $headers): CerbosClientBuilder { + $this->metadata = $headers; + return $this; + } + /** * @param bool $plaintext * @return CerbosClientBuilder @@ -126,6 +140,16 @@ public function build(): CerbosClient { ] ); - return new CerbosClient($csc, $this->playgroundInstanceId); + $combined = $this->metadata; + if ($this->playgroundInstanceId != "") { + $combined = Metadata::merge( + $this->metadata, + [ + playgroundInstanceHeader => [ $this->playgroundInstanceId ] + ] + ); + } + + return new CerbosClient($csc, $combined); } } diff --git a/src/Sdk/CerbosClient.php b/src/Sdk/CerbosClient.php index 3ae3d20..e05246f 100644 --- a/src/Sdk/CerbosClient.php +++ b/src/Sdk/CerbosClient.php @@ -11,32 +11,32 @@ use Cerbos\Sdk\Builder\PlanResourcesRequest; use Cerbos\Sdk\Response\V1\CheckResourcesResponse\CheckResourcesResponse; use Cerbos\Sdk\Response\V1\PlanResourcesResponse\PlanResourcesResponse; +use Cerbos\Sdk\Utility\Metadata; use Cerbos\Svc\V1\CerbosServiceClient; use Exception; class CerbosClient { private CerbosServiceClient $csc; - - private string $playgroundInstanceId; - private string $playgroundInstanceHeader = "playground-instance"; + private ?array $metadata; /** * @param CerbosServiceClient $csc - * @param string $playgroundInstanceId + * @param array $headers */ - public function __construct(CerbosServiceClient $csc, string $playgroundInstanceId) { + public function __construct(CerbosServiceClient $csc, $headers = null) { $this->csc = $csc; - $this->playgroundInstanceId = $playgroundInstanceId; + $this->metadata = $headers; } /** * @param CheckResourcesRequest $request + * @param array $headers * @return CheckResourcesResponse * @throws Exception */ - public function checkResources(CheckResourcesRequest $request): CheckResourcesResponse { - list($checkResourcesResponse, $status) = $this->csc->CheckResources($request->toCheckResourcesRequest(), $this->getMetadata())->wait(); + public function checkResources(CheckResourcesRequest $request, $headers = null): CheckResourcesResponse { + list($checkResourcesResponse, $status) = $this->csc->CheckResources($request->toCheckResourcesRequest(), Metadata::merge($this->metadata, $headers))->wait(); $this->handleError($status); return new CheckResourcesResponse($checkResourcesResponse); @@ -44,25 +44,17 @@ public function checkResources(CheckResourcesRequest $request): CheckResourcesRe /** * @param PlanResourcesRequest $request + * @param array $headers * @return PlanResourcesResponse * @throws Exception */ - public function planResources(PlanResourcesRequest $request): PlanResourcesResponse { - list($planResourcesResponse, $status) = $this->csc->PlanResources($request->toPlanResourcesRequest(), $this->getMetadata())->wait(); + public function planResources(PlanResourcesRequest $request, $headers = null): PlanResourcesResponse { + list($planResourcesResponse, $status) = $this->csc->PlanResources($request->toPlanResourcesRequest(), Metadata::merge($this->metadata, $headers))->wait(); $this->handleError($status); return new PlanResourcesResponse($planResourcesResponse); } - /** - * @return array - */ - private function getMetadata(): array { - return array( - $this->playgroundInstanceHeader => [$this->playgroundInstanceId] - ); - } - /** * @param object $status * @throws Exception diff --git a/src/Sdk/Utility/Metadata.php b/src/Sdk/Utility/Metadata.php new file mode 100644 index 0000000..e235ce9 --- /dev/null +++ b/src/Sdk/Utility/Metadata.php @@ -0,0 +1,53 @@ + + * @throws Exception + */ + public static function merge(?array $first, ?array $second): array { + if (is_null($first) && is_null($second)) + return []; + else if (is_null($first) && !is_null($second)) + return $second; + else if (is_null($second)) + return $first; + + $combined = array(); + foreach ($first as $k => $v) { + if (is_array($v)) { + foreach ($v as $i => $vv) { + $combined[$k][] = $vv; + } + } + else { + throw new Exception("the type for the parameter first and second parameter is array|null"); + } + } + + foreach ($second as $k => $v) { + if (is_array($v)) { + foreach ($v as $i => $vv) { + $combined[$k][] = $vv; + } + } + else { + throw new Exception("the type for the parameter first and second parameter is array|null"); + } + } + + return $combined; + } +} diff --git a/tests/CerbosClientTest.php b/tests/CerbosClientTest.php index 82c741a..83ead2d 100644 --- a/tests/CerbosClientTest.php +++ b/tests/CerbosClientTest.php @@ -47,7 +47,7 @@ public function testCheckWithoutJwt(): void ); try { - $checkResourcesResult = $this->client->checkResources($request); + $checkResourcesResult = $this->client->checkResources($request, $this->metadata); $resultEntry = $checkResourcesResult->find("XX125"); } catch (Exception $e) { $this->fail($e->getMessage()); @@ -83,7 +83,7 @@ public function testCheckWithJwt(): void { ); try { - $checkResourcesResult = $this->client->checkResources($request); + $checkResourcesResult = $this->client->checkResources($request, $this->metadata); $resultEntry = $checkResourcesResult->find("XX125"); } catch (Exception $e) { $this->fail($e->getMessage()); @@ -137,7 +137,7 @@ public function testCheckMultiple(): void { ); try { - $checkResourcesResult = $this->client->checkResources($request); + $checkResourcesResult = $this->client->checkResources($request, $this->metadata); $resultEntryXX125 = $checkResourcesResult->find("XX125"); $resultEntryXX225 = $checkResourcesResult->find("XX225"); $resultEntryXX325 = $checkResourcesResult->find("XX325"); @@ -177,7 +177,7 @@ public function testValidationErrors(): void ); try { - $checkResourcesResult = $this->client->checkResources($request); + $checkResourcesResult = $this->client->checkResources($request, $this->metadata); $resultEntry = $checkResourcesResult->find("XX125"); } catch (Exception $e) { $this->fail($e->getMessage()); @@ -208,7 +208,7 @@ public function testPlanResources(): void{ try { - $planResourcesResult = $this->client->planResources($request); + $planResourcesResult = $this->client->planResources($request, $this->metadata); } catch (Exception $e) { $this->fail($e->getMessage()); } @@ -256,7 +256,7 @@ public function testPlanResourcesValidation(): void{ ->withAction("approve"); try { - $planResourcesResult = $this->client->planResources($request); + $planResourcesResult = $this->client->planResources($request, $this->metadata); } catch (Exception $e) { $this->fail($e->getMessage()); } @@ -294,7 +294,7 @@ public function testPlayground(): void { ); try { - $checkResourcesResult = $this->playgroundClient->checkResources($request); + $checkResourcesResult = $this->playgroundClient->checkResources($request, $this->metadata); $resultEntry = $checkResourcesResult->find("XX125"); } catch (Exception $e) { $this->fail($e->getMessage()); diff --git a/tests/TestCase.php b/tests/TestCase.php index c33709f..8103036 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -16,6 +16,7 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase private string $host = 'localhost:3593'; private string $playgroundHost = 'demo-pdp.cerbos.cloud'; private string $playgroundInstanceId = 'XhkOi82fFKk3YW60e2c806Yvm0trKEje'; // See: https://play.cerbos.dev/p/XhkOi82fFKk3YW60e2c806Yvm0trKEje + protected array $metadata = ["wibble" => ["wobble"]]; protected CerbosClient $client; protected CerbosClient $playgroundClient; @@ -26,8 +27,13 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase protected function setUp(): void { parent::setUp(); - - $this->client = CerbosClientBuilder::newInstance($this->host)->withPlaintext(true)->build(); - $this->playgroundClient = CerbosClientBuilder::newInstance($this->playgroundHost)->withPlayground($this->playgroundInstanceId)->build(); + $this->client = CerbosClientBuilder::newInstance($this->host) + ->withMetadata($this->metadata) + ->withPlaintext(true) + ->build(); + $this->playgroundClient = CerbosClientBuilder::newInstance($this->playgroundHost) + ->withMetadata($this->metadata) + ->withPlayground($this->playgroundInstanceId) + ->build(); } }