API: /backend/.../ Do not do partial updates if some option fails validation.
This commit is contained in:
@@ -106,8 +106,9 @@ return [
|
|||||||
'visible' => true,
|
'visible' => true,
|
||||||
'description' => 'How many items to per request.',
|
'description' => 'How many items to per request.',
|
||||||
'validate' => function ($value) {
|
'validate' => function ($value) {
|
||||||
if ((int)$value < 100) {
|
$limit = 300;
|
||||||
throw new ValidationException('The value must be greater than 100 items.');
|
if ((int)$value < $limit) {
|
||||||
|
throw new ValidationException(r('The value must be greater than {limit} items.', ['limit' => $limit]));
|
||||||
}
|
}
|
||||||
return (int)$value;
|
return (int)$value;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use App\Libs\ConfigFile;
|
|||||||
use App\Libs\Container;
|
use App\Libs\Container;
|
||||||
use App\Libs\DataUtil;
|
use App\Libs\DataUtil;
|
||||||
use App\Libs\Exceptions\Backends\InvalidContextException;
|
use App\Libs\Exceptions\Backends\InvalidContextException;
|
||||||
|
use App\Libs\Exceptions\ValidationException;
|
||||||
use App\Libs\HTTP_STATUS;
|
use App\Libs\HTTP_STATUS;
|
||||||
use App\Libs\Traits\APITraits;
|
use App\Libs\Traits\APITraits;
|
||||||
use App\Libs\Uri;
|
use App\Libs\Uri;
|
||||||
@@ -84,7 +85,7 @@ final class Update
|
|||||||
$backend = array_pop($backend);
|
$backend = array_pop($backend);
|
||||||
|
|
||||||
return api_response(HTTP_STATUS::HTTP_OK, $backend);
|
return api_response(HTTP_STATUS::HTTP_OK, $backend);
|
||||||
} catch (InvalidContextException $e) {
|
} catch (InvalidContextException|ValidationException $e) {
|
||||||
return api_error($e->getMessage(), HTTP_STATUS::HTTP_BAD_REQUEST);
|
return api_error($e->getMessage(), HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,6 +108,8 @@ final class Update
|
|||||||
HTTP_STATUS::HTTP_BAD_REQUEST);
|
HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$updates = [];
|
||||||
|
|
||||||
foreach ($data as $update) {
|
foreach ($data as $update) {
|
||||||
$value = ag($update, 'value');
|
$value = ag($update, 'value');
|
||||||
|
|
||||||
@@ -117,14 +120,31 @@ final class Update
|
|||||||
$spec = getServerColumnSpec($key);
|
$spec = getServerColumnSpec($key);
|
||||||
|
|
||||||
if (empty($spec)) {
|
if (empty($spec)) {
|
||||||
return api_error(r('Invalid key to update: {key}', ['key' => $key]), HTTP_STATUS::HTTP_BAD_REQUEST);
|
return api_error(r("Invalid key '{key}' was given.", ['key' => $key]), HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
settype($value, ag($spec, 'type', 'string'));
|
||||||
|
|
||||||
|
if (true === ag_exists($spec, 'validate')) {
|
||||||
|
try {
|
||||||
|
$value = $spec['validate']($value);
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
return api_error(r("Value validation for '{key}' failed. {error}", [
|
||||||
|
'key' => $key,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]), HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array($key, self::IMMUTABLE_KEYS, true)) {
|
if (in_array($key, self::IMMUTABLE_KEYS, true)) {
|
||||||
return api_error(r('Key {key} is immutable.', ['key' => $key]), HTTP_STATUS::HTTP_BAD_REQUEST);
|
return api_error(r('Key {key} is immutable.', ['key' => $key]), HTTP_STATUS::HTTP_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->backendFile->set("{$name}.{$key}", $value);
|
$updates["{$name}.{$key}"] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($updates as $key => $value) {
|
||||||
|
$this->backendFile->set($key, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->backendFile->persist();
|
$this->backendFile->persist();
|
||||||
@@ -171,6 +191,19 @@ final class Update
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
settype($value, ag($spec, 'type', 'string'));
|
||||||
|
|
||||||
|
if (true === ag_exists($spec, 'validate')) {
|
||||||
|
try {
|
||||||
|
$value = $spec['validate']($value);
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
throw new ValidationException(r("Value validation for '{key}' failed. {error}", [
|
||||||
|
'key' => $key,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
]), $e->getCode(), $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$newData = ag_set($newData, $key, $value);
|
$newData = ag_set($newData, $key, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ namespace App\Commands\Config;
|
|||||||
use App\Command;
|
use App\Command;
|
||||||
use App\Libs\Attributes\Route\Cli;
|
use App\Libs\Attributes\Route\Cli;
|
||||||
use App\Libs\HTTP_STATUS;
|
use App\Libs\HTTP_STATUS;
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
use Symfony\Component\Console\Completion\CompletionInput;
|
use Symfony\Component\Console\Completion\CompletionInput;
|
||||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
@@ -24,11 +23,6 @@ final class EditCommand extends Command
|
|||||||
{
|
{
|
||||||
public const string ROUTE = 'config:edit';
|
public const string ROUTE = 'config:edit';
|
||||||
|
|
||||||
public function __construct(private LoggerInterface $logger)
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the command.
|
* Configures the command.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user