Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions config/request-docs.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,16 @@
],
],
],
//openapi export with security configuration,
// if type set null then doc will exclude global security schema.
// Ref: https://spec.openapis.org/oas/v3.0.3#security-scheme-object
'security' => [
//available options [null, bearer, basic, apikey, jwt]
'type' => 'bearer',
'name' => 'api_key',
//Note: only works for "apikey" & "jwt", available options [query, header, cookie]
'position' => 'header',
],
],

//export request docs as json file from terminal
Expand Down
98 changes: 81 additions & 17 deletions src/LaravelRequestDocsToOpenApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class LaravelRequestDocsToOpenApi
private array $openApi = [];

/**
* @param \Rakutentech\LaravelRequestDocs\Doc[] $docs
* @param \Rakutentech\LaravelRequestDocs\Doc[] $docs
* @return $this
*/
public function openApi(array $docs): LaravelRequestDocsToOpenApi
Expand All @@ -23,18 +23,19 @@ public function openApi(array $docs): LaravelRequestDocsToOpenApi
];

$this->docsToOpenApi($docs);
$this->appendGlobalSecurityScheme();
return $this;
}

/**
* @param \Rakutentech\LaravelRequestDocs\Doc[] $docs
* @param \Rakutentech\LaravelRequestDocs\Doc[] $docs
* @return void
*/
private function docsToOpenApi(array $docs): void
{
$this->openApi['paths'] = [];
$deleteWithBody = config('request-docs.open_api.delete_with_body', false);
$excludeHttpMethods = array_map(fn ($item) => strtolower($item), config('request-docs.open_api.exclude_http_methods', []));
$excludeHttpMethods = array_map(fn($item) => strtolower($item), config('request-docs.open_api.exclude_http_methods', []));

foreach ($docs as $doc) {
$httpMethod = strtolower($doc->getHttpMethod());
Expand Down Expand Up @@ -90,6 +91,7 @@ private function docsToOpenApi(array $docs): void
}
}
}

protected function setAndFilterResponses(Doc $doc): array
{
$docResponses = $doc->getResponses();
Expand All @@ -115,12 +117,12 @@ protected function makeQueryParameterItem(string $attribute, $rule): array
$rule = implode('|', $rule);
}
$parameter = [
'name' => $attribute,
'name' => $attribute,
'description' => $rule,
'in' => 'query',
'style' => 'form',
'required' => str_contains($rule, 'required'),
'schema' => [
'in' => 'query',
'style' => 'form',
'required' => str_contains($rule, 'required'),
'schema' => [
'type' => $this->getAttributeType($rule),
],
];
Expand All @@ -134,12 +136,12 @@ protected function makePathParameterItem(string $attribute, $rule): array
}

$parameter = [
'name' => $attribute,
'name' => $attribute,
'description' => $rule,
'in' => 'path',
'style' => 'simple',
'required' => str_contains($rule, 'required'),
'schema' => [
'in' => 'path',
'style' => 'simple',
'required' => str_contains($rule, 'required'),
'schema' => [
'type' => $this->getAttributeType($rule),
],
];
Expand All @@ -150,10 +152,10 @@ protected function makeRequestBodyItem(string $contentType): array
{
$requestBody = [
'description' => "Request body",
'content' => [
'content' => [
$contentType => [
'schema' => [
'type' => 'object',
'type' => 'object',
'properties' => [],
],
],
Expand All @@ -167,9 +169,9 @@ protected function makeRequestBodyContentPropertyItem(string $rule): array
$type = $this->getAttributeType($rule);

return [
'type' => $type,
'type' => $type,
'nullable' => str_contains($rule, 'nullable'),
'format' => $this->attributeIsFile($rule) ? 'binary' : $type,
'format' => $this->attributeIsFile($rule) ? 'binary' : $type,
];
}

Expand All @@ -190,6 +192,68 @@ protected function getAttributeType(string $rule): string
return "object";
}

protected function appendGlobalSecurityScheme(): void
{
$securityType = config('request-docs.open_api.security.type');

if ($securityType == null) {
return;
}

switch ($securityType) {
case 'bearer':
$this->openApi['components']['securitySchemes']['bearerAuth'] = [
'type' => 'http',
'name' => config('request-docs.open_api.security.name', 'Bearer Token'),
'description' => 'Http Bearer Authorization Token',
'scheme' => 'bearer'
];
$this->openApi['security'][] = [
'bearerAuth' => []
];
break;

case 'basic':
$this->openApi['components']['securitySchemes']['basicAuth'] = [
'type' => 'http',
'name' => config('request-docs.open_api.security.name', 'Basic Username and Password'),
'description' => 'Http Basic Authorization Username and Password',
'scheme' => 'basic'
];
$this->openApi['security'][] = [
'basicAuth' => []
];
break;

case 'apikey':
$this->openApi['components']['securitySchemes']['apiKeyAuth'] = [
'type' => 'apiKey',
'name' => config('request-docs.open_api.security.name', 'api_key'),
'in' => config('request-docs.open_api.security.position', 'header'),
'description' => config('app.name').' Provided Authorization Api Key',
];
$this->openApi['security'][] = ['apiKeyAuth' => []];
break;

case 'jwt':
$this->openApi['components']['securitySchemes']['bearerAuth'] = [
'type' => 'http',
'scheme' => 'bearer',
'name' => config('request-docs.open_api.security.name', 'Bearer JWT Token'),
'in' => config('request-docs.open_api.security.position', 'header'),
'description' => 'JSON Web Token',
'bearerFormat' => 'JWT'
];
$this->openApi['security'][] = [
'bearerAuth' => []
];
break;

default:
break;
}
}

/**
* @codeCoverageIgnore
*/
Expand Down