diff --git a/config/routes/admin.php b/config/routes/admin.php index 361f72f90..0fc568321 100644 --- a/config/routes/admin.php +++ b/config/routes/admin.php @@ -7,194 +7,230 @@ use Slim\App; use Slim\Routing\RouteCollectorProxy; return function (App $app) { - $app->group('/admin', function (RouteCollectorProxy $group) { - $group->get('', Controller\Admin\IndexController::class) - ->setName('admin:index:index'); - - $group->group('/debug', function (RouteCollectorProxy $group) { - - $group->get('', Controller\Admin\DebugController::class) - ->setName('admin:debug:index'); - - $group->get('/clear-cache', Controller\Admin\DebugController::class . ':clearCacheAction') - ->setName('admin:debug:clear-cache'); - - $group->get('/clear-queue[/{queue}]', - Controller\Admin\DebugController::class . ':clearQueueAction') - ->setName('admin:debug:clear-queue'); - - $group->get('/sync/{type}', Controller\Admin\DebugController::class . ':syncAction') - ->setName('admin:debug:sync'); - - $group->get('/log/{path}', Controller\Admin\DebugController::class . ':logAction') - ->setName('admin:debug:log'); - - $group->group('/station/{station_id}', function (RouteCollectorProxy $group) { - - $group->map(['GET', 'POST'], '/nextsong', Controller\Admin\DebugController::class . ':nextsongAction') - ->setName('admin:debug:nextsong'); - - $group->post('/telnet', Controller\Admin\DebugController::class . ':telnetAction') - ->setName('admin:debug:telnet'); - - })->add(Middleware\GetStation::class); - - })->add(new Middleware\Permissions(Acl::GLOBAL_ALL)); - - $group->group('/install', function (RouteCollectorProxy $group) { - - $group->map(['GET', 'POST'], '/shoutcast', Controller\Admin\InstallShoutcastController::class) - ->setName('admin:install_shoutcast:index'); - - $group->map(['GET', 'POST'], '/geolite', Controller\Admin\InstallGeoLiteController::class) - ->setName('admin:install_geolite:index'); - - $group->get( - '/geolite/uninstall/{csrf}', - Controller\Admin\InstallGeoLiteController::class . ':uninstallAction' - )->setName('admin:install_geolite:uninstall'); - - })->add(new Middleware\Permissions(Acl::GLOBAL_ALL)); - - $group->get('/auditlog', Controller\Admin\AuditLogController::class) - ->setName('admin:auditlog:index') - ->add(new Middleware\Permissions(Acl::GLOBAL_LOGS)); - - $group->group('/api', function (RouteCollectorProxy $group) { - - $group->get('', Controller\Admin\ApiController::class . ':indexAction') - ->setName('admin:api:index'); - - $group->map(['GET', 'POST'], '/edit/{id}', Controller\Admin\ApiController::class . ':editAction') - ->setName('admin:api:edit'); - - $group->get('/delete/{id}/{csrf}', Controller\Admin\ApiController::class . ':deleteAction') - ->setName('admin:api:delete'); - - })->add(new Middleware\Permissions(Acl::GLOBAL_API_KEYS)); - - $group->group('/backups', function (RouteCollectorProxy $group) { - - $group->get('', Controller\Admin\BackupsController::class) - ->setName('admin:backups:index'); - - $group->map(['GET', 'POST'], '/configure', Controller\Admin\BackupsController::class . ':configureAction') - ->setName('admin:backups:configure'); - - $group->map(['GET', 'POST'], '/run', Controller\Admin\BackupsController::class . ':runAction') - ->setName('admin:backups:run'); - - $group->get('/log/{path}', Controller\Admin\BackupsController::class . ':logAction') - ->setName('admin:backups:log'); - - $group->get('/download/{path}', Controller\Admin\BackupsController::class . ':downloadAction') - ->setName('admin:backups:download'); - - $group->get('/delete/{path}/{csrf}', Controller\Admin\BackupsController::class . ':deleteAction') - ->setName('admin:backups:delete'); - - })->add(new Middleware\Permissions(Acl::GLOBAL_BACKUPS)); - - $group->map(['GET', 'POST'], '/branding', Controller\Admin\BrandingController::class) - ->setName('admin:branding:index') - ->add(new Middleware\Permissions(Acl::GLOBAL_SETTINGS)); - - $group->group('/custom_fields', function (RouteCollectorProxy $group) { - - $group->get('', Controller\Admin\CustomFieldsController::class . ':indexAction') - ->setName('admin:custom_fields:index'); - - $group->map(['GET', 'POST'], '/edit/{id}', Controller\Admin\CustomFieldsController::class . ':editAction') - ->setName('admin:custom_fields:edit'); - - $group->map(['GET', 'POST'], '/add', Controller\Admin\CustomFieldsController::class . ':editAction') - ->setName('admin:custom_fields:add'); - - $group->get('/delete/{id}/{csrf}', Controller\Admin\CustomFieldsController::class . ':deleteAction') - ->setName('admin:custom_fields:delete'); - - })->add(new Middleware\Permissions(Acl::GLOBAL_CUSTOM_FIELDS)); - - $group->group('/logs', function (RouteCollectorProxy $group) { - - $group->get('', Controller\Admin\LogsController::class) - ->setName('admin:logs:index'); - - $group->get('/view/{station_id}/{log}', Controller\Admin\LogsController::class . ':viewAction') - ->setName('admin:logs:view') - ->add(Middleware\GetStation::class); - - })->add(new Middleware\Permissions(Acl::GLOBAL_LOGS)); - - $group->group('/permissions', function (RouteCollectorProxy $group) { - - $group->get('', Controller\Admin\PermissionsController::class . ':indexAction') - ->setName('admin:permissions:index'); - - $group->map(['GET', 'POST'], '/edit/{id}', Controller\Admin\PermissionsController::class . ':editAction') - ->setName('admin:permissions:edit'); - - $group->map(['GET', 'POST'], '/add', Controller\Admin\PermissionsController::class . ':editAction') - ->setName('admin:permissions:add'); - - $group->get('/delete/{id}/{csrf}', Controller\Admin\PermissionsController::class . ':deleteAction') - ->setName('admin:permissions:delete'); - - })->add(new Middleware\Permissions(Acl::GLOBAL_ALL)); - - $group->get('/relays', Controller\Admin\RelaysController::class) - ->setName('admin:relays:index') - ->add(new Middleware\Permissions(Acl::GLOBAL_STATIONS)); - - $group->map(['GET', 'POST'], '/settings', Controller\Admin\SettingsController::class) - ->setName('admin:settings:index') - ->add(new Middleware\Permissions(Acl::GLOBAL_SETTINGS)); - - $group->group('/stations', function (RouteCollectorProxy $group) { - - $group->get('', Controller\Admin\StationsController::class) - ->setName('admin:stations:index'); - - $group->map(['GET', 'POST'], '/edit/{id}', Controller\Admin\StationsController::class . ':editAction') - ->setName('admin:stations:edit'); - - $group->map(['GET', 'POST'], '/add', Controller\Admin\StationsController::class . ':editAction') - ->setName('admin:stations:add'); - - $group->map(['GET', 'POST'], '/clone/{id}', Controller\Admin\StationsController::class . ':cloneAction') - ->setName('admin:stations:clone'); - - $group->get('/delete/{id}/{csrf}', Controller\Admin\StationsController::class . ':deleteAction') - ->setName('admin:stations:delete'); - - })->add(new Middleware\Permissions(Acl::GLOBAL_STATIONS)); - - $group->get('/storage_locations', Controller\Admin\StorageLocationsController::class) - ->setName('admin:storage_locations:index') - ->add(new Middleware\Permissions(Acl::GLOBAL_STORAGE_LOCATIONS)); - - $group->group('/users', function (RouteCollectorProxy $group) { - - $group->get('', Controller\Admin\UsersController::class . ':indexAction') - ->setName('admin:users:index'); - - $group->map(['GET', 'POST'], '/edit/{id}', Controller\Admin\UsersController::class . ':editAction') - ->setName('admin:users:edit'); - - $group->map(['GET', 'POST'], '/add', Controller\Admin\UsersController::class . ':editAction') - ->setName('admin:users:add'); - - $group->get('/delete/{id}/{csrf}', Controller\Admin\UsersController::class . ':deleteAction') - ->setName('admin:users:delete'); - - $group->get('/login-as/{id}/{csrf}', Controller\Admin\UsersController::class . ':impersonateAction') - ->setName('admin:users:impersonate'); - - })->add(new Middleware\Permissions(Acl::GLOBAL_ALL)); - - // END /admin GROUP - - }) + $app->group( + '/admin', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Admin\IndexController::class) + ->setName('admin:index:index'); + + $group->group( + '/debug', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Admin\DebugController::class) + ->setName('admin:debug:index'); + + $group->get('/clear-cache', Controller\Admin\DebugController::class . ':clearCacheAction') + ->setName('admin:debug:clear-cache'); + + $group->get( + '/clear-queue[/{queue}]', + Controller\Admin\DebugController::class . ':clearQueueAction' + ) + ->setName('admin:debug:clear-queue'); + + $group->get('/sync/{type}', Controller\Admin\DebugController::class . ':syncAction') + ->setName('admin:debug:sync'); + + $group->get('/log/{path}', Controller\Admin\DebugController::class . ':logAction') + ->setName('admin:debug:log'); + + $group->group( + '/station/{station_id}', + function (RouteCollectorProxy $group) { + $group->map( + ['GET', 'POST'], + '/nextsong', + Controller\Admin\DebugController::class . ':nextsongAction' + ) + ->setName('admin:debug:nextsong'); + + $group->post('/telnet', Controller\Admin\DebugController::class . ':telnetAction') + ->setName('admin:debug:telnet'); + } + )->add(Middleware\GetStation::class); + } + )->add(new Middleware\Permissions(Acl::GLOBAL_ALL)); + + $group->group( + '/install', + function (RouteCollectorProxy $group) { + $group->map(['GET', 'POST'], '/shoutcast', Controller\Admin\InstallShoutcastController::class) + ->setName('admin:install_shoutcast:index'); + + $group->map(['GET', 'POST'], '/geolite', Controller\Admin\InstallGeoLiteController::class) + ->setName('admin:install_geolite:index'); + + $group->get( + '/geolite/uninstall/{csrf}', + Controller\Admin\InstallGeoLiteController::class . ':uninstallAction' + )->setName('admin:install_geolite:uninstall'); + } + )->add(new Middleware\Permissions(Acl::GLOBAL_ALL)); + + $group->get('/auditlog', Controller\Admin\AuditLogController::class) + ->setName('admin:auditlog:index') + ->add(new Middleware\Permissions(Acl::GLOBAL_LOGS)); + + $group->group( + '/api', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Admin\ApiController::class . ':indexAction') + ->setName('admin:api:index'); + + $group->map(['GET', 'POST'], '/edit/{id}', Controller\Admin\ApiController::class . ':editAction') + ->setName('admin:api:edit'); + + $group->get('/delete/{id}/{csrf}', Controller\Admin\ApiController::class . ':deleteAction') + ->setName('admin:api:delete'); + } + )->add(new Middleware\Permissions(Acl::GLOBAL_API_KEYS)); + + $group->group( + '/backups', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Admin\BackupsController::class) + ->setName('admin:backups:index'); + + $group->map( + ['GET', 'POST'], + '/configure', + Controller\Admin\BackupsController::class . ':configureAction' + ) + ->setName('admin:backups:configure'); + + $group->map(['GET', 'POST'], '/run', Controller\Admin\BackupsController::class . ':runAction') + ->setName('admin:backups:run'); + + $group->get('/log/{path}', Controller\Admin\BackupsController::class . ':logAction') + ->setName('admin:backups:log'); + + $group->get('/download/{path}', Controller\Admin\BackupsController::class . ':downloadAction') + ->setName('admin:backups:download'); + + $group->get('/delete/{path}/{csrf}', Controller\Admin\BackupsController::class . ':deleteAction') + ->setName('admin:backups:delete'); + } + )->add(new Middleware\Permissions(Acl::GLOBAL_BACKUPS)); + + $group->map(['GET', 'POST'], '/branding', Controller\Admin\BrandingController::class) + ->setName('admin:branding:index') + ->add(new Middleware\Permissions(Acl::GLOBAL_SETTINGS)); + + $group->group( + '/custom_fields', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Admin\CustomFieldsController::class . ':indexAction') + ->setName('admin:custom_fields:index'); + + $group->map( + ['GET', 'POST'], + '/edit/{id}', + Controller\Admin\CustomFieldsController::class . ':editAction' + ) + ->setName('admin:custom_fields:edit'); + + $group->map(['GET', 'POST'], '/add', Controller\Admin\CustomFieldsController::class . ':editAction') + ->setName('admin:custom_fields:add'); + + $group->get('/delete/{id}/{csrf}', Controller\Admin\CustomFieldsController::class . ':deleteAction') + ->setName('admin:custom_fields:delete'); + } + )->add(new Middleware\Permissions(Acl::GLOBAL_CUSTOM_FIELDS)); + + $group->group( + '/logs', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Admin\LogsController::class) + ->setName('admin:logs:index'); + + $group->get('/view/{station_id}/{log}', Controller\Admin\LogsController::class . ':viewAction') + ->setName('admin:logs:view') + ->add(Middleware\GetStation::class); + } + )->add(new Middleware\Permissions(Acl::GLOBAL_LOGS)); + + $group->group( + '/permissions', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Admin\PermissionsController::class . ':indexAction') + ->setName('admin:permissions:index'); + + $group->map( + ['GET', 'POST'], + '/edit/{id}', + Controller\Admin\PermissionsController::class . ':editAction' + ) + ->setName('admin:permissions:edit'); + + $group->map(['GET', 'POST'], '/add', Controller\Admin\PermissionsController::class . ':editAction') + ->setName('admin:permissions:add'); + + $group->get('/delete/{id}/{csrf}', Controller\Admin\PermissionsController::class . ':deleteAction') + ->setName('admin:permissions:delete'); + } + )->add(new Middleware\Permissions(Acl::GLOBAL_ALL)); + + $group->get('/relays', Controller\Admin\RelaysController::class) + ->setName('admin:relays:index') + ->add(new Middleware\Permissions(Acl::GLOBAL_STATIONS)); + + $group->map(['GET', 'POST'], '/settings', Controller\Admin\SettingsController::class) + ->setName('admin:settings:index') + ->add(new Middleware\Permissions(Acl::GLOBAL_SETTINGS)); + + $group->group( + '/stations', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Admin\StationsController::class) + ->setName('admin:stations:index'); + + $group->map( + ['GET', 'POST'], + '/edit/{id}', + Controller\Admin\StationsController::class . ':editAction' + ) + ->setName('admin:stations:edit'); + + $group->map(['GET', 'POST'], '/add', Controller\Admin\StationsController::class . ':editAction') + ->setName('admin:stations:add'); + + $group->map( + ['GET', 'POST'], + '/clone/{id}', + Controller\Admin\StationsController::class . ':cloneAction' + ) + ->setName('admin:stations:clone'); + + $group->get('/delete/{id}/{csrf}', Controller\Admin\StationsController::class . ':deleteAction') + ->setName('admin:stations:delete'); + } + )->add(new Middleware\Permissions(Acl::GLOBAL_STATIONS)); + + $group->get('/storage_locations', Controller\Admin\StorageLocationsController::class) + ->setName('admin:storage_locations:index') + ->add(new Middleware\Permissions(Acl::GLOBAL_STORAGE_LOCATIONS)); + + $group->group( + '/users', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Admin\UsersController::class . ':indexAction') + ->setName('admin:users:index'); + + $group->map(['GET', 'POST'], '/edit/{id}', Controller\Admin\UsersController::class . ':editAction') + ->setName('admin:users:edit'); + + $group->map(['GET', 'POST'], '/add', Controller\Admin\UsersController::class . ':editAction') + ->setName('admin:users:add'); + + $group->get('/delete/{id}/{csrf}', Controller\Admin\UsersController::class . ':deleteAction') + ->setName('admin:users:delete'); + + $group->get('/login-as/{id}/{csrf}', Controller\Admin\UsersController::class . ':impersonateAction') + ->setName('admin:users:impersonate'); + } + )->add(new Middleware\Permissions(Acl::GLOBAL_ALL)); + } + ) ->add(Middleware\Module\Admin::class) ->add(Middleware\EnableView::class) ->add(new Middleware\Permissions(Acl::GLOBAL_VIEW)) diff --git a/config/routes/api.php b/config/routes/api.php index 51f8a4083..1e28e1ddb 100644 --- a/config/routes/api.php +++ b/config/routes/api.php @@ -9,302 +9,404 @@ use Slim\App; use Slim\Routing\RouteCollectorProxy; return function (App $app) { - - $app->group('/api', function (RouteCollectorProxy $group) { - - $group->options('/{routes:.+}', function (ServerRequest $request, Response $response) { - return $response - ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') - ->withHeader('Access-Control-Allow-Headers', - 'x-requested-with, Content-Type, Accept, Origin, Authorization') - ->withHeader('Access-Control-Allow-Origin', '*'); - }); - - $group->get('', Controller\Api\IndexController::class . ':indexAction') - ->setName('api:index:index'); - - $group->get('/openapi.yml', Controller\Api\OpenApiController::class) - ->setName('api:openapi'); - - $group->get('/status', Controller\Api\IndexController::class . ':statusAction') - ->setName('api:index:status'); - - $group->get('/time', Controller\Api\IndexController::class . ':timeAction') - ->setName('api:index:time'); - - $group->group('/internal', function (RouteCollectorProxy $group) { - - $group->group('/{station_id}', function (RouteCollectorProxy $group) { - - // Liquidsoap internal authentication functions - $group->map(['GET', 'POST'], '/auth', Controller\Api\InternalController::class . ':authAction') - ->setName('api:internal:auth'); - - $group->map(['GET', 'POST'], '/nextsong', Controller\Api\InternalController::class . ':nextsongAction') - ->setName('api:internal:nextsong'); - - $group->map(['GET', 'POST'], '/djon', Controller\Api\InternalController::class . ':djonAction') - ->setName('api:internal:djon'); - - $group->map(['GET', 'POST'], '/djoff', Controller\Api\InternalController::class . ':djoffAction') - ->setName('api:internal:djoff'); - - $group->map(['GET', 'POST'], '/feedback', Controller\Api\InternalController::class . ':feedbackAction') - ->setName('api:internal:feedback'); - - })->add(Middleware\GetStation::class); - - $group->get('/relays', Controller\Api\Admin\RelaysController::class) - ->setName('api:internal:relays') - ->add(Middleware\RequireLogin::class); - - $group->post('/relays', Controller\Api\Admin\RelaysController::class . ':updateAction') - ->add(Middleware\RequireLogin::class); - - }); - - $group->get('/nowplaying[/{station_id}]', Controller\Api\NowplayingController::class) - ->setName('api:nowplaying:index'); - - $group->get('/stations', Controller\Api\Stations\IndexController::class . ':listAction') - ->setName('api:stations:list') - ->add(new Middleware\RateLimit('api')); - - $group->group('/admin', function (RouteCollectorProxy $group) { - - $group->get('/auditlog', Controller\Api\Admin\AuditLogController::class) - ->setName('api:admin:auditlog') - ->add(new Middleware\Permissions(Acl::GLOBAL_LOGS)); - - $group->get('/permissions', Controller\Api\Admin\PermissionsController::class) - ->add(new Middleware\Permissions(Acl::GLOBAL_ALL)); - - $group->map(['GET', 'POST'], '/relays', function (ServerRequest $request, Response $response) { - return $response->withRedirect((string)$request->getRouter()->fromHere('api:internal:relays')); - }); - - $group->group('', function (RouteCollectorProxy $group) { - $group->get('/settings', Controller\Api\Admin\SettingsController::class . ':listAction') - ->setName('api:admin:settings'); - - $group->put('/settings', Controller\Api\Admin\SettingsController::class . ':updateAction'); - })->add(new Middleware\Permissions(Acl::GLOBAL_SETTINGS)); - - $admin_api_endpoints = [ - [ - 'custom_field', - 'custom_fields', - Controller\Api\Admin\CustomFieldsController::class, - Acl::GLOBAL_CUSTOM_FIELDS, - ], - ['role', 'roles', Controller\Api\Admin\RolesController::class, Acl::GLOBAL_ALL], - ['station', 'stations', Controller\Api\Admin\StationsController::class, Acl::GLOBAL_STATIONS], - ['user', 'users', Controller\Api\Admin\UsersController::class, Acl::GLOBAL_ALL], - [ - 'storage_location', - 'storage_locations', - Controller\Api\Admin\StorageLocationsController::class, - Acl::GLOBAL_STORAGE_LOCATIONS, - ], - ]; - - foreach ($admin_api_endpoints as [$singular, $plural, $class, $permission]) { - $group->group('', function (RouteCollectorProxy $group) use ($singular, $plural, $class) { - $group->get('/' . $plural, $class . ':listAction') - ->setName('api:admin:' . $plural); - $group->post('/' . $plural, $class . ':createAction'); - - $group->get('/' . $singular . '/{id}', $class . ':getAction') - ->setName('api:admin:' . $singular); - $group->put('/' . $singular . '/{id}', $class . ':editAction'); - $group->delete('/' . $singular . '/{id}', $class . ':deleteAction'); - })->add(new Middleware\Permissions($permission)); - } - }); - - $group->group('/station/{station_id}', function (RouteCollectorProxy $group) { - - $group->get('', Controller\Api\Stations\IndexController::class . ':indexAction') - ->setName('api:stations:index') - ->add(new Middleware\RateLimit('api', 5, 2)); - - $group->get('/nowplaying', Controller\Api\NowplayingController::class . ':indexAction'); - - $group->map(['GET', 'POST'], '/nowplaying/update', Controller\Api\Stations\UpdateMetadataController::class) - ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); - - $group->get('/profile', Controller\Api\Stations\ProfileController::class) - ->setName('api:stations:profile') - ->add(new Middleware\Permissions(Acl::STATION_VIEW, true)); - - $group->get('/schedule', Controller\Api\Stations\ScheduleController::class) - ->setName('api:stations:schedule'); - - $group->get('/history', Controller\Api\Stations\HistoryController::class) - ->setName('api:stations:history') - ->add(new Middleware\Permissions(Acl::STATION_REPORTS, true)); - - $group->group('/queue', function (RouteCollectorProxy $group) { - $group->get('', Controller\Api\Stations\QueueController::class . ':listAction') - ->setName('api:stations:queue'); - - $group->get('/{id}', Controller\Api\Stations\QueueController::class . ':getAction') - ->setName('api:stations:queue:record'); - - $group->delete('/{id}', Controller\Api\Stations\QueueController::class . ':deleteAction'); - })->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); - - $group->get('/requests', Controller\Api\Stations\RequestsController::class . ':listAction') - ->setName('api:requests:list'); - - $group->map(['GET', 'POST'], '/request/{media_id}', - Controller\Api\Stations\RequestsController::class . ':submitAction') - ->setName('api:requests:submit') - ->add(new Middleware\RateLimit('api', 5, 2)); - - $group->get('/ondemand', Controller\Api\Stations\OnDemand\ListAction::class) - ->setName('api:stations:ondemand:list'); - - $group->get('/ondemand/download/{media_id}', Controller\Api\Stations\OnDemand\DownloadAction::class) - ->setName('api:stations:ondemand:download') - ->add(new Middleware\RateLimit('ondemand', 1, 2)); - - $group->get('/listeners', Controller\Api\Stations\ListenersController::class . ':indexAction') - ->setName('api:listeners:index') - ->add(new Middleware\Permissions(Acl::STATION_REPORTS, true)); - - $group->get('/waveform/{media_id:[a-zA-Z0-9\-]+}.json', - Controller\Api\Stations\Waveform\GetWaveformAction::class) - ->setName('api:stations:media:waveform'); - - $group->get('/art/{media_id:[a-zA-Z0-9\-]+}.jpg', Controller\Api\Stations\Art\GetArtAction::class) - ->setName('api:stations:media:art'); - - $group->get('/art/{media_id:[a-zA-Z0-9\-]+}', Controller\Api\Stations\Art\GetArtAction::class) - ->setName('api:stations:media:art-internal'); - - $group->post('/art/{media_id:[a-zA-Z0-9]+}', Controller\Api\Stations\Art\PostArtAction::class) - ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); - - $group->delete('/art/{media_id:[a-zA-Z0-9]+}', Controller\Api\Stations\Art\DeleteArtAction::class) - ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); - - $station_api_endpoints = [ - ['file', 'files', Controller\Api\Stations\FilesController::class, Acl::STATION_MEDIA], - ['mount', 'mounts', Controller\Api\Stations\MountsController::class, Acl::STATION_MOUNTS], - ['playlist', 'playlists', Controller\Api\Stations\PlaylistsController::class, Acl::STATION_MEDIA], - ['remote', 'remotes', Controller\Api\Stations\RemotesController::class, Acl::STATION_REMOTES], - ['streamer', 'streamers', Controller\Api\Stations\StreamersController::class, Acl::STATION_STREAMERS], - ['webhook', 'webhooks', Controller\Api\Stations\WebhooksController::class, Acl::STATION_WEB_HOOKS], - ]; - - foreach ($station_api_endpoints as [$singular, $plural, $class, $permission]) { - $group->group('', function (RouteCollectorProxy $group) use ($singular, $plural, $class) { - $group->get('/' . $plural, $class . ':listAction') - ->setName('api:stations:' . $plural); - $group->post('/' . $plural, $class . ':createAction'); - - $group->get('/' . $singular . '/{id}', $class . ':getAction') - ->setName('api:stations:' . $singular); - $group->put('/' . $singular . '/{id}', $class . ':editAction'); - $group->delete('/' . $singular . '/{id}', $class . ':deleteAction'); - })->add(new Middleware\Permissions($permission, true)); - } - - $group->group('/files', function (RouteCollectorProxy $group) { - - $group->get('/list', Controller\Api\Stations\Files\ListAction::class) - ->setName('api:stations:files:list'); - - $group->get('/directories', Controller\Api\Stations\Files\ListDirectoriesAction::class) - ->setName('api:stations:files:directories'); - - $group->put('/rename', Controller\Api\Stations\Files\RenameAction::class) - ->setName('api:stations:files:rename'); - - $group->put('/batch', Controller\Api\Stations\Files\BatchAction::class) - ->setName('api:stations:files:batch'); - - $group->post('/mkdir', Controller\Api\Stations\Files\MakeDirectoryAction::class) - ->setName('api:stations:files:mkdir'); - - $group->map(['GET', 'POST'], '/upload', Controller\Api\Stations\Files\FlowUploadAction::class) - ->setName('api:stations:files:upload'); - }) - ->add(Middleware\Module\StationFiles::class) - ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); - - $group->get('/download/{id}', Controller\Api\Stations\Files\DownloadAction::class) - ->setName('api:stations:file:download') - ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); - - $group->get('/playlists/schedule', Controller\Api\Stations\PlaylistsController::class . ':scheduleAction') - ->setName('api:stations:playlists:schedule') - ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); - - $group->group('/playlist/{id}', function (RouteCollectorProxy $group) { - - $group->put('/toggle', Controller\Api\Stations\PlaylistsController::class . ':toggleAction') - ->setName('api:stations:playlist:toggle'); - - $group->put('/reshuffle', Controller\Api\Stations\PlaylistsController::class . ':reshuffleAction') - ->setName('api:stations:playlist:reshuffle'); - - $group->get('/order', Controller\Api\Stations\PlaylistsController::class . ':getOrderAction') - ->setName('api:stations:playlist:order'); - - $group->put('/order', Controller\Api\Stations\PlaylistsController::class . ':putOrderAction'); - - $group->post('/import', Controller\Api\Stations\PlaylistsController::class . ':importAction') - ->setName('api:stations:playlist:import'); - - $group->get('/export[/{format}]', - Controller\Api\Stations\PlaylistsController::class . ':exportAction') - ->setName('api:stations:playlist:export'); - - })->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); - - $group->get('/streamers/schedule', Controller\Api\Stations\StreamersController::class . ':scheduleAction') - ->setName('api:stations:streamers:schedule') - ->add(new Middleware\Permissions(Acl::STATION_STREAMERS, true)); - - $group->group('/streamer/{id}', function (RouteCollectorProxy $group) { - - $group->get('/broadcasts', - Controller\Api\Stations\Streamers\BroadcastsController::class . ':listAction') - ->setName('api:stations:streamer:broadcasts'); - - $group->get('/broadcast/{broadcast_id}/download', - Controller\Api\Stations\Streamers\BroadcastsController::class . ':downloadAction') - ->setName('api:stations:streamer:broadcast:download'); - - $group->delete('/broadcast/{broadcast_id}', - Controller\Api\Stations\Streamers\BroadcastsController::class . ':deleteAction') - ->setName('api:stations:streamer:broadcast:delete'); - - })->add(new Middleware\Permissions(Acl::STATION_STREAMERS, true)); - - $group->get('/status', Controller\Api\Stations\ServicesController::class . ':statusAction') - ->setName('api:stations:status') - ->add(new Middleware\Permissions(Acl::STATION_VIEW, true)); - - $group->post('/backend/{do}', Controller\Api\Stations\ServicesController::class . ':backendAction') - ->setName('api:stations:backend') - ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); - - $group->post('/frontend/{do}', Controller\Api\Stations\ServicesController::class . ':frontendAction') - ->setName('api:stations:frontend') - ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); - - $group->post('/restart', Controller\Api\Stations\ServicesController::class . ':restartAction') - ->setName('api:stations:restart') - ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); - - })->add(Middleware\RequireStation::class) - ->add(Middleware\GetStation::class); - - // END /api GROUP - - })->add(Middleware\Module\Api::class); - + $app->group( + '/api', + function (RouteCollectorProxy $group) { + $group->options( + '/{routes:.+}', + function (ServerRequest $request, Response $response) { + return $response + ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') + ->withHeader( + 'Access-Control-Allow-Headers', + 'x-requested-with, Content-Type, Accept, Origin, Authorization' + ) + ->withHeader('Access-Control-Allow-Origin', '*'); + } + ); + + $group->get('', Controller\Api\IndexController::class . ':indexAction') + ->setName('api:index:index'); + + $group->get('/openapi.yml', Controller\Api\OpenApiController::class) + ->setName('api:openapi'); + + $group->get('/status', Controller\Api\IndexController::class . ':statusAction') + ->setName('api:index:status'); + + $group->get('/time', Controller\Api\IndexController::class . ':timeAction') + ->setName('api:index:time'); + + $group->group( + '/internal', + function (RouteCollectorProxy $group) { + $group->group( + '/{station_id}', + function (RouteCollectorProxy $group) { + // Liquidsoap internal authentication functions + $group->map( + ['GET', 'POST'], + '/auth', + Controller\Api\InternalController::class . ':authAction' + )->setName('api:internal:auth'); + + $group->map( + ['GET', 'POST'], + '/nextsong', + Controller\Api\InternalController::class . ':nextsongAction' + )->setName('api:internal:nextsong'); + + $group->map( + ['GET', 'POST'], + '/djon', + Controller\Api\InternalController::class . ':djonAction' + )->setName('api:internal:djon'); + + $group->map( + ['GET', 'POST'], + '/djoff', + Controller\Api\InternalController::class . ':djoffAction' + )->setName('api:internal:djoff'); + + $group->map( + ['GET', 'POST'], + '/feedback', + Controller\Api\InternalController::class . ':feedbackAction' + )->setName('api:internal:feedback'); + } + )->add(Middleware\GetStation::class); + + $group->get('/relays', Controller\Api\Admin\RelaysController::class) + ->setName('api:internal:relays') + ->add(Middleware\RequireLogin::class); + + $group->post('/relays', Controller\Api\Admin\RelaysController::class . ':updateAction') + ->add(Middleware\RequireLogin::class); + } + ); + + $group->get('/nowplaying[/{station_id}]', Controller\Api\NowplayingController::class) + ->setName('api:nowplaying:index'); + + $group->get('/stations', Controller\Api\Stations\IndexController::class . ':listAction') + ->setName('api:stations:list') + ->add(new Middleware\RateLimit('api')); + + $group->group( + '/admin', + function (RouteCollectorProxy $group) { + $group->get('/auditlog', Controller\Api\Admin\AuditLogController::class) + ->setName('api:admin:auditlog') + ->add(new Middleware\Permissions(Acl::GLOBAL_LOGS)); + + $group->get('/permissions', Controller\Api\Admin\PermissionsController::class) + ->add(new Middleware\Permissions(Acl::GLOBAL_ALL)); + + $group->map( + ['GET', 'POST'], + '/relays', + function (ServerRequest $request, Response $response) { + return $response->withRedirect( + (string)$request->getRouter()->fromHere('api:internal:relays') + ); + } + ); + + $group->group( + '', + function (RouteCollectorProxy $group) { + $group->get('/settings', Controller\Api\Admin\SettingsController::class . ':listAction') + ->setName('api:admin:settings'); + + $group->put('/settings', Controller\Api\Admin\SettingsController::class . ':updateAction'); + } + )->add(new Middleware\Permissions(Acl::GLOBAL_SETTINGS)); + + $admin_api_endpoints = [ + [ + 'custom_field', + 'custom_fields', + Controller\Api\Admin\CustomFieldsController::class, + Acl::GLOBAL_CUSTOM_FIELDS, + ], + ['role', 'roles', Controller\Api\Admin\RolesController::class, Acl::GLOBAL_ALL], + ['station', 'stations', Controller\Api\Admin\StationsController::class, Acl::GLOBAL_STATIONS], + ['user', 'users', Controller\Api\Admin\UsersController::class, Acl::GLOBAL_ALL], + [ + 'storage_location', + 'storage_locations', + Controller\Api\Admin\StorageLocationsController::class, + Acl::GLOBAL_STORAGE_LOCATIONS, + ], + ]; + + foreach ($admin_api_endpoints as [$singular, $plural, $class, $permission]) { + $group->group( + '', + function (RouteCollectorProxy $group) use ($singular, $plural, $class) { + $group->get('/' . $plural, $class . ':listAction') + ->setName('api:admin:' . $plural); + $group->post('/' . $plural, $class . ':createAction'); + + $group->get('/' . $singular . '/{id}', $class . ':getAction') + ->setName('api:admin:' . $singular); + $group->put('/' . $singular . '/{id}', $class . ':editAction'); + $group->delete('/' . $singular . '/{id}', $class . ':deleteAction'); + } + )->add(new Middleware\Permissions($permission)); + } + } + ); + + $group->group( + '/station/{station_id}', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Api\Stations\IndexController::class . ':indexAction') + ->setName('api:stations:index') + ->add(new Middleware\RateLimit('api', 5, 2)); + + $group->get('/nowplaying', Controller\Api\NowplayingController::class . ':indexAction'); + + $group->map( + ['GET', 'POST'], + '/nowplaying/update', + Controller\Api\Stations\UpdateMetadataController::class + ) + ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); + + $group->get('/profile', Controller\Api\Stations\ProfileController::class) + ->setName('api:stations:profile') + ->add(new Middleware\Permissions(Acl::STATION_VIEW, true)); + + $group->get('/schedule', Controller\Api\Stations\ScheduleController::class) + ->setName('api:stations:schedule'); + + $group->get('/history', Controller\Api\Stations\HistoryController::class) + ->setName('api:stations:history') + ->add(new Middleware\Permissions(Acl::STATION_REPORTS, true)); + + $group->group( + '/queue', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Api\Stations\QueueController::class . ':listAction') + ->setName('api:stations:queue'); + + $group->get('/{id}', Controller\Api\Stations\QueueController::class . ':getAction') + ->setName('api:stations:queue:record'); + + $group->delete('/{id}', Controller\Api\Stations\QueueController::class . ':deleteAction'); + } + )->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); + + $group->get('/requests', Controller\Api\Stations\RequestsController::class . ':listAction') + ->setName('api:requests:list'); + + $group->map( + ['GET', 'POST'], + '/request/{media_id}', + Controller\Api\Stations\RequestsController::class . ':submitAction' + ) + ->setName('api:requests:submit') + ->add(new Middleware\RateLimit('api', 5, 2)); + + $group->get('/ondemand', Controller\Api\Stations\OnDemand\ListAction::class) + ->setName('api:stations:ondemand:list'); + + $group->get('/ondemand/download/{media_id}', Controller\Api\Stations\OnDemand\DownloadAction::class) + ->setName('api:stations:ondemand:download') + ->add(new Middleware\RateLimit('ondemand', 1, 2)); + + $group->get('/listeners', Controller\Api\Stations\ListenersController::class . ':indexAction') + ->setName('api:listeners:index') + ->add(new Middleware\Permissions(Acl::STATION_REPORTS, true)); + + $group->get( + '/waveform/{media_id:[a-zA-Z0-9\-]+}.json', + Controller\Api\Stations\Waveform\GetWaveformAction::class + ) + ->setName('api:stations:media:waveform'); + + $group->get('/art/{media_id:[a-zA-Z0-9\-]+}.jpg', Controller\Api\Stations\Art\GetArtAction::class) + ->setName('api:stations:media:art'); + + $group->get('/art/{media_id:[a-zA-Z0-9\-]+}', Controller\Api\Stations\Art\GetArtAction::class) + ->setName('api:stations:media:art-internal'); + + $group->post('/art/{media_id:[a-zA-Z0-9]+}', Controller\Api\Stations\Art\PostArtAction::class) + ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); + + $group->delete('/art/{media_id:[a-zA-Z0-9]+}', Controller\Api\Stations\Art\DeleteArtAction::class) + ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); + + $station_api_endpoints = [ + ['file', 'files', Controller\Api\Stations\FilesController::class, Acl::STATION_MEDIA], + ['mount', 'mounts', Controller\Api\Stations\MountsController::class, Acl::STATION_MOUNTS], + [ + 'playlist', + 'playlists', + Controller\Api\Stations\PlaylistsController::class, + Acl::STATION_MEDIA, + ], + ['remote', 'remotes', Controller\Api\Stations\RemotesController::class, Acl::STATION_REMOTES], + [ + 'streamer', + 'streamers', + Controller\Api\Stations\StreamersController::class, + Acl::STATION_STREAMERS, + ], + [ + 'webhook', + 'webhooks', + Controller\Api\Stations\WebhooksController::class, + Acl::STATION_WEB_HOOKS, + ], + ]; + + foreach ($station_api_endpoints as [$singular, $plural, $class, $permission]) { + $group->group( + '', + function (RouteCollectorProxy $group) use ($singular, $plural, $class) { + $group->get('/' . $plural, $class . ':listAction') + ->setName('api:stations:' . $plural); + $group->post('/' . $plural, $class . ':createAction'); + + $group->get('/' . $singular . '/{id}', $class . ':getAction') + ->setName('api:stations:' . $singular); + $group->put('/' . $singular . '/{id}', $class . ':editAction'); + $group->delete('/' . $singular . '/{id}', $class . ':deleteAction'); + } + )->add(new Middleware\Permissions($permission, true)); + } + + $group->group( + '/files', + function (RouteCollectorProxy $group) { + $group->get('/list', Controller\Api\Stations\Files\ListAction::class) + ->setName('api:stations:files:list'); + + $group->get('/directories', Controller\Api\Stations\Files\ListDirectoriesAction::class) + ->setName('api:stations:files:directories'); + + $group->put('/rename', Controller\Api\Stations\Files\RenameAction::class) + ->setName('api:stations:files:rename'); + + $group->put('/batch', Controller\Api\Stations\Files\BatchAction::class) + ->setName('api:stations:files:batch'); + + $group->post('/mkdir', Controller\Api\Stations\Files\MakeDirectoryAction::class) + ->setName('api:stations:files:mkdir'); + + $group->get('/play/{id}', Controller\Api\Stations\Files\PlayAction::class) + ->setName('api:stations:files:play'); + + $group->get('/download', Controller\Api\Stations\Files\DownloadAction::class) + ->setName('api:stations:files:download'); + + $group->map( + ['GET', 'POST'], + '/upload', + Controller\Api\Stations\Files\FlowUploadAction::class + )->setName('api:stations:files:upload'); + } + ) + ->add(Middleware\Module\StationFiles::class) + ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); + + $group->get( + '/playlists/schedule', + Controller\Api\Stations\PlaylistsController::class . ':scheduleAction' + ) + ->setName('api:stations:playlists:schedule') + ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); + + $group->group( + '/playlist/{id}', + function (RouteCollectorProxy $group) { + $group->put('/toggle', Controller\Api\Stations\PlaylistsController::class . ':toggleAction') + ->setName('api:stations:playlist:toggle'); + + $group->put( + '/reshuffle', + Controller\Api\Stations\PlaylistsController::class . ':reshuffleAction' + ) + ->setName('api:stations:playlist:reshuffle'); + + $group->get( + '/order', + Controller\Api\Stations\PlaylistsController::class . ':getOrderAction' + ) + ->setName('api:stations:playlist:order'); + + $group->put( + '/order', + Controller\Api\Stations\PlaylistsController::class . ':putOrderAction' + ); + + $group->post( + '/import', + Controller\Api\Stations\PlaylistsController::class . ':importAction' + ) + ->setName('api:stations:playlist:import'); + + $group->get( + '/export[/{format}]', + Controller\Api\Stations\PlaylistsController::class . ':exportAction' + ) + ->setName('api:stations:playlist:export'); + } + )->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); + + $group->get( + '/streamers/schedule', + Controller\Api\Stations\StreamersController::class . ':scheduleAction' + ) + ->setName('api:stations:streamers:schedule') + ->add(new Middleware\Permissions(Acl::STATION_STREAMERS, true)); + + $group->group( + '/streamer/{id}', + function (RouteCollectorProxy $group) { + $group->get( + '/broadcasts', + Controller\Api\Stations\Streamers\BroadcastsController::class . ':listAction' + ) + ->setName('api:stations:streamer:broadcasts'); + + $group->get( + '/broadcast/{broadcast_id}/download', + Controller\Api\Stations\Streamers\BroadcastsController::class . ':downloadAction' + ) + ->setName('api:stations:streamer:broadcast:download'); + + $group->delete( + '/broadcast/{broadcast_id}', + Controller\Api\Stations\Streamers\BroadcastsController::class . ':deleteAction' + ) + ->setName('api:stations:streamer:broadcast:delete'); + } + )->add(new Middleware\Permissions(Acl::STATION_STREAMERS, true)); + + $group->get('/status', Controller\Api\Stations\ServicesController::class . ':statusAction') + ->setName('api:stations:status') + ->add(new Middleware\Permissions(Acl::STATION_VIEW, true)); + + $group->post('/backend/{do}', Controller\Api\Stations\ServicesController::class . ':backendAction') + ->setName('api:stations:backend') + ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); + + $group->post( + '/frontend/{do}', + Controller\Api\Stations\ServicesController::class . ':frontendAction' + ) + ->setName('api:stations:frontend') + ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); + + $group->post('/restart', Controller\Api\Stations\ServicesController::class . ':restartAction') + ->setName('api:stations:restart') + ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); + } + )->add(Middleware\RequireStation::class) + ->add(Middleware\GetStation::class); + } + )->add(Middleware\Module\Api::class); }; diff --git a/config/routes/base.php b/config/routes/base.php index a59aa3034..a6f4d2797 100644 --- a/config/routes/base.php +++ b/config/routes/base.php @@ -6,52 +6,61 @@ use Slim\App; use Slim\Routing\RouteCollectorProxy; return function (App $app) { - $app->get('/', Controller\Frontend\IndexController::class . ':indexAction') ->setName('home'); - $app->group('', function (RouteCollectorProxy $group) { + $app->group( + '', + function (RouteCollectorProxy $group) { + $group->get('/dashboard', Controller\Frontend\DashboardController::class . ':indexAction') + ->setName('dashboard'); - $group->get('/dashboard', Controller\Frontend\DashboardController::class . ':indexAction') - ->setName('dashboard'); + $group->get('/logout', Controller\Frontend\Account\LogoutAction::class) + ->setName('account:logout'); - $group->get('/logout', Controller\Frontend\Account\LogoutAction::class) - ->setName('account:logout'); + $group->get('/endsession', Controller\Frontend\Account\EndMasqueradeAction::class) + ->setName('account:endmasquerade'); - $group->get('/endsession', Controller\Frontend\Account\EndMasqueradeAction::class) - ->setName('account:endmasquerade'); + $group->get('/profile', Controller\Frontend\Profile\IndexAction::class) + ->setName('profile:index'); - $group->get('/profile', Controller\Frontend\Profile\IndexAction::class) - ->setName('profile:index'); + $group->map(['GET', 'POST'], '/profile/edit', Controller\Frontend\Profile\EditAction::class) + ->setName('profile:edit'); - $group->map(['GET', 'POST'], '/profile/edit', Controller\Frontend\Profile\EditAction::class) - ->setName('profile:edit'); + $group->map( + ['GET', 'POST'], + '/profile/2fa/enable', + Controller\Frontend\Profile\EnableTwoFactorAction::class + ) + ->setName('profile:2fa:enable'); - $group->map(['GET', 'POST'], '/profile/2fa/enable', - Controller\Frontend\Profile\EnableTwoFactorAction::class) - ->setName('profile:2fa:enable'); + $group->map( + ['GET', 'POST'], + '/profile/2fa/disable', + Controller\Frontend\Profile\DisableTwoFactorAction::class + ) + ->setName('profile:2fa:disable'); - $group->map(['GET', 'POST'], '/profile/2fa/disable', - Controller\Frontend\Profile\DisableTwoFactorAction::class) - ->setName('profile:2fa:disable'); + $group->get('/profile/theme', Controller\Frontend\Profile\ThemeAction::class) + ->setName('profile:theme'); - $group->get('/profile/theme', Controller\Frontend\Profile\ThemeAction::class) - ->setName('profile:theme'); + $group->get('/api_keys', Controller\Frontend\ApiKeysController::class . ':indexAction') + ->setName('api_keys:index'); - $group->get('/api_keys', Controller\Frontend\ApiKeysController::class . ':indexAction') - ->setName('api_keys:index'); + $group->map( + ['GET', 'POST'], + '/api_keys/edit/{id}', + Controller\Frontend\ApiKeysController::class . ':editAction' + ) + ->setName('api_keys:edit'); - $group->map(['GET', 'POST'], '/api_keys/edit/{id}', - Controller\Frontend\ApiKeysController::class . ':editAction') - ->setName('api_keys:edit'); + $group->map(['GET', 'POST'], '/api_keys/add', Controller\Frontend\ApiKeysController::class . ':editAction') + ->setName('api_keys:add'); - $group->map(['GET', 'POST'], '/api_keys/add', Controller\Frontend\ApiKeysController::class . ':editAction') - ->setName('api_keys:add'); - - $group->get('/api_keys/delete/{id}/{csrf}', Controller\Frontend\ApiKeysController::class . ':deleteAction') - ->setName('api_keys:delete'); - - })->add(Middleware\EnableView::class) + $group->get('/api_keys/delete/{id}/{csrf}', Controller\Frontend\ApiKeysController::class . ':deleteAction') + ->setName('api_keys:delete'); + } + )->add(Middleware\EnableView::class) ->add(Middleware\RequireLogin::class); $app->map(['GET', 'POST'], '/login', Controller\Frontend\Account\LoginAction::class) @@ -62,23 +71,23 @@ return function (App $app) { ->setName('account:login:2fa') ->add(Middleware\EnableView::class); - $app->group('/setup', function (RouteCollectorProxy $group) { + $app->group( + '/setup', + function (RouteCollectorProxy $group) { + $group->map(['GET', 'POST'], '', Controller\Frontend\SetupController::class . ':indexAction') + ->setName('setup:index'); - $group->map(['GET', 'POST'], '', Controller\Frontend\SetupController::class . ':indexAction') - ->setName('setup:index'); + $group->map(['GET', 'POST'], '/complete', Controller\Frontend\SetupController::class . ':completeAction') + ->setName('setup:complete'); - $group->map(['GET', 'POST'], '/complete', Controller\Frontend\SetupController::class . ':completeAction') - ->setName('setup:complete'); + $group->map(['GET', 'POST'], '/register', Controller\Frontend\SetupController::class . ':registerAction') + ->setName('setup:register'); - $group->map(['GET', 'POST'], '/register', Controller\Frontend\SetupController::class . ':registerAction') - ->setName('setup:register'); + $group->map(['GET', 'POST'], '/station', Controller\Frontend\SetupController::class . ':stationAction') + ->setName('setup:station'); - $group->map(['GET', 'POST'], '/station', Controller\Frontend\SetupController::class . ':stationAction') - ->setName('setup:station'); - - $group->map(['GET', 'POST'], '/settings', Controller\Frontend\SetupController::class . ':settingsAction') - ->setName('setup:settings'); - - })->add(Middleware\EnableView::class); - -}; \ No newline at end of file + $group->map(['GET', 'POST'], '/settings', Controller\Frontend\SetupController::class . ':settingsAction') + ->setName('setup:settings'); + } + )->add(Middleware\EnableView::class); +}; diff --git a/config/routes/public.php b/config/routes/public.php index 3995a404e..7b9c729c5 100644 --- a/config/routes/public.php +++ b/config/routes/public.php @@ -6,25 +6,25 @@ use Slim\App; use Slim\Routing\RouteCollectorProxy; return function (App $app) { + $app->group( + '/public/{station_id}', + function (RouteCollectorProxy $group) { + $group->get('[/{embed:embed}]', Controller\Frontend\PublicPages\PlayerAction::class) + ->setName('public:index'); - $app->group('/public/{station_id}', function (RouteCollectorProxy $group) { + $group->get('/embed-requests', Controller\Frontend\PublicPages\RequestsAction::class) + ->setName('public:embedrequests'); - $group->get('[/{embed:embed}]', Controller\Frontend\PublicPages\PlayerAction::class) - ->setName('public:index'); + $group->get('/playlist[.{format}]', Controller\Frontend\PublicPages\PlaylistAction::class) + ->setName('public:playlist'); - $group->get('/embed-requests', Controller\Frontend\PublicPages\RequestsAction::class) - ->setName('public:embedrequests'); + $group->get('/dj', Controller\Frontend\PublicPages\WebDjAction::class) + ->setName('public:dj'); - $group->get('/playlist[.{format}]', Controller\Frontend\PublicPages\PlaylistAction::class) - ->setName('public:playlist'); - - $group->get('/dj', Controller\Frontend\PublicPages\WebDjAction::class) - ->setName('public:dj'); - - $group->get('/ondemand[/{embed:embed}]', Controller\Frontend\PublicPages\OnDemandAction::class) - ->setName('public:ondemand'); - - }) + $group->get('/ondemand[/{embed:embed}]', Controller\Frontend\PublicPages\OnDemandAction::class) + ->setName('public:ondemand'); + } + ) ->add(Middleware\GetStation::class) ->add(Middleware\EnableView::class); }; diff --git a/config/routes/stations.php b/config/routes/stations.php index 7c8116c12..90f0a027e 100644 --- a/config/routes/stations.php +++ b/config/routes/stations.php @@ -9,179 +9,224 @@ use Slim\App; use Slim\Routing\RouteCollectorProxy; return function (App $app) { + $app->group( + '/station/{station_id}', + function (RouteCollectorProxy $group) { + $group->get( + '', + function (ServerRequest $request, Response $response) { + return $response->withRedirect( + (string)$request->getRouter()->fromHere('stations:profile:index') + ); + } + )->setName('stations:index:index'); - $app->group('/station/{station_id}', function (RouteCollectorProxy $group) { + $group->group( + '/automation', + function (RouteCollectorProxy $group) { + $group->map(['GET', 'POST'], '', Controller\Stations\AutomationController::class . ':indexAction') + ->setName('stations:automation:index'); - $group->get('', function (ServerRequest $request, Response $response) { - return $response->withRedirect((string)$request->getRouter()->fromHere('stations:profile:index')); - })->setName('stations:index:index'); + $group->get('/run', Controller\Stations\AutomationController::class . ':runAction') + ->setName('stations:automation:run'); + } + )->add(new Middleware\Permissions(Acl::STATION_AUTOMATION, true)); - $group->group('/automation', function (RouteCollectorProxy $group) { + $group->get('/files', Controller\Stations\FilesController::class) + ->setName('stations:files:index') + ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); - $group->map(['GET', 'POST'], '', Controller\Stations\AutomationController::class . ':indexAction') - ->setName('stations:automation:index'); + $group->map(['GET', 'POST'], '/ls_config', Controller\Stations\EditLiquidsoapConfigController::class) + ->setName('stations:util:ls_config') + ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); - $group->get('/run', Controller\Stations\AutomationController::class . ':runAction') - ->setName('stations:automation:run'); + $group->group( + '/logs', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Stations\LogsController::class) + ->setName('stations:logs:index'); - })->add(new Middleware\Permissions(Acl::STATION_AUTOMATION, true)); + $group->get('/view/{log}', Controller\Stations\LogsController::class . ':viewAction') + ->setName('stations:logs:view'); + } + )->add(new Middleware\Permissions(Acl::STATION_LOGS, true)); - $group->get('/files', Controller\Stations\FilesController::class) - ->setName('stations:files:index') - ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); + $group->get('/playlists', Controller\Stations\PlaylistsController::class) + ->setName('stations:playlists:index') + ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); - $group->map(['GET', 'POST'], '/ls_config', Controller\Stations\EditLiquidsoapConfigController::class) - ->setName('stations:util:ls_config') - ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); + $group->group( + '/mounts', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Stations\MountsController::class . ':indexAction') + ->setName('stations:mounts:index'); - $group->group('/logs', function (RouteCollectorProxy $group) { + $group->map( + ['GET', 'POST'], + '/edit/{id}', + Controller\Stations\MountsController::class . ':editAction' + ) + ->setName('stations:mounts:edit'); - $group->get('', Controller\Stations\LogsController::class) - ->setName('stations:logs:index'); + $group->map(['GET', 'POST'], '/add', Controller\Stations\MountsController::class . ':editAction') + ->setName('stations:mounts:add'); - $group->get('/view/{log}', Controller\Stations\LogsController::class . ':viewAction') - ->setName('stations:logs:view'); + $group->get('/delete/{id}/{csrf}', Controller\Stations\MountsController::class . ':deleteAction') + ->setName('stations:mounts:delete'); + } + )->add(new Middleware\Permissions(Acl::STATION_MOUNTS, true)); - })->add(new Middleware\Permissions(Acl::STATION_LOGS, true)); + $group->get('/profile', Controller\Stations\ProfileController::class) + ->setName('stations:profile:index'); - $group->get('/playlists', Controller\Stations\PlaylistsController::class) - ->setName('stations:playlists:index') - ->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); + $group->get( + '/profile/toggle/{feature}/{csrf}', + Controller\Stations\ProfileController::class . ':toggleAction' + ) + ->setName('stations:profile:toggle') + ->add(new Middleware\Permissions(Acl::STATION_PROFILE, true)); - $group->group('/mounts', function (RouteCollectorProxy $group) { + $group->map(['GET', 'POST'], '/profile/edit', Controller\Stations\ProfileController::class . ':editAction') + ->setName('stations:profile:edit') + ->add(new Middleware\Permissions(Acl::STATION_PROFILE, true)); - $group->get('', Controller\Stations\MountsController::class . ':indexAction') - ->setName('stations:mounts:index'); + $group->get('/queue', Controller\Stations\QueueController::class) + ->setName('stations:queue:index') + ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); - $group->map(['GET', 'POST'], '/edit/{id}', Controller\Stations\MountsController::class . ':editAction') - ->setName('stations:mounts:edit'); + $group->group( + '/remotes', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Stations\RemotesController::class . ':indexAction') + ->setName('stations:remotes:index'); - $group->map(['GET', 'POST'], '/add', Controller\Stations\MountsController::class . ':editAction') - ->setName('stations:mounts:add'); + $group->map( + ['GET', 'POST'], + '/edit/{id}', + Controller\Stations\RemotesController::class . ':editAction' + ) + ->setName('stations:remotes:edit'); - $group->get('/delete/{id}/{csrf}', Controller\Stations\MountsController::class . ':deleteAction') - ->setName('stations:mounts:delete'); + $group->map(['GET', 'POST'], '/add', Controller\Stations\RemotesController::class . ':editAction') + ->setName('stations:remotes:add'); - })->add(new Middleware\Permissions(Acl::STATION_MOUNTS, true)); + $group->get('/delete/{id}/{csrf}', Controller\Stations\RemotesController::class . ':deleteAction') + ->setName('stations:remotes:delete'); + } + )->add(new Middleware\Permissions(Acl::STATION_REMOTES, true)); - $group->get('/profile', Controller\Stations\ProfileController::class) - ->setName('stations:profile:index'); + $group->group( + '/reports', + function (RouteCollectorProxy $group) { + $group->get('/overview', Controller\Stations\Reports\OverviewController::class) + ->setName('stations:reports:overview'); - $group->get('/profile/toggle/{feature}/{csrf}', Controller\Stations\ProfileController::class . ':toggleAction') - ->setName('stations:profile:toggle') - ->add(new Middleware\Permissions(Acl::STATION_PROFILE, true)); + $group->get('/timeline[/format/{format}]', Controller\Stations\Reports\TimelineController::class) + ->setName('stations:reports:timeline'); - $group->map(['GET', 'POST'], '/profile/edit', Controller\Stations\ProfileController::class . ':editAction') - ->setName('stations:profile:edit') - ->add(new Middleware\Permissions(Acl::STATION_PROFILE, true)); + $group->get( + '/performance[/format/{format}]', + Controller\Stations\Reports\PerformanceController::class + ) + ->setName('stations:reports:performance'); - $group->get('/queue', Controller\Stations\QueueController::class) - ->setName('stations:queue:index') - ->add(new Middleware\Permissions(Acl::STATION_BROADCASTING, true)); + $group->get('/duplicates', Controller\Stations\Reports\DuplicatesController::class) + ->setName('stations:reports:duplicates'); - $group->group('/remotes', function (RouteCollectorProxy $group) { + $group->get( + '/duplicates/delete/{media_id}', + Controller\Stations\Reports\DuplicatesController::class . ':deleteAction' + ) + ->setName('stations:reports:duplicates:delete'); - $group->get('', Controller\Stations\RemotesController::class . ':indexAction') - ->setName('stations:remotes:index'); + $group->map(['GET', 'POST'], '/listeners', Controller\Stations\Reports\ListenersController::class) + ->setName('stations:reports:listeners'); - $group->map(['GET', 'POST'], '/edit/{id}', Controller\Stations\RemotesController::class . ':editAction') - ->setName('stations:remotes:edit'); + $group->map( + ['GET', 'POST'], + '/soundexchange', + Controller\Stations\Reports\SoundExchangeController::class + ) + ->setName('stations:reports:soundexchange'); - $group->map(['GET', 'POST'], '/add', Controller\Stations\RemotesController::class . ':editAction') - ->setName('stations:remotes:add'); + $group->get('/requests', Controller\Stations\Reports\RequestsController::class) + ->setName('stations:reports:requests'); - $group->get('/delete/{id}/{csrf}', Controller\Stations\RemotesController::class . ':deleteAction') - ->setName('stations:remotes:delete'); + $group->get( + '/requests/delete/{request_id}/{csrf}', + Controller\Stations\Reports\RequestsController::class . ':deleteAction' + ) + ->setName('stations:reports:requests:delete'); - })->add(new Middleware\Permissions(Acl::STATION_REMOTES, true)); + $group->get( + '/requests/clear/{csrf}', + Controller\Stations\Reports\RequestsController::class . ':clearAction' + ) + ->setName('stations:reports:requests:clear'); + } + )->add(new Middleware\Permissions(Acl::STATION_REPORTS, true)); - $group->group('/reports', function (RouteCollectorProxy $group) { + $group->group( + '/sftp_users', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Stations\SftpUsersController::class . ':indexAction') + ->setName('stations:sftp_users:index'); - $group->get('/overview', Controller\Stations\Reports\OverviewController::class) - ->setName('stations:reports:overview'); + $group->map( + ['GET', 'POST'], + '/edit/{id}', + Controller\Stations\SftpUsersController::class . ':editAction' + ) + ->setName('stations:sftp_users:edit'); - $group->get('/timeline[/format/{format}]', Controller\Stations\Reports\TimelineController::class) - ->setName('stations:reports:timeline'); + $group->map(['GET', 'POST'], '/add', Controller\Stations\SftpUsersController::class . ':editAction') + ->setName('stations:sftp_users:add'); - $group->get('/performance[/format/{format}]', Controller\Stations\Reports\PerformanceController::class) - ->setName('stations:reports:performance'); + $group->get('/delete/{id}/{csrf}', Controller\Stations\SftpUsersController::class . ':deleteAction') + ->setName('stations:sftp_users:delete'); + } + )->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); - $group->get('/duplicates', Controller\Stations\Reports\DuplicatesController::class) - ->setName('stations:reports:duplicates'); + $group->get('/streamers', Controller\Stations\StreamersController::class) + ->setName('stations:streamers:index') + ->add(new Middleware\Permissions(Acl::STATION_STREAMERS, true)); - $group->get('/duplicates/delete/{media_id}', - Controller\Stations\Reports\DuplicatesController::class . ':deleteAction') - ->setName('stations:reports:duplicates:delete'); + $group->group( + '/webhooks', + function (RouteCollectorProxy $group) { + $group->get('', Controller\Stations\WebhooksController::class . ':indexAction') + ->setName('stations:webhooks:index'); - $group->map(['GET', 'POST'], '/listeners', Controller\Stations\Reports\ListenersController::class) - ->setName('stations:reports:listeners'); + $group->map( + ['GET', 'POST'], + '/edit/{id}', + Controller\Stations\WebhooksController::class . ':editAction' + ) + ->setName('stations:webhooks:edit'); - $group->map(['GET', 'POST'], '/soundexchange', Controller\Stations\Reports\SoundExchangeController::class) - ->setName('stations:reports:soundexchange'); + $group->map( + ['GET', 'POST'], + '/add[/{type}]', + Controller\Stations\WebhooksController::class . ':addAction' + ) + ->setName('stations:webhooks:add'); - $group->get('/requests', Controller\Stations\Reports\RequestsController::class) - ->setName('stations:reports:requests'); + $group->get('/toggle/{id}/{csrf}', Controller\Stations\WebhooksController::class . ':toggleAction') + ->setName('stations:webhooks:toggle'); - $group->get('/requests/delete/{request_id}/{csrf}', - Controller\Stations\Reports\RequestsController::class . ':deleteAction') - ->setName('stations:reports:requests:delete'); + $group->get('/test/{id}/{csrf}', Controller\Stations\WebhooksController::class . ':testAction') + ->setName('stations:webhooks:test'); - $group->get('/requests/clear/{csrf}', - Controller\Stations\Reports\RequestsController::class . ':clearAction') - ->setName('stations:reports:requests:clear'); - - })->add(new Middleware\Permissions(Acl::STATION_REPORTS, true)); - - $group->group('/sftp_users', function (RouteCollectorProxy $group) { - - $group->get('', Controller\Stations\SftpUsersController::class . ':indexAction') - ->setName('stations:sftp_users:index'); - - $group->map(['GET', 'POST'], '/edit/{id}', Controller\Stations\SftpUsersController::class . ':editAction') - ->setName('stations:sftp_users:edit'); - - $group->map(['GET', 'POST'], '/add', Controller\Stations\SftpUsersController::class . ':editAction') - ->setName('stations:sftp_users:add'); - - $group->get('/delete/{id}/{csrf}', Controller\Stations\SftpUsersController::class . ':deleteAction') - ->setName('stations:sftp_users:delete'); - - })->add(new Middleware\Permissions(Acl::STATION_MEDIA, true)); - - $group->get('/streamers', Controller\Stations\StreamersController::class) - ->setName('stations:streamers:index') - ->add(new Middleware\Permissions(Acl::STATION_STREAMERS, true)); - - $group->group('/webhooks', function (RouteCollectorProxy $group) { - - $group->get('', Controller\Stations\WebhooksController::class . ':indexAction') - ->setName('stations:webhooks:index'); - - $group->map(['GET', 'POST'], '/edit/{id}', Controller\Stations\WebhooksController::class . ':editAction') - ->setName('stations:webhooks:edit'); - - $group->map(['GET', 'POST'], '/add[/{type}]', Controller\Stations\WebhooksController::class . ':addAction') - ->setName('stations:webhooks:add'); - - $group->get('/toggle/{id}/{csrf}', Controller\Stations\WebhooksController::class . ':toggleAction') - ->setName('stations:webhooks:toggle'); - - $group->get('/test/{id}/{csrf}', Controller\Stations\WebhooksController::class . ':testAction') - ->setName('stations:webhooks:test'); - - $group->get('/delete/{id}/{csrf}', Controller\Stations\WebhooksController::class . ':deleteAction') - ->setName('stations:webhooks:delete'); - - })->add(new Middleware\Permissions(Acl::STATION_WEB_HOOKS, true)); - - // END /stations GROUP - - }) + $group->get('/delete/{id}/{csrf}', Controller\Stations\WebhooksController::class . ':deleteAction') + ->setName('stations:webhooks:delete'); + } + )->add(new Middleware\Permissions(Acl::STATION_WEB_HOOKS, true)); + } + ) ->add(Middleware\Module\Stations::class) ->add(new Middleware\Permissions(Acl::STATION_VIEW, true)) ->add(Middleware\RequireStation::class) ->add(Middleware\GetStation::class) ->add(Middleware\EnableView::class) ->add(Middleware\RequireLogin::class); - -}; \ No newline at end of file +}; diff --git a/frontend/vue/StationMedia.vue b/frontend/vue/StationMedia.vue index da37bddc2..ca19d8a7d 100644 --- a/frontend/vue/StationMedia.vue +++ b/frontend/vue/StationMedia.vue @@ -38,14 +38,19 @@ {{ row.item.text }} -