mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-31 21:12:41 +00:00
Fix up error codes for category changes
This commit is contained in:
parent
197922f92f
commit
bf95b134bd
2 changed files with 58 additions and 53 deletions
|
@ -50,81 +50,81 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
'entry_swipe' => ["swipe", true, false],
|
'entry_swipe' => ["swipe", true, false],
|
||||||
'custom_css' => ["stylesheet", "", true],
|
'custom_css' => ["stylesheet", "", true],
|
||||||
];
|
];
|
||||||
protected const CALLS = [ // handler method Admin Path Body Query
|
protected const CALLS = [ // handler method Admin Path Body Query Required fields
|
||||||
'/categories' => [
|
'/categories' => [
|
||||||
'GET' => ["getCategories", false, false, false, false],
|
'GET' => ["getCategories", false, false, false, false, []],
|
||||||
'POST' => ["createCategory", false, false, true, false],
|
'POST' => ["createCategory", false, false, true, false, ["title"]],
|
||||||
],
|
],
|
||||||
'/categories/1' => [
|
'/categories/1' => [
|
||||||
'PUT' => ["updateCategory", false, true, true, false],
|
'PUT' => ["updateCategory", false, true, true, false, ["title"]], // title is effectively required since no other field can be changed
|
||||||
'DELETE' => ["deleteCategory", false, true, false, false],
|
'DELETE' => ["deleteCategory", false, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/categories/1/mark-all-as-read' => [
|
'/categories/1/mark-all-as-read' => [
|
||||||
'PUT' => ["markCategory", false, true, false, false],
|
'PUT' => ["markCategory", false, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/discover' => [
|
'/discover' => [
|
||||||
'POST' => ["discoverSubscriptions", false, false, true, false],
|
'POST' => ["discoverSubscriptions", false, false, true, false, ["url"]],
|
||||||
],
|
],
|
||||||
'/entries' => [
|
'/entries' => [
|
||||||
'GET' => ["getEntries", false, false, false, true],
|
'GET' => ["getEntries", false, false, false, true, []],
|
||||||
'PUT' => ["updateEntries", false, false, true, false],
|
'PUT' => ["updateEntries", false, false, true, false, []],
|
||||||
],
|
],
|
||||||
'/entries/1' => [
|
'/entries/1' => [
|
||||||
'GET' => ["getEntry", false, true, false, false],
|
'GET' => ["getEntry", false, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/entries/1/bookmark' => [
|
'/entries/1/bookmark' => [
|
||||||
'PUT' => ["toggleEntryBookmark", false, true, false, false],
|
'PUT' => ["toggleEntryBookmark", false, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/export' => [
|
'/export' => [
|
||||||
'GET' => ["opmlExport", false, false, false, false],
|
'GET' => ["opmlExport", false, false, false, false, []],
|
||||||
],
|
],
|
||||||
'/feeds' => [
|
'/feeds' => [
|
||||||
'GET' => ["getFeeds", false, false, false, false],
|
'GET' => ["getFeeds", false, false, false, false, []],
|
||||||
'POST' => ["createFeed", false, false, true, false],
|
'POST' => ["createFeed", false, false, true, false, []],
|
||||||
],
|
],
|
||||||
'/feeds/1' => [
|
'/feeds/1' => [
|
||||||
'GET' => ["getFeed", false, true, false, false],
|
'GET' => ["getFeed", false, true, false, false, []],
|
||||||
'PUT' => ["updateFeed", false, true, true, false],
|
'PUT' => ["updateFeed", false, true, true, false, []],
|
||||||
'DELETE' => ["deleteFeed", false, true, false, false],
|
'DELETE' => ["deleteFeed", false, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/feeds/1/entries' => [
|
'/feeds/1/entries' => [
|
||||||
'GET' => ["getFeedEntries", false, true, false, false],
|
'GET' => ["getFeedEntries", false, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/feeds/1/entries/1' => [
|
'/feeds/1/entries/1' => [
|
||||||
'GET' => ["getFeedEntry", false, true, false, false],
|
'GET' => ["getFeedEntry", false, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/feeds/1/icon' => [
|
'/feeds/1/icon' => [
|
||||||
'GET' => ["getFeedIcon", false, true, false, false],
|
'GET' => ["getFeedIcon", false, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/feeds/1/mark-all-as-read' => [
|
'/feeds/1/mark-all-as-read' => [
|
||||||
'PUT' => ["markFeed", false, true, false, false],
|
'PUT' => ["markFeed", false, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/feeds/1/refresh' => [
|
'/feeds/1/refresh' => [
|
||||||
'PUT' => ["refreshFeed", false, true, false, false],
|
'PUT' => ["refreshFeed", false, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/feeds/refresh' => [
|
'/feeds/refresh' => [
|
||||||
'PUT' => ["refreshAllFeeds", false, false, false, false],
|
'PUT' => ["refreshAllFeeds", false, false, false, false, []],
|
||||||
],
|
],
|
||||||
'/import' => [
|
'/import' => [
|
||||||
'POST' => ["opmlImport", false, false, true, false],
|
'POST' => ["opmlImport", false, false, true, false, []],
|
||||||
],
|
],
|
||||||
'/me' => [
|
'/me' => [
|
||||||
'GET' => ["getCurrentUser", false, false, false, false],
|
'GET' => ["getCurrentUser", false, false, false, false, []],
|
||||||
],
|
],
|
||||||
'/users' => [
|
'/users' => [
|
||||||
'GET' => ["getUsers", true, false, false, false],
|
'GET' => ["getUsers", true, false, false, false, []],
|
||||||
'POST' => ["createUser", true, false, true, false],
|
'POST' => ["createUser", true, false, true, false, ["username", "password"]],
|
||||||
],
|
],
|
||||||
'/users/1' => [
|
'/users/1' => [
|
||||||
'GET' => ["getUserByNum", true, true, false, false],
|
'GET' => ["getUserByNum", true, true, false, false, []],
|
||||||
'PUT' => ["updateUserByNum", false, true, true, false], // requires admin for users other than self
|
'PUT' => ["updateUserByNum", false, true, true, false, []], // requires admin for users other than self
|
||||||
'DELETE' => ["deleteUserByNum", true, true, false, false],
|
'DELETE' => ["deleteUserByNum", true, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/users/1/mark-all-as-read' => [
|
'/users/1/mark-all-as-read' => [
|
||||||
'PUT' => ["markUserByNum", false, true, false, false],
|
'PUT' => ["markUserByNum", false, true, false, false, []],
|
||||||
],
|
],
|
||||||
'/users/*' => [
|
'/users/*' => [
|
||||||
'GET' => ["getUserById", true, true, false, false],
|
'GET' => ["getUserById", true, true, false, false, []],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
if ($func instanceof ResponseInterface) {
|
if ($func instanceof ResponseInterface) {
|
||||||
return $func;
|
return $func;
|
||||||
} else {
|
} else {
|
||||||
[$func, $reqAdmin, $reqPath, $reqBody, $reqQuery] = $func;
|
[$func, $reqAdmin, $reqPath, $reqBody, $reqQuery, $reqFields] = $func;
|
||||||
}
|
}
|
||||||
if ($reqAdmin && !$this->isAdmin()) {
|
if ($reqAdmin && !$this->isAdmin()) {
|
||||||
return new ErrorResponse("403", 403);
|
return new ErrorResponse("403", 403);
|
||||||
|
@ -195,7 +195,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
} else {
|
} else {
|
||||||
$data = [];
|
$data = [];
|
||||||
}
|
}
|
||||||
$data = $this->normalizeBody((array) $data);
|
$data = $this->normalizeBody((array) $data, $reqFields);
|
||||||
if ($data instanceof ResponseInterface) {
|
if ($data instanceof ResponseInterface) {
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
return implode("/", $path);
|
return implode("/", $path);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function normalizeBody(array $body) {
|
protected function normalizeBody(array $body, array $req) {
|
||||||
// Miniflux does not attempt to coerce values into different types
|
// Miniflux does not attempt to coerce values into different types
|
||||||
foreach (self::VALID_JSON as $k => $t) {
|
foreach (self::VALID_JSON as $k => $t) {
|
||||||
if (!isset($body[$k])) {
|
if (!isset($body[$k])) {
|
||||||
|
@ -264,6 +264,7 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
return new ErrorResponse(["InvalidInputType", 'field' => $k, 'expected' => $t, 'actual' => gettype($body[$k])], 422);
|
return new ErrorResponse(["InvalidInputType", 'field' => $k, 'expected' => $t, 'actual' => gettype($body[$k])], 422);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//normalize user-specific input
|
||||||
foreach (self::USER_META_MAP as $k => [,$d,]) {
|
foreach (self::USER_META_MAP as $k => [,$d,]) {
|
||||||
$t = gettype($d);
|
$t = gettype($d);
|
||||||
if (!isset($body[$k])) {
|
if (!isset($body[$k])) {
|
||||||
|
@ -276,6 +277,12 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
return new ErrorResponse(["InvalidInputType", 'field' => $k, 'expected' => $t, 'actual' => gettype($body[$k])], 422);
|
return new ErrorResponse(["InvalidInputType", 'field' => $k, 'expected' => $t, 'actual' => gettype($body[$k])], 422);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// check for any missing required values
|
||||||
|
foreach ($req as $k) {
|
||||||
|
if (!isset($body[$k])) {
|
||||||
|
return new ErrorResponse(["MissingInputValue", 'field' => $k], 422);
|
||||||
|
}
|
||||||
|
}
|
||||||
return $body;
|
return $body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,11 +413,6 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createUser(array $data): ResponseInterface {
|
protected function createUser(array $data): ResponseInterface {
|
||||||
if ($data['username'] === null) {
|
|
||||||
return new ErrorResponse(["MissingInputValue", 'field' => "username"], 422);
|
|
||||||
} elseif ($data['password'] === null) {
|
|
||||||
return new ErrorResponse(["MissingInputValue", 'field' => "password"], 422);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
$tr = Arsse::$user->begin();
|
$tr = Arsse::$user->begin();
|
||||||
$data['password'] = Arsse::$user->add($data['username'], $data['password']);
|
$data['password'] = Arsse::$user->add($data['username'], $data['password']);
|
||||||
|
@ -496,9 +498,9 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
$id = Arsse::$db->folderAdd(Arsse::$user->id, ['name' => (string) $data['title']]);
|
$id = Arsse::$db->folderAdd(Arsse::$user->id, ['name' => (string) $data['title']]);
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
if ($e->getCode() === 10236) {
|
if ($e->getCode() === 10236) {
|
||||||
return new ErrorResponse(["DuplicateCategory", 'title' => $data['title']], 500);
|
return new ErrorResponse(["DuplicateCategory", 'title' => $data['title']], 409);
|
||||||
} else {
|
} else {
|
||||||
return new ErrorResponse(["InvalidCategory", 'title' => $data['title']], 500);
|
return new ErrorResponse(["InvalidCategory", 'title' => $data['title']], 422);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$meta = Arsse::$user->propertiesGet(Arsse::$user->id, false);
|
$meta = Arsse::$user->propertiesGet(Arsse::$user->id, false);
|
||||||
|
@ -521,11 +523,11 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
}
|
}
|
||||||
} catch (ExceptionInput $e) {
|
} catch (ExceptionInput $e) {
|
||||||
if ($e->getCode() === 10236) {
|
if ($e->getCode() === 10236) {
|
||||||
return new ErrorResponse(["DuplicateCategory", 'title' => $title], 500);
|
return new ErrorResponse(["DuplicateCategory", 'title' => $title], 409);
|
||||||
} elseif (in_array($e->getCode(), [10237, 10239])) {
|
} elseif (in_array($e->getCode(), [10237, 10239])) {
|
||||||
return new ErrorResponse("404", 404);
|
return new ErrorResponse("404", 404);
|
||||||
} else {
|
} else {
|
||||||
return new ErrorResponse(["InvalidCategory", 'title' => $title], 500);
|
return new ErrorResponse(["InvalidCategory", 'title' => $title], 422);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$meta = Arsse::$user->propertiesGet(Arsse::$user->id, false);
|
$meta = Arsse::$user->propertiesGet(Arsse::$user->id, false);
|
||||||
|
|
|
@ -416,9 +416,10 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
public function provideCategoryAdditions(): iterable {
|
public function provideCategoryAdditions(): iterable {
|
||||||
return [
|
return [
|
||||||
["New", new Response(['id' => 2112, 'title' => "New", 'user_id' => 42], 201)],
|
["New", new Response(['id' => 2112, 'title' => "New", 'user_id' => 42], 201)],
|
||||||
["Duplicate", new ErrorResponse(["DuplicateCategory", 'title' => "Duplicate"], 500)],
|
["Duplicate", new ErrorResponse(["DuplicateCategory", 'title' => "Duplicate"], 409)],
|
||||||
["", new ErrorResponse(["InvalidCategory", 'title' => ""], 500)],
|
["", new ErrorResponse(["InvalidCategory", 'title' => ""], 422)],
|
||||||
[" ", new ErrorResponse(["InvalidCategory", 'title' => " "], 500)],
|
[" ", new ErrorResponse(["InvalidCategory", 'title' => " "], 422)],
|
||||||
|
[null, new ErrorResponse(["MissingInputValue", 'field' => "title"], 422)],
|
||||||
[false, new ErrorResponse(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"],422)],
|
[false, new ErrorResponse(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"],422)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -442,14 +443,16 @@ class TestV1 extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
return [
|
return [
|
||||||
[3, "New", "subjectMissing", new ErrorResponse("404", 404)],
|
[3, "New", "subjectMissing", new ErrorResponse("404", 404)],
|
||||||
[2, "New", true, new Response(['id' => 2, 'title' => "New", 'user_id' => 42])],
|
[2, "New", true, new Response(['id' => 2, 'title' => "New", 'user_id' => 42])],
|
||||||
[2, "Duplicate", "constraintViolation", new ErrorResponse(["DuplicateCategory", 'title' => "Duplicate"], 500)],
|
[2, "Duplicate", "constraintViolation", new ErrorResponse(["DuplicateCategory", 'title' => "Duplicate"], 409)],
|
||||||
[2, "", "missing", new ErrorResponse(["InvalidCategory", 'title' => ""], 500)],
|
[2, "", "missing", new ErrorResponse(["InvalidCategory", 'title' => ""], 422)],
|
||||||
[2, " ", "whitespace", new ErrorResponse(["InvalidCategory", 'title' => " "], 500)],
|
[2, " ", "whitespace", new ErrorResponse(["InvalidCategory", 'title' => " "], 422)],
|
||||||
[2, false, "subjectMissing", new ErrorResponse(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"],422)],
|
[2, null, "missing", new ErrorResponse(["MissingInputValue", 'field' => "title"], 422)],
|
||||||
|
[2, false, "subjectMissing", new ErrorResponse(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"], 422)],
|
||||||
[1, "New", true, new Response(['id' => 1, 'title' => "New", 'user_id' => 42])],
|
[1, "New", true, new Response(['id' => 1, 'title' => "New", 'user_id' => 42])],
|
||||||
[1, "Duplicate", "constraintViolation", new Response(['id' => 1, 'title' => "Duplicate", 'user_id' => 42])], // This is allowed because the name of the root folder is only a duplicate in circumstances where it is used
|
[1, "Duplicate", "constraintViolation", new Response(['id' => 1, 'title' => "Duplicate", 'user_id' => 42])], // This is allowed because the name of the root folder is only a duplicate in circumstances where it is used
|
||||||
[1, "", "missing", new ErrorResponse(["InvalidCategory", 'title' => ""], 500)],
|
[1, "", "missing", new ErrorResponse(["InvalidCategory", 'title' => ""], 422)],
|
||||||
[1, " ", "whitespace", new ErrorResponse(["InvalidCategory", 'title' => " "], 500)],
|
[1, " ", "whitespace", new ErrorResponse(["InvalidCategory", 'title' => " "], 422)],
|
||||||
|
[1, null, "missing", new ErrorResponse(["MissingInputValue", 'field' => "title"], 422)],
|
||||||
[1, false, false, new ErrorResponse(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"], 422)],
|
[1, false, false, new ErrorResponse(["InvalidInputType", 'field' => "title", 'actual' => "boolean", 'expected' => "string"], 422)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue