API: Add openapi endpoint to view specification

This commit is contained in:
Igor Scheller 2023-11-15 22:41:44 +01:00 committed by Michael Weimann
parent 8894f183f2
commit fe836e281e
4 changed files with 60 additions and 5 deletions

View File

@ -118,6 +118,7 @@ $route->addGroup(
function (RouteCollector $route): void { function (RouteCollector $route): void {
$route->addRoute(['OPTIONS'], '[/{resource:.+}]', 'Api\IndexController@options'); $route->addRoute(['OPTIONS'], '[/{resource:.+}]', 'Api\IndexController@options');
$route->get('', 'Api\IndexController@indexV0'); $route->get('', 'Api\IndexController@indexV0');
$route->get('/openapi', 'Api\IndexController@openApiV0');
$route->get('/angeltypes', 'Api\AngelTypeController@index'); $route->get('/angeltypes', 'Api\AngelTypeController@index');
$route->get('/news', 'Api\NewsController@index'); $route->get('/news', 'Api\NewsController@index');

View File

@ -455,3 +455,20 @@ paths:
$ref: '#/components/responses/ForbiddenError' $ref: '#/components/responses/ForbiddenError'
'404': '404':
$ref: '#/components/responses/NotFoundError' $ref: '#/components/responses/NotFoundError'
/openapi:
get:
tags:
- api
summary: Get the OpenAPI definition
responses:
'200':
description: Ok
content:
application/json: {}
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFoundError'

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Engelsystem\Controllers\Api; namespace Engelsystem\Controllers\Api;
use cebe\openapi\spec\OpenApi;
use Engelsystem\Http\Response; use Engelsystem\Http\Response;
use League\OpenAPIValidation\PSR7\ValidatorBuilder as OpenApiValidatorBuilder; use League\OpenAPIValidation\PSR7\ValidatorBuilder as OpenApiValidatorBuilder;
@ -12,6 +13,7 @@ class IndexController extends ApiController
public array $permissions = [ public array $permissions = [
'index' => 'api', 'index' => 'api',
'indexV0' => 'api', 'indexV0' => 'api',
'openApiV0' => 'api',
]; ];
public function index(): Response public function index(): Response
@ -26,11 +28,7 @@ class IndexController extends ApiController
public function indexV0(): Response public function indexV0(): Response
{ {
$openApiDefinition = app()->get('path.resources.api') . '/openapi.yml'; $schema = $this->getApiSpecV0();
$schema = (new OpenApiValidatorBuilder())
->fromYamlFile($openApiDefinition)
->getResponseValidator()
->getSchema();
$info = $schema->info; $info = $schema->info;
$paths = []; $paths = [];
foreach ($schema->paths->getIterator() as $path => $item) { foreach ($schema->paths->getIterator() as $path => $item) {
@ -45,6 +43,16 @@ class IndexController extends ApiController
])); ]));
} }
public function openApiV0(): Response
{
$schema = $this->getApiSpecV0();
$data = $schema->getSerializableData();
unset($data->servers[1]);
$data->servers[0]->url = url('/api/v0-beta');
return $this->response->withContent(json_encode($data));
}
public function options(): Response public function options(): Response
{ {
// Respond to browser preflight options requests // Respond to browser preflight options requests
@ -68,4 +76,13 @@ class IndexController extends ApiController
->withHeader('allow', 'GET') ->withHeader('allow', 'GET')
->withContent(json_encode(['message' => 'Method not implemented'])); ->withContent(json_encode(['message' => 'Method not implemented']));
} }
protected function getApiSpecV0(): OpenApi
{
$openApiDefinition = app()->get('path.resources.api') . '/openapi.yml';
return (new OpenApiValidatorBuilder())
->fromYamlFile($openApiDefinition)
->getResponseValidator()
->getSchema();
}
} }

View File

@ -29,6 +29,7 @@ class IndexControllerTest extends ApiBaseControllerTest
/** /**
* @covers \Engelsystem\Controllers\Api\IndexController::indexV0 * @covers \Engelsystem\Controllers\Api\IndexController::indexV0
* @covers \Engelsystem\Controllers\Api\IndexController::getApiSpecV0
*/ */
public function testIndexV0(): void public function testIndexV0(): void
{ {
@ -43,6 +44,25 @@ class IndexControllerTest extends ApiBaseControllerTest
$this->assertArrayHasKey('paths', $data); $this->assertArrayHasKey('paths', $data);
} }
/**
* @covers \Engelsystem\Controllers\Api\IndexController::openApiV0
* @covers \Engelsystem\Controllers\Api\IndexController::getApiSpecV0
*/
public function testOpenApiV0(): void
{
$controller = new IndexController(new Response());
$response = $controller->openApiV0();
$this->validateApiResponse('/openapi', 'get', $response);
$this->assertEquals(['application/json'], $response->getHeader('content-type'));
$this->assertJson($response->getContent());
$data = json_decode($response->getContent(), true);
$this->assertArrayHasKey('openapi', $data);
$this->assertArrayHasKey('info', $data);
}
/** /**
* @covers \Engelsystem\Controllers\Api\IndexController::options * @covers \Engelsystem\Controllers\Api\IndexController::options
*/ */