Browse Source

Replicate some unspecified NCNv1 behaviour, and document the rest

See #139 for list

Closes #139
Closes #140
Closes #141
microsub
J. King 5 years ago
parent
commit
3b3b810f10
  1. 15
      README.md
  2. 4
      lib/REST/NextCloudNews/V1_2.php
  3. 21
      tests/cases/REST/NextCloudNews/TestV1_2.php

15
README.md

@ -97,15 +97,12 @@ As a general rule, The Arsse should yield the same output as the reference imple
- The API's "updater" routes do not require administrator priviledges as The Arsse has no concept of user classes - The API's "updater" routes do not require administrator priviledges as The Arsse has no concept of user classes
- The "updater" console commands mentioned in the protocol specification are not implemented, as The Arsse does not implement the required NextCloud subsystems - The "updater" console commands mentioned in the protocol specification are not implemented, as The Arsse does not implement the required NextCloud subsystems
- The `lastLoginTimestamp` attribute of the user metadata is always the current time: The Arsse's implementation of the protocol is fully stateless - The `lastLoginTimestamp` attribute of the user metadata is always the current time: The Arsse's implementation of the protocol is fully stateless
- Syntactically invalid JSON input will yield a `400 Bad Request` response instead of falling back to GET parameters
#### Ambiguities - Folder names consisting only of whitespace are rejected along with the empty string
- Feed titles consisting only of whitespace or the empty string are rejected with a `422 Unprocessable Entity` reponse instead of being accepted
- NCN specifies that GET parameters are treated "the same" as request body parameters; it does not specify what to do in cases where they conflict. The Arsse chooses to give GET parameters precedence - Bulk-marking operations without a `newestItemId` argument result in a `422 Unprocessable Entity` reponse instead of silently failing
- NCN does not define validity of folder and names other than to specify that the empty string is invalid. The Arsse further considers any string composed only of whitesapce to be invalid - Creating a feed in a folder which does not exist places the feed in the root folder rather than suppressing the feed
- NCN does not specify a return code for bulk-marking operations without a `newestItemId` provided; The Arsse returns `422` - Moving a feed to a folder which does not exist results in a `422 Unprocessable Entity` reponse rather than suppressing the feed
- NCN does not specify what should be done when creating a feed in a folder which does not exist; the Arsse adds the feed to the root folder
- NCN does not specify what should be done when moving a feed to a folder which does not exist; The Arsse return `422`
- NCN does not specify what should be done when renaming a feed to an invalid title, nor what constitutes an invalid title; The Arsse uses the same rules as it does for folders, and returns `422` in cases of rejection
### Tiny Tiny RSS ### Tiny Tiny RSS

4
lib/REST/NextCloudNews/V1_2.php

@ -111,8 +111,8 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
} else { } else {
$data = []; $data = [];
} }
// FIXME: Do query parameters take precedence in NextCloud? Is there a conflict error when values differ? // merge GET and POST data, and normalize it. POST parameters are preferred over GET parameters
$data = $this->normalizeInput(array_merge($data, $req->getQueryParams()), $this->validInput, "unix"); $data = $this->normalizeInput(array_merge($req->getQueryParams(), $data), $this->validInput, "unix");
// check to make sure the requested function is implemented // check to make sure the requested function is implemented
try { try {
$func = $this->chooseCall((string) $target, $req->getMethod()); $func = $this->chooseCall((string) $target, $req->getMethod());

21
tests/cases/REST/NextCloudNews/TestV1_2.php

@ -939,4 +939,25 @@ class TestV1_2 extends \JKingWeb\Arsse\Test\AbstractTest {
]); ]);
$this->assertMessage($exp, $act); $this->assertMessage($exp, $act);
} }
public function testPreferJsonOverQueryParameters() {
$in = ['name' => "Software"];
$url = "/folders?name=Hardware";
$out1 = ['id' => 1, 'name' => "Software"];
$out2 = ['id' => 2, 'name' => "Hardware"];
Phake::when(Arsse::$db)->folderAdd($this->anything(), $this->anything())->thenReturn(2);
Phake::when(Arsse::$db)->folderAdd($this->anything(), $in)->thenReturn(1);
Phake::when(Arsse::$db)->folderPropertiesGet(Arsse::$user->id, 1)->thenReturn($this->v($out1));
Phake::when(Arsse::$db)->folderPropertiesGet(Arsse::$user->id, 2)->thenReturn($this->v($out2));
$exp = new Response(['folders' => [$out1]]);
$this->assertMessage($exp, $this->req("POST", "/folders?name=Hardware", json_encode($in)));
}
public function testMeldJsonAndQueryParameters() {
$in = ['oldestFirst' => true];
$url = "/items?type=2";
Phake::when(Arsse::$db)->articleList->thenReturn(new Result([]));
$this->req("GET", $url, json_encode($in));
Phake::verify(Arsse::$db)->articleList(Arsse::$user->id, (new Context)->reverse(false)->starred(true), Database::LIST_TYPICAL);
}
} }

Loading…
Cancel
Save