API: Added event / api info endpoint, simplified spec

This commit is contained in:
Igor Scheller 2023-12-22 14:18:12 +01:00 committed by Michael Weimann
parent da8178b0bc
commit dc7c62ffe5
4 changed files with 180 additions and 43 deletions

View File

@ -121,6 +121,7 @@ $route->addGroup(
$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('/openapi', 'Api\IndexController@openApiV0');
$route->get('/info', 'Api\IndexController@info');
$route->get('/angeltypes', 'Api\AngelTypeController@index'); $route->get('/angeltypes', 'Api\AngelTypeController@index');
$route->get('/angeltypes/{angeltype_id:\d+}/shifts', 'Api\ShiftsController@entriesByAngeltype'); $route->get('/angeltypes/{angeltype_id:\d+}/shifts', 'Api\ShiftsController@entriesByAngeltype');

View File

@ -21,8 +21,12 @@ servers:
description: Your local dev instance description: Your local dev instance
tags: tags:
- name: api
description: API related
- name: angeltype - name: angeltype
description: Angeltypes description: Angeltypes
- name: event
description: Event information
- name: location - name: location
description: Event locations description: Event locations
- name: news - name: news
@ -105,11 +109,6 @@ components:
required: required:
- confirmed - confirmed
- supporter - supporter
Error:
type: object
properties:
message:
type: string
News: News:
type: object type: object
properties: properties:
@ -140,16 +139,9 @@ components:
example: false example: false
description: True if the news should be highlightet and shown on the dashboard description: True if the news should be highlightet and shown on the dashboard
created_at: created_at:
type: string $ref: '#/components/schemas/DateTime'
format: date-time
description: DateTime in ISO-8601 format
example: 2023-05-13T13:37:42.000000Z
updated_at: updated_at:
type: string $ref: '#/components/schemas/DateTimeOptional'
nullable: true
format: date-time
description: DateTime in ISO-8601 format
example: 2023-05-13T23:00:00.000000Z
url: url:
type: string type: string
example: https://example.com/news/42 example: https://example.com/news/42
@ -197,31 +189,17 @@ components:
Shift description, should be added to the shift type description but might be empty. Shift description, should be added to the shift type description but might be empty.
Normally contains additional information for a specific shift / task. Normally contains additional information for a specific shift / task.
starts_at: starts_at:
type: string $ref: '#/components/schemas/DateTime'
format: date-time
description: DateTime in ISO-8601 format
example: 2023-05-13T14:00:00.000000Z
ends_at: ends_at:
type: string $ref: '#/components/schemas/DateTime'
format: date-time
description: DateTime in ISO-8601 format
example: 2023-05-13T16:00:00.000000Z23
location: location:
$ref: '#/components/schemas/Location' $ref: '#/components/schemas/Location'
shift_type: shift_type:
$ref: '#/components/schemas/ShiftType' $ref: '#/components/schemas/ShiftType'
created_at: created_at:
type: string $ref: '#/components/schemas/DateTimeOptional'
nullable: true
format: date-time
description: DateTime in ISO-8601 format
example: 2023-05-13T13:37:42.000000Z
updated_at: updated_at:
type: string $ref: '#/components/schemas/DateTimeOptional'
nullable: true
format: date-time
description: DateTime in ISO-8601 format
example: 2023-05-13T23:00:00.000000Z
entries: entries:
type: array type: array
description: Can be empty (for example on Schedule import of unused room) description: Can be empty (for example on Schedule import of unused room)
@ -341,17 +319,9 @@ components:
type: object type: object
properties: properties:
planned_arrival: planned_arrival:
type: string $ref: '#/components/schemas/DateTimeOptional'
nullable: true
format: date-time
description: DateTime in ISO-8601 format
example: 2023-05-13T00:00:00.000000Z
planned_departure: planned_departure:
type: string $ref: '#/components/schemas/DateTimeOptional'
nullable: true
format: date-time
description: DateTime in ISO-8601 format
example: 2023-05-23T00:00:00.000000Z
arrival: arrival:
type: string type: string
nullable: true nullable: true
@ -375,6 +345,77 @@ components:
- language - language
- arrived - arrived
DateTime:
type: string
format: date-time
description: DateTime in ISO-8601 format
example: 2023-05-23T00:00:00.000000Z
DateTimeOptional:
type: string
format: date-time
description: DateTime in ISO-8601 format
example: 2023-05-23T00:00:00.000000Z
nullable: true
Error:
type: object
properties:
message:
type: string
EventInfo:
type: object
properties:
api:
type: string
description: API version for easier version detection
example: 1.2.3
spec:
type: string
description: Link to OpenAPI specification
example: https://galactic-help.example/api/v1.2.3/openapi
name:
type: string
example: 42. Galactic Conglomeration Congress
app_name:
type: string
example: Engelsystem
url:
type: string
description: URL to be used when linking to the application
example: https://galactic-help.example
timezone:
type: string
example: Europe/Berlin
description: Timezone of the event
buildup:
type: object
properties:
start:
$ref: '#/components/schemas/DateTimeOptional'
end:
$ref: '#/components/schemas/DateTimeOptional'
required:
- start
- end
teardown:
type: object
properties:
start:
$ref: '#/components/schemas/DateTimeOptional'
end:
$ref: '#/components/schemas/DateTimeOptional'
required:
- start
- end
required:
- api
- spec
- name
- app_name
- url
- timezone
- buildup
- teardown
security: security:
- bearerAuth: [ ] - bearerAuth: [ ]
@ -609,6 +650,28 @@ paths:
'404': '404':
$ref: '#/components/responses/NotFoundError' $ref: '#/components/responses/NotFoundError'
/info:
get:
tags:
- event
summary: Get event information
responses:
'200':
description: Ok
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/EventInfo'
'401':
$ref: '#/components/responses/UnauthorizedError'
'403':
$ref: '#/components/responses/ForbiddenError'
'404':
$ref: '#/components/responses/NotFoundError'
/openapi: /openapi:
get: get:
tags: tags:

View File

@ -21,7 +21,7 @@ class IndexController extends ApiController
return $this->response return $this->response
->withContent(json_encode([ ->withContent(json_encode([
'versions' => [ 'versions' => [
'0.0.1-beta' => '/v0-beta', $this->getApiSpecV0()->info->version => '/v0-beta',
], ],
])); ]));
} }
@ -53,6 +53,32 @@ class IndexController extends ApiController
return $this->response->withContent(json_encode($data)); return $this->response->withContent(json_encode($data));
} }
public function info(): Response
{
$config = config();
$schema = $this->getApiSpecV0();
$data = ['data' => [
'api' => $schema->info->version,
'spec' => url('/api/v0-beta/openapi'),
'name' => (string) $config->get('name'),
'app_name' => (string) $config->get('app_name'),
'url' => url('/'),
'timezone' => (string) $config->get('timezone'),
'buildup' => [
'start' => $config->get('buildup_start'),
'end' => $config->get('buildup_end'),
],
'teardown' => [
'start' => $config->get('teardown_start'),
'end' => $config->get('teardown_end'),
],
]];
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

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Engelsystem\Test\Unit\Controllers\Api; namespace Engelsystem\Test\Unit\Controllers\Api;
use Engelsystem\Config\Config;
use Engelsystem\Controllers\Api\IndexController; use Engelsystem\Controllers\Api\IndexController;
use Engelsystem\Http\Response; use Engelsystem\Http\Response;
@ -63,6 +64,52 @@ class IndexControllerTest extends ApiBaseControllerTest
$this->assertArrayHasKey('info', $data); $this->assertArrayHasKey('info', $data);
} }
/**
* @covers \Engelsystem\Controllers\Api\IndexController::info
*/
public function testInfo(): void
{
$config = new Config(['name' => 'TestEvent', 'app_name' => 'TestSystem', 'timezone' => 'UTC']);
$this->app->instance('config', $config);
$controller = new IndexController(new Response());
$response = $controller->info();
$this->validateApiResponse('/info', 'get', $response);
$this->assertEquals(['application/json'], $response->getHeader('content-type'));
$this->assertJson($response->getContent());
$data = json_decode($response->getContent(), true);
$this->assertArrayHasKey('data', $data);
$data = $data['data'];
$this->assertArrayHasKey('api', $data);
$this->assertArrayHasKey('timezone', $data);
$this->assertEquals('UTC', $data['timezone']);
}
/**
* @covers \Engelsystem\Controllers\Api\IndexController::info
*/
public function testInfoNotConfigured(): void
{
$config = new Config([]);
$this->app->instance('config', $config);
$controller = new IndexController(new Response());
$response = $controller->info();
$this->validateApiResponse('/info', 'get', $response);
$this->assertEquals(['application/json'], $response->getHeader('content-type'));
$this->assertJson($response->getContent());
$data = json_decode($response->getContent(), true);
$this->assertArrayHasKey('data', $data);
$this->assertArrayHasKey('name', $data['data']);
$this->assertEquals('', $data['data']['name']);
}
/** /**
* @covers \Engelsystem\Controllers\Api\IndexController::options * @covers \Engelsystem\Controllers\Api\IndexController::options
*/ */