Browse Source

Fever fixes

- Ensure the last refresh time is included in authenticated requests
- Use a partial mock in auth tests so that other processing does not
get in the way of results
- Make sure the group list includes unused groups
- Make sure the update time of subscriptions is correct
microsub
J. King 5 years ago
parent
commit
7faec3b0db
  1. 57
      lib/REST/Fever/API.php
  2. 15
      tests/cases/REST/Fever/TestAPI.php

57
lib/REST/Fever/API.php

@ -60,23 +60,9 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
// check that the user specified credentials // check that the user specified credentials
if ($this->logIn(strtolower($inW['api_key'] ?? ""))) { if ($this->logIn(strtolower($inW['api_key'] ?? ""))) {
$out['auth'] = 1; $out['auth'] = 1;
$out = $this->processRequest($out, $inR, $inW);
} else { } else {
$out['auth'] = 0; $out['auth'] = 0;
return $this->formatResponse($out, $xml);
}
// handle each possible parameter
if (array_key_exists("feeds", $inR) || array_key_exists("groups", $inR)) {
$groupData = (array) Arsse::$db->tagSummarize(Arsse::$user->id);
if (array_key_exists("groups", $inR)) {
$out['groups'] = $this->getGroups($groupData);
}
if (array_key_exists("feeds", $inR)) {
$out['feeds'] = $this->getFeeds();
}
$out['feeds_groups'] = $this->getRelationships($groupData);
}
if (array_key_exists("favicons", $inR)) {
# deal with favicons
} }
// return the result // return the result
return $this->formatResponse($out, $xml); return $this->formatResponse($out, $xml);
@ -86,6 +72,25 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
} }
} }
protected function processRequest(array $out, array $G, array $P): array {
// add base metadata
$out['last_refreshed_on_time'] = Date::transform(Arsse::$db->subscriptionRefreshed(Arsse::$user->id), "unix");
// handle each possible parameter
if (array_key_exists("feeds", $G) || array_key_exists("groups", $G)) {
if (array_key_exists("groups", $G)) {
$out['groups'] = $this->getGroups();
}
if (array_key_exists("feeds", $G)) {
$out['feeds'] = $this->getFeeds();
}
$out['feeds_groups'] = $this->getRelationships();
}
if (array_key_exists("favicons", $G)) {
# deal with favicons
}
return $out;
}
protected function formatResponse(array $data, bool $xml): ResponseInterface { protected function formatResponse(array $data, bool $xml): ResponseInterface {
if ($xml) { if ($xml) {
throw \Exception("Not implemented yet"); throw \Exception("Not implemented yet");
@ -120,31 +125,27 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
'url' => $sub['url'], 'url' => $sub['url'],
'site_url' => $sub['source'], 'site_url' => $sub['source'],
'is_spark' => 0, 'is_spark' => 0,
'lat_updated_on_time' => Date::transform($sub['updated'], "unix"), 'lat_updated_on_time' => Date::transform($sub['edited'], "unix", "sql"),
]; ];
} }
return $out; return $out;
} }
protected function getGroups(array $data): array { protected function getGroups(): array {
$out = []; $out = [];
$seen = []; foreach (Arsse::$db->tagList(Arsse::$user->id) as $member) {
foreach ($data as $member) { $out[] = [
if (!($seen[$member['id']] ?? false)) { 'id' => (int) $member['id'],
$seen[$member['id']] = true; 'title' => $member['name'],
$out[] = [ ];
'id' => (int) $member['id'],
'title' => $member['name'],
];
}
} }
return $out; return $out;
} }
protected function getRelationships(array $data): array { protected function getRelationships(): array {
$out = []; $out = [];
$sets = []; $sets = [];
foreach ($data as $member) { foreach (Arsse::$db->tagSummarize(Arsse::$user->id) as $member) {
if (!isset($sets[$member['id']])) { if (!isset($sets[$member['id']])) {
$sets[$member['id']] = []; $sets[$member['id']] = [];
} }

15
tests/cases/REST/Fever/TestAPI.php

@ -23,7 +23,6 @@ use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\ServerRequest; use Zend\Diactoros\ServerRequest;
use Zend\Diactoros\Response\JsonResponse; use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\Response\EmptyResponse; use Zend\Diactoros\Response\EmptyResponse;
use Phake;
/** @covers \JKingWeb\Arsse\REST\Fever\API<extended> */ /** @covers \JKingWeb\Arsse\REST\Fever\API<extended> */
class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
@ -66,12 +65,13 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
self::clearData(); self::clearData();
self::setConf(); self::setConf();
// create a mock user manager // create a mock user manager
Arsse::$user = Phake::mock(User::class); Arsse::$user = \Phake::mock(User::class);
Phake::when(Arsse::$user)->auth->thenReturn(true); \Phake::when(Arsse::$user)->auth->thenReturn(true);
Arsse::$user->id = "john.doe@example.com"; Arsse::$user->id = "john.doe@example.com";
// create a mock database interface // create a mock database interface
Arsse::$db = Phake::mock(Database::class); Arsse::$db = \Phake::mock(Database::class);
Phake::when(Arsse::$db)->begin->thenReturn(Phake::mock(Transaction::class)); \Phake::when(Arsse::$db)->begin->thenReturn(\Phake::mock(Transaction::class));
\Phake::when(Arsse::$db)->tokenLookup->thenReturn(['user' => "john.doe@example.com"]);
// instantiate the handler // instantiate the handler
$this->h = new API(); $this->h = new API();
} }
@ -89,6 +89,11 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest {
Arsse::$user->id = null; Arsse::$user->id = null;
\Phake::when(Arsse::$db)->tokenLookup->thenThrow(new ExceptionInput("subjectMissing")); \Phake::when(Arsse::$db)->tokenLookup->thenThrow(new ExceptionInput("subjectMissing"));
\Phake::when(Arsse::$db)->tokenLookup("fever.login", "validtoken")->thenReturn(['user' => "jane.doe@example.com"]); \Phake::when(Arsse::$db)->tokenLookup("fever.login", "validtoken")->thenReturn(['user' => "jane.doe@example.com"]);
// use a partial mock to test only the authentication process
$this->h = \Phake::partialMock(API::class);
\Phake::when($this->h)->processRequest->thenReturnCallback(function($out, $G, $P) {
return $out;
});
$act = $this->req($dataGet, $dataPost, "POST", null, "", $httpUser); $act = $this->req($dataGet, $dataPost, "POST", null, "", $httpUser);
$this->assertMessage($exp, $act); $this->assertMessage($exp, $act);
} }

Loading…
Cancel
Save