Massive API & WebUI changes.
This commit is contained in:
64
src/API/Backend/AccessToken.php
Normal file
64
src/API/Backend/AccessToken.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\API\Backend;
|
||||
|
||||
use App\Libs\Attributes\Route\Post;
|
||||
use App\Libs\DataUtil;
|
||||
use App\Libs\Exceptions\InvalidArgumentException;
|
||||
use App\Libs\HTTP_STATUS;
|
||||
use App\Libs\Traits\APITraits;
|
||||
use Psr\Http\Message\ResponseInterface as iResponse;
|
||||
use Psr\Http\Message\ServerRequestInterface as iRequest;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface as iHttp;
|
||||
use Throwable;
|
||||
|
||||
final class AccessToken
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
public function __construct(private readonly iHttp $http)
|
||||
{
|
||||
}
|
||||
|
||||
#[Post(Index::URL . '/{name:backend}/accesstoken[/]', name: 'backend.accesstoken')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$data = DataUtil::fromArray($request->getParsedBody());
|
||||
|
||||
if (null === ($id = $data->get('id'))) {
|
||||
return api_error('No id was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$client = $this->getClient(name: $name);
|
||||
$token = $client->getUserToken(
|
||||
userId: $id,
|
||||
username: $data->get('username', $client->getContext()->backendName . '_user'),
|
||||
);
|
||||
|
||||
if (!is_string($token)) {
|
||||
return api_error('Failed to generate access token.', HTTP_STATUS::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$arr = [
|
||||
'token' => $token,
|
||||
];
|
||||
|
||||
if ($data->get('username')) {
|
||||
$arr['username'] = $data->get('username');
|
||||
}
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $arr);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
} catch (Throwable $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
49
src/API/Backend/Discover.php
Normal file
49
src/API/Backend/Discover.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\API\Backend;
|
||||
|
||||
use App\Backends\Plex\PlexClient;
|
||||
use App\Libs\Attributes\Route\Get;
|
||||
use App\Libs\Exceptions\InvalidArgumentException;
|
||||
use App\Libs\HTTP_STATUS;
|
||||
use App\Libs\Traits\APITraits;
|
||||
use Psr\Http\Message\ResponseInterface as iResponse;
|
||||
use Psr\Http\Message\ServerRequestInterface as iRequest;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface as iHttp;
|
||||
use Throwable;
|
||||
|
||||
final class Discover
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
public function __construct(private readonly iHttp $http)
|
||||
{
|
||||
}
|
||||
|
||||
#[Get(Index::URL . '/{name:backend}/discover[/]', name: 'backend.discover')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$client = $this->getClient(name: $name);
|
||||
|
||||
if (PlexClient::CLIENT_NAME !== $client->getType()) {
|
||||
return api_error('Discover is only available for Plex backends.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
assert($client instanceof PlexClient);
|
||||
|
||||
$list = $client::discover($this->http, $client->getContext()->backendToken);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, ag($list, 'list', []));
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
} catch (Throwable $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,11 +27,11 @@ final class Ignore
|
||||
$this->file = new ConfigFile(Config::get('path') . '/config/ignore.yaml', type: 'yaml', autoCreate: true);
|
||||
}
|
||||
|
||||
#[Get(Index::URL . '/{name:backend}/ignore[/]', name: 'backends.backend.ignoredIds')]
|
||||
#[Get(Index::URL . '/{name:backend}/ignore[/]', name: 'backend.ignoredIds')]
|
||||
public function ignoredIds(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('No backend was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$list = [];
|
||||
@@ -61,22 +61,23 @@ final class Ignore
|
||||
'created' => makeDate($date),
|
||||
];
|
||||
}
|
||||
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
|
||||
|
||||
$response = [
|
||||
'ignore' => $list,
|
||||
'links' => [
|
||||
'self' => (string)$apiUrl,
|
||||
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
|
||||
],
|
||||
];
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $response);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $list);
|
||||
}
|
||||
|
||||
#[Delete(Index::URL . '/{name:backend}/ignore[/]', name: 'backends.backend.ignoredIds.delete')]
|
||||
#[Delete(Index::URL . '/{name:backend}/ignore[/]', name: 'backend.ignoredIds.delete')]
|
||||
public function deleteRule(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$data = $this->getBackends(name: $name);
|
||||
|
||||
if (empty($data)) {
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$params = DataUtil::fromRequest($request);
|
||||
|
||||
if (null === ($rule = $params->get('rule'))) {
|
||||
@@ -98,11 +99,11 @@ final class Ignore
|
||||
return api_response(HTTP_STATUS::HTTP_OK);
|
||||
}
|
||||
|
||||
#[Post(Index::URL . '/{name:backend}/ignore[/]', name: 'backends.backend.ignoredIds.add')]
|
||||
#[Post(Index::URL . '/{name:backend}/ignore[/]', name: 'backend.ignoredIds.add')]
|
||||
public function addRule(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('No backend was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$data = $this->getBackends(name: $name);
|
||||
|
||||
@@ -16,11 +16,11 @@ final class Index
|
||||
|
||||
public const string URL = '%{api.prefix}/backend';
|
||||
|
||||
#[Get(self::URL . '/{name:backend}[/]', name: 'backends.view')]
|
||||
#[Get(self::URL . '/{name:backend}[/]', name: 'backend.view')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$data = $this->getBackends(name: $name);
|
||||
@@ -29,17 +29,8 @@ final class Index
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
|
||||
$data = array_pop($data);
|
||||
|
||||
$response = [
|
||||
...$data,
|
||||
'links' => [
|
||||
'self' => (string)$apiUrl,
|
||||
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
|
||||
],
|
||||
];
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, ['backend' => $response]);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ final class Info
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
#[Get(Index::URL . '/{name:backend}/info[/]', name: 'backends.backend.info')]
|
||||
public function backendsView(iRequest $request, array $args = []): iResponse
|
||||
#[Get(Index::URL . '/{name:backend}/info[/]', name: 'backend.info')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -40,20 +40,9 @@ final class Info
|
||||
|
||||
try {
|
||||
$data = $client->getInfo($opts);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $data);
|
||||
} catch (Throwable $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
|
||||
|
||||
$response = [
|
||||
'data' => $data,
|
||||
'links' => [
|
||||
'self' => (string)$apiUrl,
|
||||
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
|
||||
],
|
||||
];
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,32 +2,51 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\API\Backend\Library;
|
||||
namespace App\API\Backend;
|
||||
|
||||
use App\API\Backend\Index as BackendsIndex;
|
||||
use App\Libs\Attributes\Route\Get;
|
||||
use App\Libs\Attributes\Route\Route;
|
||||
use App\Libs\Config;
|
||||
use App\Libs\ConfigFile;
|
||||
use App\Libs\DataUtil;
|
||||
use App\Libs\Exceptions\RuntimeException;
|
||||
use App\Libs\HTTP_STATUS;
|
||||
use App\Libs\Options;
|
||||
use App\Libs\Traits\APITraits;
|
||||
use Psr\Http\Message\ResponseInterface as iResponse;
|
||||
use Psr\Http\Message\ServerRequestInterface as iRequest;
|
||||
use Throwable;
|
||||
|
||||
final class Ignore
|
||||
final class Library
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
#[Route(['POST', 'DELETE'], BackendsIndex::URL . '/{name:backend}/library[/]', name: 'backends.library.ignore')]
|
||||
public function _invoke(iRequest $request, array $args = []): iResponse
|
||||
#[Get(BackendsIndex::URL . '/{name:backend}/library[/]', name: 'backend.library')]
|
||||
public function listLibraries(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('No backend was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (null === ($id = DataUtil::fromRequest($request, true)->get('id', null))) {
|
||||
return api_error('No library id was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
try {
|
||||
$client = $this->getClient(name: $name);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $client->listLibraries());
|
||||
} catch (RuntimeException $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
} catch (Throwable $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
#[Route(['POST', 'DELETE'], BackendsIndex::URL . '/{name:backend}/library/{id}[/]', name: 'backend.library.ignore')]
|
||||
public function ignoreLibrary(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (null === ($id = ag($args, 'id'))) {
|
||||
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$remove = 'DELETE' === $request->getMethod();
|
||||
@@ -75,13 +94,6 @@ final class Ignore
|
||||
|
||||
$config->set("{$name}.options." . Options::IGNORE, implode(',', array_values($ignoreIds)))->persist();
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, [
|
||||
'type' => $config->get("{$name}.type"),
|
||||
'libraries' => $libraries,
|
||||
'links' => [
|
||||
'self' => (string)parseConfigValue(BackendsIndex::URL . "/{$name}/library"),
|
||||
'backend' => (string)parseConfigValue(BackendsIndex::URL . "/{$name}"),
|
||||
],
|
||||
]);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $libraries);
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\API\Backend\Library;
|
||||
|
||||
use App\API\Backend\Index as BackendsIndex;
|
||||
use App\Libs\Attributes\Route\Get;
|
||||
use App\Libs\Config;
|
||||
use App\Libs\Exceptions\RuntimeException;
|
||||
use App\Libs\HTTP_STATUS;
|
||||
use App\Libs\Traits\APITraits;
|
||||
use Psr\Http\Message\ResponseInterface as iResponse;
|
||||
use Psr\Http\Message\ServerRequestInterface as iRequest;
|
||||
|
||||
final class Index
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
#[Get(BackendsIndex::URL . '/{name:backend}/library[/]', name: 'backends.library.list')]
|
||||
public function listLibraries(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('No backend was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$client = $this->getClient(name: $name);
|
||||
} catch (RuntimeException $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$response = [
|
||||
'type' => ag(array_flip(Config::get('supported')), $client::class),
|
||||
'libraries' => $client->listLibraries(),
|
||||
'links' => [
|
||||
'self' => (string)$request->getUri()->withHost('')->withPort(0)->withScheme(''),
|
||||
'backend' => (string)parseConfigValue(BackendsIndex::URL . "/{$name}"),
|
||||
],
|
||||
];
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $response);
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\API\Backend\Library;
|
||||
namespace App\API\Backend;
|
||||
|
||||
use App\API\Backend\Index as BackendsIndex;
|
||||
use App\API\Backend\Index as backendIndex;
|
||||
use App\Commands\Backend\Library\MismatchCommand;
|
||||
use App\Libs\Attributes\Route\Get;
|
||||
use App\Libs\DataUtil;
|
||||
@@ -19,11 +19,11 @@ final class Mismatched
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
#[Get(BackendsIndex::URL . '/{name:backend}/mismatched[/[{id}[/]]]', name: 'backends.library.mismatched')]
|
||||
public function listLibraries(iRequest $request, array $args = []): iResponse
|
||||
#[Get(backendIndex::URL . '/{name:backend}/mismatched[/[{id}[/]]]', name: 'backend.mismatched')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('No backend was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$params = DataUtil::fromArray($request->getQueryParams());
|
||||
@@ -74,15 +74,6 @@ final class Mismatched
|
||||
$list[] = $processed;
|
||||
}
|
||||
}
|
||||
|
||||
$response = [
|
||||
'items' => $list,
|
||||
'links' => [
|
||||
'self' => (string)$request->getUri()->withHost('')->withPort(0)->withScheme(''),
|
||||
'backend' => (string)parseConfigValue(BackendsIndex::URL . "/{$name}"),
|
||||
],
|
||||
];
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $response);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $list);
|
||||
}
|
||||
}
|
||||
171
src/API/Backend/Option.php
Normal file
171
src/API/Backend/Option.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\API\Backend;
|
||||
|
||||
use App\Libs\Attributes\Route\Delete;
|
||||
use App\Libs\Attributes\Route\Get;
|
||||
use App\Libs\Attributes\Route\Patch;
|
||||
use App\Libs\Attributes\Route\Post;
|
||||
use App\Libs\Config;
|
||||
use App\Libs\ConfigFile;
|
||||
use App\Libs\DataUtil;
|
||||
use App\Libs\HTTP_STATUS;
|
||||
use App\Libs\Traits\APITraits;
|
||||
use Psr\Http\Message\ResponseInterface as iResponse;
|
||||
use Psr\Http\Message\ServerRequestInterface as iRequest;
|
||||
|
||||
final class Option
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
#[Get(Index::URL . '/{name:backend}/option/{option}[/]', name: 'backend.option')]
|
||||
public function viewOption(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (null === ($option = ag($args, 'option'))) {
|
||||
return api_error('Invalid value for option path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$list = ConfigFile::open(Config::get('backends_file'), 'yaml', autoCreate: true);
|
||||
|
||||
if (false === $list->has($name)) {
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key = $name . '.options.' . $option;
|
||||
|
||||
if (false === $list->has($key)) {
|
||||
return api_error(r("Option '{option}' not found in backend '{name}'.", [
|
||||
'option' => $option,
|
||||
'name' => $name
|
||||
]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$value = $list->get($key);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, [
|
||||
'key' => $option,
|
||||
'value' => $value,
|
||||
'type' => get_debug_type($value),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Post(Index::URL . '/{name:backend}/option[/]', name: 'backend.option.add')]
|
||||
public function addOption(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$list = ConfigFile::open(Config::get('backends_file'), 'yaml', autoCreate: true);
|
||||
|
||||
if (false === $list->has($name)) {
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$data = DataUtil::fromRequest($request);
|
||||
|
||||
if (null === ($option = $data->get('key'))) {
|
||||
return api_error('Invalid value for key.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$spec = require __DIR__ . '/../../../config/backend.spec.php';
|
||||
$found = false;
|
||||
|
||||
foreach ($spec as $supportedKey => $_) {
|
||||
if (str_ends_with($supportedKey, 'options.' . $option)) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (false === $found) {
|
||||
return api_error(r("Option '{key}' is not supported.", ['key' => $option]), HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$value = $data->get('value');
|
||||
|
||||
$list->set($name . '.options.' . $option, $value)->persist();
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, [
|
||||
'key' => $option,
|
||||
'value' => $value,
|
||||
'type' => get_debug_type($value),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Patch(Index::URL . '/{name:backend}/option/{option}[/]', name: 'backend.option.update')]
|
||||
public function updateOption(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (null === ($option = ag($args, 'option'))) {
|
||||
return api_error('Invalid value for option parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$list = ConfigFile::open(Config::get('backends_file'), 'yaml', autoCreate: true);
|
||||
|
||||
if (false === $list->has($name)) {
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key = $name . '.options.' . $option;
|
||||
if (false === $list->has($key)) {
|
||||
return api_error(r("Option '{option}' not found in backend '{name}'.", [
|
||||
'option' => $option,
|
||||
'name' => $name
|
||||
]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$data = DataUtil::fromRequest($request);
|
||||
|
||||
if (null === ($value = $data->get('value'))) {
|
||||
return api_error(r("No value was provided for '{key}'.", [
|
||||
'key' => $key,
|
||||
]), HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$list->set($key, $value)->persist();
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, [
|
||||
'key' => $option,
|
||||
'value' => $value,
|
||||
'type' => get_debug_type($value),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Delete(Index::URL . '/{name:backend}/option/{option}[/]', name: 'backend.option.delete')]
|
||||
public function deleteOption(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (null === ($option = ag($args, 'option'))) {
|
||||
return api_error('Invalid value for option option parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$list = ConfigFile::open(Config::get('backends_file'), 'yaml', autoCreate: true);
|
||||
|
||||
if (false === $list->has($name)) {
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$key = $name . '.options.' . $option;
|
||||
|
||||
$value = $list->get($key);
|
||||
$list->delete($key)->persist();
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, [
|
||||
'key' => $option,
|
||||
'value' => $value,
|
||||
'type' => get_debug_type($value),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\API\Backend;
|
||||
|
||||
use App\Libs\Attributes\Route\Patch;
|
||||
use App\Libs\Config;
|
||||
use App\Libs\ConfigFile;
|
||||
use App\Libs\HTTP_STATUS;
|
||||
use App\Libs\Traits\APITraits;
|
||||
use JsonException;
|
||||
use Psr\Http\Message\ResponseInterface as iResponse;
|
||||
use Psr\Http\Message\ServerRequestInterface as iRequest;
|
||||
|
||||
final class PartialUpdate
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
#[Patch(Index::URL . '/{name:backend}[/]', name: 'backends.view')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$list = ConfigFile::open(Config::get('backends_file'), 'yaml', autoCreate: true);
|
||||
|
||||
if (false === $list->has($name)) {
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
try {
|
||||
$data = json_decode((string)$request->getBody(), true, flags: JSON_THROW_ON_ERROR);
|
||||
} catch (JsonException $e) {
|
||||
return api_error(r('Invalid JSON data. {error}', ['error' => $e->getMessage()]),
|
||||
HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
foreach ($data as $update) {
|
||||
if (!ag_exists($update, 'key')) {
|
||||
return api_error('No key to update was present.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$list->set($name . '.' . ag($update, 'key'), ag($update, 'value'));
|
||||
}
|
||||
|
||||
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
|
||||
|
||||
$list->persist();
|
||||
|
||||
$backend = $this->getBackends(name: $name);
|
||||
|
||||
if (empty($backend)) {
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
$backend = array_pop($backend);
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, [
|
||||
'backend' => array_filter(
|
||||
$backend,
|
||||
fn($key) => false === in_array($key, ['options', 'webhook'], true),
|
||||
ARRAY_FILTER_USE_KEY
|
||||
),
|
||||
'links' => [
|
||||
'self' => (string)$apiUrl,
|
||||
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ final class Search
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
#[Get(Index::URL . '/{name:backend}/search[/[{id}[/]]]', name: 'backends.backend.search.id')]
|
||||
public function searchById(iRequest $request, array $args = []): iResponse
|
||||
#[Get(Index::URL . '/{name:backend}/search[/[{id}[/]]]', name: 'backend.search')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
@@ -55,14 +55,8 @@ final class Search
|
||||
]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
|
||||
$response = [
|
||||
'results' => $id ? [$data] : $data,
|
||||
'links' => [
|
||||
'self' => (string)$apiUrl,
|
||||
'backend' => (string)$apiUrl->withPath(parseConfigValue(Index::URL . '/' . $name)),
|
||||
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
|
||||
],
|
||||
'options' => [
|
||||
'raw' => (bool)$params->get('raw', false),
|
||||
],
|
||||
|
||||
@@ -18,11 +18,11 @@ final class Sessions
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
#[Get(Index::URL . '/{name:backend}/sessions[/]', name: 'backends.backend.sessions')]
|
||||
public function backendsView(iRequest $request, array $args = []): iResponse
|
||||
#[Get(Index::URL . '/{name:backend}/sessions[/]', name: 'backend.sessions')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -40,20 +40,9 @@ final class Sessions
|
||||
|
||||
try {
|
||||
$sessions = $client->getSessions($opts);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, ag($sessions, 'sessions', []));
|
||||
} catch (Throwable $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
|
||||
|
||||
$response = [
|
||||
'sessions' => ag($sessions, 'sessions', []),
|
||||
'links' => [
|
||||
'self' => (string)$apiUrl,
|
||||
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
|
||||
],
|
||||
];
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\API\Backend\Library;
|
||||
namespace App\API\Backend;
|
||||
|
||||
use App\API\Backend\Index as BackendsIndex;
|
||||
use App\API\Backend\Index as backendIndex;
|
||||
use App\Libs\Attributes\Route\Get;
|
||||
use App\Libs\DataUtil;
|
||||
use App\Libs\Exceptions\RuntimeException;
|
||||
@@ -18,11 +18,11 @@ final class Unmatched
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
#[Get(BackendsIndex::URL . '/{name:backend}/unmatched[/[{id}[/]]]', name: 'backends.library.unmatched')]
|
||||
public function listLibraries(iRequest $request, array $args = []): iResponse
|
||||
#[Get(backendIndex::URL . '/{name:backend}/unmatched[/[{id}[/]]]', name: 'backend.unmatched')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('No backend was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$params = DataUtil::fromArray($request->getQueryParams());
|
||||
@@ -63,14 +63,6 @@ final class Unmatched
|
||||
}
|
||||
}
|
||||
|
||||
$response = [
|
||||
'items' => $list,
|
||||
'links' => [
|
||||
'self' => (string)$request->getUri()->withHost('')->withPort(0)->withScheme(''),
|
||||
'backend' => (string)parseConfigValue(BackendsIndex::URL . "/{$name}"),
|
||||
],
|
||||
];
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $response);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $list);
|
||||
}
|
||||
}
|
||||
144
src/API/Backend/Update.php
Normal file
144
src/API/Backend/Update.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\API\Backend;
|
||||
|
||||
use App\Backends\Common\ClientInterface as iClient;
|
||||
use App\Libs\Attributes\Route\Patch;
|
||||
use App\Libs\Attributes\Route\Put;
|
||||
use App\Libs\Config;
|
||||
use App\Libs\ConfigFile;
|
||||
use App\Libs\DataUtil;
|
||||
use App\Libs\HTTP_STATUS;
|
||||
use App\Libs\Options;
|
||||
use App\Libs\Traits\APITraits;
|
||||
use JsonException;
|
||||
use Psr\Http\Message\ResponseInterface as iResponse;
|
||||
use Psr\Http\Message\ServerRequestInterface as iRequest;
|
||||
|
||||
final class Update
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
private ConfigFile $backendFile;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->backendFile = ConfigFile::open(Config::get('backends_file'), 'yaml', autoCreate: true);
|
||||
}
|
||||
|
||||
#[Put(Index::URL . '/{name:backend}[/]', name: 'backend.update')]
|
||||
public function update(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (false === $this->backendFile->has($name)) {
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$this->backendFile->set(
|
||||
$name,
|
||||
$this->fromRequest($this->backendFile->get($name), $request, $this->getClient($name))
|
||||
)->persist();
|
||||
|
||||
$backend = $this->getBackends(name: $name);
|
||||
|
||||
if (empty($backend)) {
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$backend = array_pop($backend);
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $backend);
|
||||
}
|
||||
|
||||
#[Patch(Index::URL . '/{name:backend}[/]', name: 'backend.patch')]
|
||||
public function patchUpdate(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (false === $this->backendFile->has($name)) {
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
try {
|
||||
$data = json_decode((string)$request->getBody(), true, flags: JSON_THROW_ON_ERROR);
|
||||
} catch (JsonException $e) {
|
||||
return api_error(r('Invalid JSON data. {error}', ['error' => $e->getMessage()]),
|
||||
HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$spec = require __DIR__ . '/../../../config/backend.spec.php';
|
||||
|
||||
foreach ($data as $update) {
|
||||
$key = ag($update, 'key');
|
||||
$value = ag($update, 'value');
|
||||
|
||||
if (null === $key) {
|
||||
return api_error('No key to update was present.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (false === in_array($key, $spec, true)) {
|
||||
return api_error(r('Invalid key to update: {key}', ['key' => $key]), HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$this->backendFile->set("{$name}.{$key}", $value);
|
||||
}
|
||||
|
||||
$this->backendFile->persist();
|
||||
|
||||
$backend = $this->getBackends(name: $name);
|
||||
|
||||
if (empty($backend)) {
|
||||
return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$backend = array_pop($backend);
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $backend);
|
||||
}
|
||||
|
||||
private function fromRequest(array $config, iRequest $request, iClient $client): array
|
||||
{
|
||||
$data = DataUtil::fromArray($request->getParsedBody());
|
||||
|
||||
$newData = [
|
||||
'url' => $data->get('url'),
|
||||
'token' => $data->get('token'),
|
||||
'user' => $data->get('user'),
|
||||
'uuid' => $data->get('uuid'),
|
||||
'export' => [
|
||||
'enabled' => (bool)$data->get('export.enabled', false),
|
||||
],
|
||||
'import' => [
|
||||
'enabled' => (bool)$data->get('import.enabled', false),
|
||||
],
|
||||
'webhook' => [
|
||||
'match' => [
|
||||
'user' => (bool)$data->get('webhook.match.user'),
|
||||
'uuid' => (bool)$data->get('webhook.match.uuid'),
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$optionals = [
|
||||
Options::DUMP_PAYLOAD => 'bool',
|
||||
Options::LIBRARY_SEGMENT => 'int',
|
||||
Options::IGNORE => 'string',
|
||||
];
|
||||
|
||||
foreach ($optionals as $key => $type) {
|
||||
if (null !== ($value = $data->get('options.' . $key))) {
|
||||
settype($value, $type);
|
||||
$newData = ag_set($newData, "options.{$key}", $value);
|
||||
}
|
||||
}
|
||||
|
||||
return deepArrayMerge([$config, $client->fromRequest($newData, $request)]);
|
||||
}
|
||||
}
|
||||
@@ -18,19 +18,13 @@ final class Users
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
#[Get(Index::URL . '/{name:backend}/users[/]', name: 'backends.backend.users')]
|
||||
public function backendsView(iRequest $request, array $args = []): iResponse
|
||||
#[Get(Index::URL . '/{name:backend}/users[/]', name: 'backend.users')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$client = $this->getClient(name: $name);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$opts = [];
|
||||
$params = DataUtil::fromRequest($request, true);
|
||||
|
||||
@@ -43,21 +37,11 @@ final class Users
|
||||
}
|
||||
|
||||
try {
|
||||
$users = $client->getUsersList($opts);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $this->getClient(name: $name)->getUsersList($opts));
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
} catch (Throwable $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
|
||||
|
||||
$response = [
|
||||
'users' => $users,
|
||||
'links' => [
|
||||
'self' => (string)$apiUrl,
|
||||
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
|
||||
],
|
||||
];
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,8 @@ declare(strict_types=1);
|
||||
namespace App\API\Backend;
|
||||
|
||||
use App\Libs\Attributes\Route\Get;
|
||||
use App\Libs\DataUtil;
|
||||
use App\Libs\Exceptions\InvalidArgumentException;
|
||||
use App\Libs\HTTP_STATUS;
|
||||
use App\Libs\Options;
|
||||
use App\Libs\Traits\APITraits;
|
||||
use Psr\Http\Message\ResponseInterface as iResponse;
|
||||
use Psr\Http\Message\ServerRequestInterface as iRequest;
|
||||
@@ -18,42 +16,19 @@ final class Version
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
#[Get(Index::URL . '/{name:backend}/version[/]', name: 'backends.backend.info')]
|
||||
public function backendsView(iRequest $request, array $args = []): iResponse
|
||||
#[Get(Index::URL . '/{name:backend}/version[/]', name: 'backend.version')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$client = $this->getClient(name: $name);
|
||||
return api_response(HTTP_STATUS::HTTP_OK, ['version' => $this->getClient(name: $name)->getVersion()]);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$opts = [];
|
||||
$params = DataUtil::fromRequest($request, true);
|
||||
|
||||
if (true === (bool)$params->get('raw', false)) {
|
||||
$opts[Options::RAW_RESPONSE] = true;
|
||||
}
|
||||
|
||||
try {
|
||||
$version = $client->getVersion($opts);
|
||||
} catch (Throwable $e) {
|
||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
|
||||
|
||||
$response = [
|
||||
'version' => $version,
|
||||
'links' => [
|
||||
'self' => (string)$apiUrl,
|
||||
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
|
||||
],
|
||||
];
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK, $response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,20 +27,20 @@ final class Webhooks
|
||||
{
|
||||
use APITraits;
|
||||
|
||||
private iLogger $accessLog;
|
||||
private iLogger $logfile;
|
||||
|
||||
public function __construct(private iCache $cache)
|
||||
{
|
||||
$this->accessLog = new Logger(name: 'http', processors: [new LogMessageProcessor()]);
|
||||
$this->logfile = new Logger(name: 'webhook', processors: [new LogMessageProcessor()]);
|
||||
|
||||
$level = Config::get('webhook.debug') ? Level::Debug : Level::Info;
|
||||
|
||||
if (null !== ($logfile = Config::get('webhook.logfile'))) {
|
||||
$this->accessLog = $this->accessLog->pushHandler(new StreamHandler($logfile, $level, true));
|
||||
$this->logfile = $this->logfile->pushHandler(new StreamHandler($logfile, $level, true));
|
||||
}
|
||||
|
||||
if (true === inContainer()) {
|
||||
$this->accessLog->pushHandler(new StreamHandler('php://stderr', $level, true));
|
||||
$this->logfile->pushHandler(new StreamHandler('php://stderr', $level, true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,13 +53,27 @@ final class Webhooks
|
||||
* @return iResponse The response object.
|
||||
* @throws InvalidArgumentException if cache key is invalid.
|
||||
*/
|
||||
#[Route(['POST', 'PUT'], Index::URL . '/{name:backend}/webhook[/]', name: 'webhooks.receive')]
|
||||
#[Route(['POST', 'PUT'], Index::URL . '/{name:backend}/webhook[/]', name: 'backend.webhook')]
|
||||
public function __invoke(iRequest $request, array $args = []): iResponse
|
||||
{
|
||||
if (null === ($name = ag($args, 'name'))) {
|
||||
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
return $this->process($name, $request)->withHeader('X-Log-Response', '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the incoming webhook request.
|
||||
*
|
||||
* @param string $name The backend name.
|
||||
* @param iRequest $request The incoming request object.
|
||||
*
|
||||
* @return iResponse The response object.
|
||||
* @throws InvalidArgumentException if cache key is invalid.
|
||||
*/
|
||||
private function process(string $name, iRequest $request): iResponse
|
||||
{
|
||||
try {
|
||||
$backend = $this->getBackends(name: $name);
|
||||
if (empty($backend)) {
|
||||
@@ -84,7 +98,7 @@ final class Webhooks
|
||||
if (null === ($requestUser = ag($attr, 'user.id'))) {
|
||||
$message = "Request payload didn't contain a user id. Backend requires a user check.";
|
||||
$this->write($request, Level::Info, $message);
|
||||
return api_error($message, HTTP_STATUS::HTTP_BAD_REQUEST)->withHeader('X-Log-Response', '0');
|
||||
return api_error($message, HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (false === hash_equals((string)$userId, (string)$requestUser)) {
|
||||
@@ -93,7 +107,7 @@ final class Webhooks
|
||||
'config_user' => $userId,
|
||||
]);
|
||||
$this->write($request, Level::Info, $message);
|
||||
return api_error($message, HTTP_STATUS::HTTP_BAD_REQUEST)->withHeader('X-Log-Response', '0');
|
||||
return api_error($message, HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +115,7 @@ final class Webhooks
|
||||
if (null === ($requestBackendId = ag($attr, 'backend.id'))) {
|
||||
$message = "Request payload didn't contain the backend unique id.";
|
||||
$this->write($request, Level::Info, $message);
|
||||
return api_error($message, HTTP_STATUS::HTTP_BAD_REQUEST)->withHeader('X-Log-Response', '0');
|
||||
return api_error($message, HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (false === hash_equals((string)$uuid, (string)$requestBackendId)) {
|
||||
@@ -110,7 +124,7 @@ final class Webhooks
|
||||
'config_uid' => $uuid,
|
||||
]);
|
||||
$this->write($request, Level::Info, $message);
|
||||
return api_error($message, HTTP_STATUS::HTTP_BAD_REQUEST)->withHeader('X-Log-Response', '0');
|
||||
return api_error($message, HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +142,7 @@ final class Webhooks
|
||||
'backend' => $client->getName(),
|
||||
]), forceContext: true);
|
||||
|
||||
return $response->withHeader('X-Log-Response', '0');
|
||||
return $response;
|
||||
}
|
||||
|
||||
$entity = $client->parseWebhook($request);
|
||||
@@ -151,7 +165,7 @@ final class Webhooks
|
||||
]
|
||||
);
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_NOT_MODIFIED)->withHeader('X-Log-Response', '0');
|
||||
return api_response(HTTP_STATUS::HTTP_NOT_MODIFIED);
|
||||
}
|
||||
|
||||
if ((0 === (int)$entity->episode || null === $entity->season) && $entity->isEpisode()) {
|
||||
@@ -170,7 +184,7 @@ final class Webhooks
|
||||
]
|
||||
);
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_NOT_MODIFIED)->withHeader('X-Log-Response', '0');
|
||||
return api_response(HTTP_STATUS::HTTP_NOT_MODIFIED);
|
||||
}
|
||||
|
||||
$items = $this->cache->get('requests', []);
|
||||
@@ -211,7 +225,7 @@ final class Webhooks
|
||||
]
|
||||
);
|
||||
|
||||
return api_response(HTTP_STATUS::HTTP_OK)->withHeader('X-Log-Response', '0');
|
||||
return api_response(HTTP_STATUS::HTTP_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,9 +271,9 @@ final class Webhooks
|
||||
}
|
||||
|
||||
if (true === (Config::get('logs.context') || $forceContext)) {
|
||||
$this->accessLog->log($level, $message, $context);
|
||||
$this->logfile->log($level, $message, $context);
|
||||
} else {
|
||||
$this->accessLog->log($level, r($message, $context));
|
||||
$this->logfile->log($level, r($message, $context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user