From 10b0edd23c8133cd2799a6ee7bb50750419887f0 Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko Date: Tue, 20 Sep 2022 23:42:06 +0300 Subject: [PATCH] added other security types --- src/Generator.php | 2 +- src/Support/Generator/SecurityScheme.php | 46 +++++++++++------- .../SecuritySchemes/ApiKeySecurityScheme.php | 28 +++++++++++ .../SecuritySchemes/HttpSecurityScheme.php | 28 +++++++++++ .../Generator/SecuritySchemes/OAuthFlow.php | 47 ++++++++++++++++++ .../Generator/SecuritySchemes/OAuthFlows.php | 48 +++++++++++++++++++ .../SecuritySchemes/Oauth2SecurityScheme.php | 41 ++++++++++++++++ .../OpenIdConnectUrlSecurityScheme.php | 24 ++++++++++ tests/OpenApiBuildersTest.php | 20 ++++++++ ...t__it_builds_oauth2_security_scheme__1.yml | 8 ++++ 10 files changed, 275 insertions(+), 17 deletions(-) create mode 100644 src/Support/Generator/SecuritySchemes/ApiKeySecurityScheme.php create mode 100644 src/Support/Generator/SecuritySchemes/HttpSecurityScheme.php create mode 100644 src/Support/Generator/SecuritySchemes/OAuthFlow.php create mode 100644 src/Support/Generator/SecuritySchemes/OAuthFlows.php create mode 100644 src/Support/Generator/SecuritySchemes/Oauth2SecurityScheme.php create mode 100644 src/Support/Generator/SecuritySchemes/OpenIdConnectUrlSecurityScheme.php create mode 100644 tests/__snapshots__/OpenApiBuildersTest__it_builds_oauth2_security_scheme__1.yml diff --git a/src/Generator.php b/src/Generator.php index 12907acb..17968059 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -40,7 +40,7 @@ public function __invoke() ->toArray(); if (isset(Scramble::$openApiExtender)) { - $openApi = (Scramble::$openApiExtender)($openApi); + (Scramble::$openApiExtender)($openApi); } return $openApi->toArray(); diff --git a/src/Support/Generator/SecurityScheme.php b/src/Support/Generator/SecurityScheme.php index 80162cef..2c88b044 100644 --- a/src/Support/Generator/SecurityScheme.php +++ b/src/Support/Generator/SecurityScheme.php @@ -2,50 +2,66 @@ namespace Dedoc\Scramble\Support\Generator; +use Dedoc\Scramble\Support\Generator\SecuritySchemes\ApiKeySecurityScheme; +use Dedoc\Scramble\Support\Generator\SecuritySchemes\HttpSecurityScheme; +use Dedoc\Scramble\Support\Generator\SecuritySchemes\Oauth2SecurityScheme; +use Dedoc\Scramble\Support\Generator\SecuritySchemes\OpenIdConnectUrlSecurityScheme; + class SecurityScheme { public string $type; - public string $name; - - public string $in; - public string $description = ''; public string $schemeName = 'scheme'; - public bool $isDefault = false; + public bool $default = false; - private function __construct(string $type) + public function __construct(string $type) { $this->type = $type; } public static function apiKey(string $in, string $name) { - $scheme = new self('apiKey'); - $scheme->schemeName = 'apiKey'; - $scheme->in = $in; - $scheme->name = $name; + return (new ApiKeySecurityScheme($in, $name))->as('apiKey'); + } + + public static function http(string $scheme, string $bearerFormat = '') + { + return (new HttpSecurityScheme($scheme, $bearerFormat))->as('http'); + } + + public static function oauth2() + { + return (new Oauth2SecurityScheme)->as('oauth2'); + } - return $scheme; + public static function openIdConnect(string $openIdConnectUrl) + { + return (new OpenIdConnectUrlSecurityScheme($openIdConnectUrl))->as('openIdConnect'); + } + + public static function mutualTLS() + { + return (new static('mutualTLS'))->as('mutualTLS'); } - public function as(string $schemeName): SecurityScheme + public function as(string $schemeName): self { $this->schemeName = $schemeName; return $this; } - public function setDescription(string $description): SecurityScheme + public function setDescription(string $description): self { $this->description = $description; return $this; } - public function default(): SecurityScheme + public function default(): self { $this->default = true; @@ -56,8 +72,6 @@ public function toArray() { return array_filter([ 'type' => $this->type, - 'in' => $this->in, - 'name' => $this->name, 'description' => $this->description, ]); } diff --git a/src/Support/Generator/SecuritySchemes/ApiKeySecurityScheme.php b/src/Support/Generator/SecuritySchemes/ApiKeySecurityScheme.php new file mode 100644 index 00000000..49069c26 --- /dev/null +++ b/src/Support/Generator/SecuritySchemes/ApiKeySecurityScheme.php @@ -0,0 +1,28 @@ +in = $in; + $this->name = $name; + } + + public function toArray() + { + return array_merge(parent::toArray(), [ + 'in' => $this->in, + 'name' => $this->name, + ]); + } +} diff --git a/src/Support/Generator/SecuritySchemes/HttpSecurityScheme.php b/src/Support/Generator/SecuritySchemes/HttpSecurityScheme.php new file mode 100644 index 00000000..b81a3c97 --- /dev/null +++ b/src/Support/Generator/SecuritySchemes/HttpSecurityScheme.php @@ -0,0 +1,28 @@ +scheme = $scheme; + $this->bearerFormat = $bearerFormat; + } + + public function toArray() + { + return array_merge(parent::toArray(), [ + 'scheme' => $this->scheme, + 'bearerFormat' => $this->bearerFormat, + ]); + } +} diff --git a/src/Support/Generator/SecuritySchemes/OAuthFlow.php b/src/Support/Generator/SecuritySchemes/OAuthFlow.php new file mode 100644 index 00000000..856e814c --- /dev/null +++ b/src/Support/Generator/SecuritySchemes/OAuthFlow.php @@ -0,0 +1,47 @@ + */ + public array $scopes = []; + + public function authorizationUrl(string $authorizationUrl): OAuthFlow + { + $this->authorizationUrl = $authorizationUrl; + return $this; + } + + public function tokenUrl(string $tokenUrl): OAuthFlow + { + $this->tokenUrl = $tokenUrl; + return $this; + } + + public function refreshUrl(string $refreshUrl): OAuthFlow + { + $this->refreshUrl = $refreshUrl; + return $this; + } + + public function addScope(string $name, string $description = '') + { + $this->scopes[$name] = $description; + + return $this; + } + + public function toArray() + { + return array_filter([ + 'authorizationUrl' => $this->authorizationUrl, + 'tokenUrl' => $this->tokenUrl, + 'refreshUrl' => $this->refreshUrl, + 'scopes' => $this->scopes, + ]); + } +} diff --git a/src/Support/Generator/SecuritySchemes/OAuthFlows.php b/src/Support/Generator/SecuritySchemes/OAuthFlows.php new file mode 100644 index 00000000..3ace27b6 --- /dev/null +++ b/src/Support/Generator/SecuritySchemes/OAuthFlows.php @@ -0,0 +1,48 @@ +implicit = $flow; + return $this; + } + + public function password(?OAuthFlow $flow): OAuthFlows + { + $this->password = $flow; + return $this; + } + + public function clientCredentials(?OAuthFlow $flow): OAuthFlows + { + $this->clientCredentials = $flow; + return $this; + } + + public function authorizationCode(?OAuthFlow $flow): OAuthFlows + { + $this->authorizationCode = $flow; + return $this; + } + + public function toArray() + { + return array_map( + fn ($f) => $f->toArray(), + array_filter([ + 'implicit' => $this->implicit, + 'password' => $this->password, + 'clientCredentials' => $this->clientCredentials, + 'authorizationCode' => $this->authorizationCode, + ]) + ); + } +} diff --git a/src/Support/Generator/SecuritySchemes/Oauth2SecurityScheme.php b/src/Support/Generator/SecuritySchemes/Oauth2SecurityScheme.php new file mode 100644 index 00000000..23e50474 --- /dev/null +++ b/src/Support/Generator/SecuritySchemes/Oauth2SecurityScheme.php @@ -0,0 +1,41 @@ +oAuthFlows = new OAuthFlows; + } + + public function flows(callable $flows) + { + $flows($this->oAuthFlows); + + return $this; + } + + public function flow(string $name, callable $flow) + { + return $this->flows(function (OAuthFlows $flows) use ($flow, $name) { + if (! $flows->$name) { + $flows->$name(new OAuthFlow); + } + $flow($flows->$name); + }); + } + + public function toArray() + { + return array_merge(parent::toArray(), [ + 'flows' => $this->oAuthFlows->toArray(), + ]); + } +} diff --git a/src/Support/Generator/SecuritySchemes/OpenIdConnectUrlSecurityScheme.php b/src/Support/Generator/SecuritySchemes/OpenIdConnectUrlSecurityScheme.php new file mode 100644 index 00000000..b8c238eb --- /dev/null +++ b/src/Support/Generator/SecuritySchemes/OpenIdConnectUrlSecurityScheme.php @@ -0,0 +1,24 @@ +openIdConnectUrl = $openIdConnectUrl; + } + + public function toArray() + { + return array_merge(parent::toArray(), [ + 'openIdConnectUrl' => $this->openIdConnectUrl, + ]); + } +} diff --git a/tests/OpenApiBuildersTest.php b/tests/OpenApiBuildersTest.php index c8460990..f7a7a920 100644 --- a/tests/OpenApiBuildersTest.php +++ b/tests/OpenApiBuildersTest.php @@ -3,6 +3,8 @@ use Dedoc\Scramble\Support\Generator\InfoObject; use Dedoc\Scramble\Support\Generator\OpenApi; use Dedoc\Scramble\Support\Generator\SecurityScheme; +use Dedoc\Scramble\Support\Generator\SecuritySchemes\OAuthFlow; +use function Spatie\Snapshots\assertMatchesSnapshot; it('builds security scheme', function () { $openApi = (new OpenApi('3.1.0')) @@ -20,3 +22,21 @@ ] ]); }); + +it('builds oauth2 security scheme', function () { + $openApi = (new OpenApi('3.1.0')) + ->setInfo(InfoObject::make('API')->setVersion('0.0.1')); + + $openApi->secure( + SecurityScheme::oauth2() + ->flow('implicit', function (OAuthFlow $flow) { + $flow + ->refreshUrl('https://test.com') + ->tokenUrl('https://test.com/token') + ->addScope('wow', 'nice'); + }) + ->default() + ); + + assertMatchesSnapshot($openApi->toArray()); +}); diff --git a/tests/__snapshots__/OpenApiBuildersTest__it_builds_oauth2_security_scheme__1.yml b/tests/__snapshots__/OpenApiBuildersTest__it_builds_oauth2_security_scheme__1.yml new file mode 100644 index 00000000..23a4c6ca --- /dev/null +++ b/tests/__snapshots__/OpenApiBuildersTest__it_builds_oauth2_security_scheme__1.yml @@ -0,0 +1,8 @@ +openapi: 3.1.0 +info: + title: API + version: 0.0.1 +security: + - { oauth2: { } } +components: + securitySchemes: { oauth2: { type: oauth2, flows: { implicit: { tokenUrl: 'https://test.com/token', refreshUrl: 'https://test.com', scopes: { wow: nice } } } } }