Provide a dynamic openapi.yml manifest, fix OpenAPI markup on several sections; update Swagger UI.
This commit is contained in:
parent
e21a23ef35
commit
10970517ac
|
@ -95,12 +95,12 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/AzuraCast/azuracore.git",
|
||||
"reference": "b1254020bdb71a266c38747466bbd7ce5b992553"
|
||||
"reference": "d3cb9c69d0a8bd6f409566eab45ae2620f3d8449"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/AzuraCast/azuracore/zipball/b1254020bdb71a266c38747466bbd7ce5b992553",
|
||||
"reference": "b1254020bdb71a266c38747466bbd7ce5b992553",
|
||||
"url": "https://api.github.com/repos/AzuraCast/azuracore/zipball/d3cb9c69d0a8bd6f409566eab45ae2620f3d8449",
|
||||
"reference": "d3cb9c69d0a8bd6f409566eab45ae2620f3d8449",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -145,7 +145,7 @@
|
|||
}
|
||||
],
|
||||
"description": "A lightweight core application framework.",
|
||||
"time": "2018-12-22T03:04:57+00:00"
|
||||
"time": "2018-12-23T18:57:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "azuracast/azuraforms",
|
||||
|
|
|
@ -155,6 +155,9 @@ return function(App $app)
|
|||
$this->get('', Controller\Api\IndexController::class.':indexAction')
|
||||
->setName('api:index:index');
|
||||
|
||||
$this->get('/openapi.yml', Controller\Api\OpenApiController::class)
|
||||
->setName('api:openapi');
|
||||
|
||||
$this->get('/status', Controller\Api\IndexController::class.':statusAction')
|
||||
->setName('api:index:status');
|
||||
|
||||
|
@ -198,31 +201,19 @@ return function(App $app)
|
|||
$this->group('/admin', function() {
|
||||
/** @var App $this */
|
||||
|
||||
$crud_areas = [
|
||||
Controller\Api\Admin\UsersController::class => [
|
||||
'collection' => 'users',
|
||||
'item' => 'user',
|
||||
'permission' => Acl::GLOBAL_USERS,
|
||||
],
|
||||
];
|
||||
$this->group('', function() {
|
||||
/** @var App $this */
|
||||
$this->get('/users', Controller\Api\Admin\UsersController::class.':listAction')
|
||||
->setName('api:admin:users');
|
||||
$this->post('/users', Controller\Api\Admin\UsersController::class.':createAction');
|
||||
|
||||
foreach($crud_areas as $controller => $route_info) {
|
||||
$this->group('', function() use ($controller, $route_info) {
|
||||
/** @var App $this */
|
||||
$this->get('/user/{id}', Controller\Api\Admin\UsersController::class.':getAction')
|
||||
->setName('api:admin:user');
|
||||
$this->put('/user/{id}', Controller\Api\Admin\UsersController::class.':editAction');
|
||||
$this->delete('/user/{id}', Controller\Api\Admin\UsersController::class.':deleteAction');
|
||||
})->add([Middleware\Permissions::class, Acl::GLOBAL_USERS]);
|
||||
|
||||
$this->get('/'.$route_info['collection'], $controller.':listAction')
|
||||
->setName('api:admin:'.$route_info['collection']);
|
||||
|
||||
$this->post('/'.$route_info['collection'], $controller.':createAction');
|
||||
|
||||
$this->get('/'.$route_info['item'].'/{id}', $controller.':getAction')
|
||||
->setName('api:admin:'.$route_info['item']);
|
||||
|
||||
$this->put('/'.$route_info['item'].'/{id}', $controller.':editAction');
|
||||
$this->delete($route_info['item'].'/{id}', $controller.':deleteAction');
|
||||
|
||||
})->add([Middleware\Permissions::class, $route_info['permission']]);
|
||||
}
|
||||
});
|
||||
|
||||
$this->group('/station/{station}', function () {
|
||||
|
@ -240,15 +231,13 @@ return function(App $app)
|
|||
|
||||
$this->group('/queue', function() {
|
||||
/** @var App $this */
|
||||
|
||||
$this->get('/queue', Controller\Api\Stations\QueueController::class.':listAction')
|
||||
$this->get('', Controller\Api\Stations\QueueController::class.':listAction')
|
||||
->setName('api:stations:queue');
|
||||
|
||||
$this->get('/queue/{id}', Controller\Api\Stations\QueueController::class.':getAction')
|
||||
$this->get('/{id}', Controller\Api\Stations\QueueController::class.':getAction')
|
||||
->setName('api:stations:queue:record');
|
||||
|
||||
$this->delete('/queue/{id}', Controller\Api\Stations\QueueController::class.':deleteAction');
|
||||
|
||||
$this->delete('/{id}', Controller\Api\Stations\QueueController::class.':deleteAction');
|
||||
})->add([Middleware\Permissions::class, Acl::STATION_BROADCASTING, true]);
|
||||
|
||||
$this->get('/requests', Controller\Api\RequestsController::class.':listAction')
|
||||
|
|
|
@ -32,7 +32,6 @@ class App extends \Azura\App
|
|||
define('APP_TESTING_MODE', (isset($settings[Settings::APP_ENV]) && Settings::ENV_TESTING === $settings[Settings::APP_ENV]));
|
||||
|
||||
// Constants used in annotations
|
||||
define('AZURACAST_VERSION', Version::FALLBACK_VERSION);
|
||||
define('SAMPLE_TIMESTAMP', rand(time() - 86400, time() + 86400));
|
||||
|
||||
// Register the plugins engine.
|
||||
|
|
|
@ -28,6 +28,10 @@ class GenerateApiDocs extends CommandAbstract
|
|||
/** @var Settings $settings */
|
||||
$settings = $this->get(Settings::class);
|
||||
|
||||
define('AZURACAST_API_URL', 'https://demo.azuracast.com/api');
|
||||
define('AZURACAST_API_NAME', 'AzuraCast Public Demo Server');
|
||||
define('AZURACAST_VERSION', Version::FALLBACK_VERSION);
|
||||
|
||||
$oa = \OpenApi\scan([
|
||||
$settings[Settings::BASE_DIR] . '/util/openapi.php',
|
||||
$settings[Settings::BASE_DIR] . '/src/Entity',
|
||||
|
|
|
@ -13,23 +13,78 @@ class UsersController extends AbstractGenericCrudController
|
|||
protected $resourceRouteName = 'api:admin:user';
|
||||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/listeners",
|
||||
* tags={"Stations: Listeners"},
|
||||
* description="Return detailed information about current listeners.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\Schema(
|
||||
* type="array",
|
||||
* @OA\Items(ref="#/components/schemas/Api_Listener")
|
||||
* )
|
||||
* @OA\Get(path="/admin/users",
|
||||
* tags={"Administration: Users"},
|
||||
* description="List all current users in the system.",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/User"))
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={
|
||||
* {"api_key"}
|
||||
* },
|
||||
* security={{"api_key": \App\Acl::GLOBAL_USERS}},
|
||||
* )
|
||||
*
|
||||
* @OA\Post(path="/admin/users",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Create a new user.",
|
||||
* @OA\RequestBody(ref="#/components/schemas/User"),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/User")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": \App\Acl::GLOBAL_USERS}},
|
||||
* )
|
||||
*
|
||||
* @OA\Get(path="/admin/user/{id}",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Retrieve details for a single current user.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/User")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": \App\Acl::GLOBAL_USERS}},
|
||||
* )
|
||||
*
|
||||
* @OA\Put(path="/admin/user/{id}",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Update details of a single user.",
|
||||
* @OA\RequestBody(ref="#/components/schemas/User"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/API_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": \App\Acl::GLOBAL_USERS}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/admin/user/{id}",
|
||||
* tags={"Administration: Users"},
|
||||
* description="Delete a single user.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="User ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/API_Status")
|
||||
* ),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": \App\Acl::GLOBAL_USERS}},
|
||||
* )
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
namespace App\Controller\Api;
|
||||
|
||||
use App\Http\Request;
|
||||
use App\Http\Response;
|
||||
use App\Version;
|
||||
use Azura\Settings;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class OpenApiController
|
||||
{
|
||||
/** @var Settings */
|
||||
protected $settings;
|
||||
|
||||
/** @var Version */
|
||||
protected $version;
|
||||
|
||||
/**
|
||||
* @param Settings $settings
|
||||
* @param Version $version
|
||||
*
|
||||
* @see \App\Provider\ApiProvider
|
||||
*/
|
||||
public function __construct(Settings $settings, Version $version)
|
||||
{
|
||||
$this->settings = $settings;
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
public function __invoke(Request $request, Response $response): ResponseInterface
|
||||
{
|
||||
$router = $request->getRouter();
|
||||
|
||||
$api_base_url = (string)$router->fromHere(null, [], [], true);
|
||||
$api_base_url = str_replace('/openapi.yml', '', $api_base_url);
|
||||
|
||||
define('AZURACAST_API_URL', $api_base_url);
|
||||
define('AZURACAST_API_NAME', 'This AzuraCast Installation');
|
||||
define('AZURACAST_VERSION', $this->version->getVersion());
|
||||
|
||||
$oa = \OpenApi\scan([
|
||||
$this->settings[Settings::BASE_DIR] . '/util/openapi.php',
|
||||
$this->settings[Settings::BASE_DIR] . '/src/Entity',
|
||||
$this->settings[Settings::BASE_DIR] . '/src/Controller/Api',
|
||||
], [
|
||||
'exclude' => [
|
||||
'bootstrap',
|
||||
'locale',
|
||||
'templates'
|
||||
],
|
||||
]);
|
||||
|
||||
$yaml = $oa->toYaml();
|
||||
|
||||
return $response
|
||||
->withHeader('Content-Type', 'text/x-yaml')
|
||||
->write($yaml);
|
||||
}
|
||||
}
|
|
@ -32,11 +32,8 @@ class IndexController
|
|||
* tags={"Stations: General"},
|
||||
* description="Returns a list of stations.",
|
||||
* parameters={},
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\Schema(
|
||||
* type="array",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array",
|
||||
* @OA\Items(ref="#/components/schemas/Api_Station")
|
||||
* )
|
||||
* )
|
||||
|
@ -70,12 +67,8 @@ class IndexController
|
|||
* tags={"Stations: General"},
|
||||
* description="Return information about a single station.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\Schema(
|
||||
* ref="#/components/schemas/Api_Station"
|
||||
* )
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_Station")
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found")
|
||||
* )
|
||||
|
|
|
@ -41,14 +41,8 @@ class MediaController
|
|||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="The requested album artwork"
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=404,
|
||||
* description="Image not found; generic filler image."
|
||||
* )
|
||||
* @OA\Response(response=200, description="The requested album artwork"),
|
||||
* @OA\Response(response=404, description="Image not found; generic filler image.")
|
||||
* )
|
||||
*/
|
||||
public function artAction(Request $request, Response $response, $station_id, $media_id): ResponseInterface
|
||||
|
|
|
@ -32,20 +32,17 @@ class QueueController extends AbstractStationCrudController
|
|||
|
||||
/**
|
||||
* @OA\Get(path="/station/{station_id}/queue",
|
||||
* tags={"Stations: Listeners"},
|
||||
* tags={"Stations: Queue"},
|
||||
* description="Return information about the upcoming song playback queue.",
|
||||
* @OA\Parameter(ref="#/components/parameters/station_id_required"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Success",
|
||||
* @OA\Schema(
|
||||
* type="array",
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(type="array",
|
||||
* @OA\Items(ref="#/components/schemas/Api_QueuedSong")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key"}},
|
||||
* security={{"api_key": \App\Acl::STATION_REPORTS}},
|
||||
* )
|
||||
*
|
||||
* @inheritdoc
|
||||
|
@ -83,20 +80,42 @@ class QueueController extends AbstractStationCrudController
|
|||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
* @OA\Get(path="/station/{station_id}/queue/{id}",
|
||||
* tags={"Stations: Queue"},
|
||||
* description="Retrieve details of a single queued item.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Queue Item ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Api_QueuedSong")
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station or Queue ID not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": App\Acl::STATION_REPORTS}},
|
||||
* )
|
||||
*
|
||||
* @OA\Delete(path="/station/{station_id}/queue/{id}",
|
||||
* tags={"Stations: Queue"},
|
||||
* description="Retrieve details of a single queued item.",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Queue Item ID",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer", format="int64")
|
||||
* ),
|
||||
* @OA\Response(response=200, description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/API_Status")
|
||||
* ),
|
||||
* @OA\Response(response=404, description="Station or Queue ID not found"),
|
||||
* @OA\Response(response=403, description="Access denied"),
|
||||
* security={{"api_key": App\Acl::STATION_REPORTS}},
|
||||
* )
|
||||
*/
|
||||
public function getAction(Request $request, Response $response, $station_id, $record_id): ResponseInterface
|
||||
{
|
||||
return parent::getAction($request, $response, $station_id, $record_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function deleteAction(Request $request, Response $response, $station_id, $record_id): ResponseInterface
|
||||
{
|
||||
return parent::deleteAction($request, $response, $station_id, $record_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
|
|
@ -36,6 +36,13 @@ class ApiProvider implements ServiceProviderInterface
|
|||
);
|
||||
};
|
||||
|
||||
$di[Api\OpenApiController::class] = function($di) {
|
||||
return new Api\OpenApiController(
|
||||
$di[\Azura\Settings::class],
|
||||
$di[\App\Version::class]
|
||||
);
|
||||
};
|
||||
|
||||
$di[Api\Stations\QueueController::class] = function($di) {
|
||||
return new Api\Stations\QueueController(
|
||||
$di[\Doctrine\ORM\EntityManager::class],
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
* )
|
||||
*
|
||||
* @OA\Server(
|
||||
* description="AzuraCast Demo API",
|
||||
* url="https://demo.azuracast.com/api"
|
||||
* description=AZURACAST_API_NAME,
|
||||
* url=AZURACAST_API_URL
|
||||
* )
|
||||
*
|
||||
* @OA\ExternalDocumentation(
|
||||
|
@ -41,10 +41,17 @@
|
|||
* name="Now Playing",
|
||||
* description="Endpoints that provide full summaries of the current state of stations.",
|
||||
* )
|
||||
* @OA\Tag(name="Miscellaneous")
|
||||
*
|
||||
* @OA\Tag(name="Stations: General")
|
||||
* @OA\Tag(name="Stations: Song Requests")
|
||||
* @OA\Tag(name="Stations: Listeners")
|
||||
* @OA\Tag(name="Stations: Media")
|
||||
* @OA\Tag(name="Stations: Queue")
|
||||
* @OA\Tag(name="Stations: Service Control")
|
||||
*
|
||||
* @OA\Tag(name="Administration: Users")
|
||||
*
|
||||
* @OA\Tag(name="Miscellaneous")
|
||||
*
|
||||
* @OA\SecurityScheme(
|
||||
* type="apiKey",
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 445 B |
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
|
@ -37,10 +37,9 @@
|
|||
<script src="./swagger-ui-standalone-preset.js"> </script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
|
||||
// Build a system
|
||||
// Begin Swagger UI call region
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "openapi.yml",
|
||||
url: "/api/openapi.yml",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
|
@ -52,6 +51,7 @@
|
|||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
// End Swagger UI call region
|
||||
|
||||
window.ui = ui
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ info:
|
|||
servers:
|
||||
-
|
||||
url: 'https://demo.azuracast.com/api'
|
||||
description: 'AzuraCast Demo API'
|
||||
description: 'AzuraCast Public Demo Server'
|
||||
paths:
|
||||
/status:
|
||||
get:
|
||||
|
@ -49,8 +49,7 @@ paths:
|
|||
description: 'Access denied'
|
||||
security:
|
||||
-
|
||||
api_key:
|
||||
- 'view station reports'
|
||||
- api_key
|
||||
/nowplaying:
|
||||
get:
|
||||
tags:
|
||||
|
@ -159,6 +158,25 @@ paths:
|
|||
description: 'The requested album artwork'
|
||||
'404':
|
||||
description: 'Image not found; generic filler image.'
|
||||
'/station/{station_id}/queue':
|
||||
get:
|
||||
tags:
|
||||
- 'Stations: Listeners'
|
||||
description: 'Return information about the upcoming song playback queue.'
|
||||
operationId: 'App\Controller\Api\Stations\QueueController::listAction'
|
||||
parameters:
|
||||
-
|
||||
$ref: '#/components/parameters/station_id_required'
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
'404':
|
||||
description: 'Station not found'
|
||||
'403':
|
||||
description: 'Access denied'
|
||||
security:
|
||||
-
|
||||
- api_key
|
||||
'/station/{station_id}/restart':
|
||||
post:
|
||||
tags:
|
||||
|
@ -285,7 +303,7 @@ components:
|
|||
connected_on:
|
||||
description: 'UNIX timestamp that the user first connected.'
|
||||
type: integer
|
||||
example: 1545441844
|
||||
example: 1545718940
|
||||
connected_time:
|
||||
description: 'Number of seconds that the user has been connected.'
|
||||
type: integer
|
||||
|
@ -381,7 +399,7 @@ components:
|
|||
cued_at:
|
||||
description: 'UNIX timestamp when the item was cued for playback.'
|
||||
type: integer
|
||||
example: 1545441844
|
||||
example: 1545718940
|
||||
autodj_custom_uri:
|
||||
description: 'Custom AutoDJ playback URI, if it exists.'
|
||||
type: string
|
||||
|
@ -436,7 +454,7 @@ components:
|
|||
played_at:
|
||||
description: 'UNIX timestamp when playback started.'
|
||||
type: integer
|
||||
example: 1545441844
|
||||
example: 1545718940
|
||||
duration:
|
||||
description: 'Duration of the song in seconds'
|
||||
type: integer
|
||||
|
@ -563,7 +581,7 @@ components:
|
|||
timestamp:
|
||||
description: 'The current UNIX timestamp'
|
||||
type: integer
|
||||
example: 1545441844
|
||||
example: 1545718940
|
||||
type: object
|
||||
Api_Time:
|
||||
properties:
|
||||
|
@ -629,10 +647,10 @@ components:
|
|||
example: dark
|
||||
created_at:
|
||||
type: integer
|
||||
example: 1545441844
|
||||
example: 1545718940
|
||||
updated_at:
|
||||
type: integer
|
||||
example: 1545441844
|
||||
example: 1545718940
|
||||
roles:
|
||||
items: { }
|
||||
type: object
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue