Browse Source

More bug fixes

- use DateFormatter throughout the Feed class
- Ensure dates have TEXT affinity in SQLite, in case it matters
- Add a userPreAuth setting for when relying on the Web server to do authentication
microsub
J. King 7 years ago
parent
commit
d4674c61b2
  1. 4
      lib/Conf.php
  2. 2
      lib/Database.php
  3. 18
      lib/Feed.php
  4. 3
      lib/Misc/DateFormatter.php
  5. 16
      lib/User.php
  6. 20
      sql/SQLite3/0.sql
  7. 1
      tests/User/TestAuthorization.php
  8. 1
      tests/lib/User/CommonTests.php

4
lib/Conf.php

@ -23,11 +23,13 @@ class Conf {
public $dbMySQLDb = "arsse"; public $dbMySQLDb = "arsse";
public $userDriver = User\Internal\Driver::class; public $userDriver = User\Internal\Driver::class;
public $userPreAuth = true;
public $userComposeNames = true; public $userComposeNames = true;
public $userTempPasswordLength = 20; public $userTempPasswordLength = 20;
public $serviceDriver = Service\Curl\Driver::class; public $serviceDriver = Service\Internal\Driver::class;
public $serviceFrequency = "PT2M"; public $serviceFrequency = "PT2M";
public $serviceQueueWidth = 5;
public $serviceCurlBase = "http://localhost/"; public $serviceCurlBase = "http://localhost/";
public $serviceCurlUser = null; public $serviceCurlUser = null;
public $serviceCurlPassword = null; public $serviceCurlPassword = null;

2
lib/Database.php

@ -442,7 +442,7 @@ class Database {
// here. When an exception is thrown it should update the database with the // here. When an exception is thrown it should update the database with the
// error instead of failing; if other exceptions are thrown, we should simply roll back // error instead of failing; if other exceptions are thrown, we should simply roll back
try { try {
$feed = new Feed($feedID, $f['url'], $this->dateTransform($f['modified'], "http", "sql"), $f['etag'], $f['username'], $f['password']); $feed = new Feed($feedID, $f['url'], (string) $this->dateTransform($f['modified'], "http", "sql"), $f['etag'], $f['username'], $f['password']);
if(!$feed->modified) { if(!$feed->modified) {
// if the feed hasn't changed, just compute the next fetch time and record it // if the feed hasn't changed, just compute the next fetch time and record it
$this->db->prepare("UPDATE arsse_feeds SET updated = CURRENT_TIMESTAMP, next_fetch = ? WHERE id is ?", 'datetime', 'int')->run($feed->nextFetch, $feedID); $this->db->prepare("UPDATE arsse_feeds SET updated = CURRENT_TIMESTAMP, next_fetch = ? WHERE id is ?", 'datetime', 'int')->run($feed->nextFetch, $feedID);

18
lib/Feed.php

@ -209,7 +209,8 @@ class Feed {
} }
$articles = Data::$db->feedMatchIds($feedID, $ids, $hashesUT, $hashesUC, $hashesTC)->getAll(); $articles = Data::$db->feedMatchIds($feedID, $ids, $hashesUT, $hashesUC, $hashesTC)->getAll();
list($this->newItems, $changed) = $this->matchItems($this->newItems, $articles); list($this->newItems, $changed) = $this->matchItems($this->newItems, $articles);
$this->changedItems = array_merge($this->changedItems, $changed); // merge the two change-lists, preserving keys
$this->changedItems = array_combine(array_merge(array_keys($this->changedItems), array_keys($changed)), array_merge($this->changedItems, $changed));
} }
// TODO: fetch full content when appropriate // TODO: fetch full content when appropriate
return true; return true;
@ -255,7 +256,7 @@ class Feed {
} }
public function computeNextFetch(): \DateTime { public function computeNextFetch(): \DateTime {
$now = new \DateTime(); $now = $this->dateNormalize(time());
if(!$this->modified) { if(!$this->modified) {
$diff = $now->getTimestamp() - $this->lastModified->getTimestamp(); $diff = $now->getTimestamp() - $this->lastModified->getTimestamp();
$offset = $this->normalizeDateDiff($diff); $offset = $this->normalizeDateDiff($diff);
@ -294,7 +295,7 @@ class Feed {
} else { } else {
$offset = "1 day"; $offset = "1 day";
} }
return new \DateTime("now + ".$offset); return self::dateNormalize("now + ".$offset);
} }
protected function normalizeDateDiff(int $diff): string { protected function normalizeDateDiff(int $diff): string {
@ -313,15 +314,10 @@ class Feed {
} }
public function computeLastModified() { public function computeLastModified() {
if(!$this->modified) { if(!$this->modified) return $this->lastModified;
return $this->lastModified; $dates = $this->gatherDates();
} else {
$dates = $this->gatherDates();
}
if(sizeof($dates)) { if(sizeof($dates)) {
$now = new \DateTime(); return $this->dateNormalize($dates[0]);
$now->setTimestamp($dates[0]);
return $now;
} else { } else {
return null; return null;
} }

3
lib/Misc/DateFormatter.php

@ -51,7 +51,8 @@ trait DateFormatter {
} else { } else {
$time = (int) $date; $time = (int) $date;
} }
$d = new \DateTime(); $tz = (!$inLocal) ? new \DateTimeZone("UTC") : null;
$d = new \DateTime("now", $tz);
$d->setTimestamp($time); $d->setTimestamp($time);
return $d; return $d;
} }

16
lib/User.php

@ -111,11 +111,20 @@ class User {
$this->actor = []; $this->actor = [];
switch($this->u->driverFunctions("auth")) { switch($this->u->driverFunctions("auth")) {
case User\Driver::FUNC_EXTERNAL: case User\Driver::FUNC_EXTERNAL:
$out = $this->u->auth($user, $password); if(Data::$conf->userPreAuth) {
$out = true;
} else {
$out = $this->u->auth($user, $password);
}
if($out && !Data::$db->userExists($user)) $this->autoProvision($user, $password); if($out && !Data::$db->userExists($user)) $this->autoProvision($user, $password);
return $out; return $out;
case User\Driver::FUNC_INTERNAL: case User\Driver::FUNC_INTERNAL:
return $this->u->auth($user, $password); if(Data::$conf->userPreAuth) {
if(!Data::$db->userExists($user)) $this->autoProvision($user, $password);
return true;
} else {
return $this->u->auth($user, $password);
}
case User\Driver::FUNCT_NOT_IMPLEMENTED: case User\Driver::FUNCT_NOT_IMPLEMENTED:
return false; return false;
} }
@ -125,8 +134,7 @@ class User {
public function authHTTP(): bool { public function authHTTP(): bool {
$cred = $this->credentials(); $cred = $this->credentials();
if(!$cred["user"]) return false; if(!$cred["user"]) return false;
if(!$this->auth($cred["user"], $cred["password"])) return false; return $this->auth($cred["user"], $cred["password"]);
return true;
} }
public function driverFunctions(string $function = null) { public function driverFunctions(string $function = null) {

20
sql/SQLite3/0.sql

@ -29,7 +29,7 @@ create table arsse_folders(
owner text not null references arsse_users(id) on delete cascade on update cascade, -- owner of folder owner text not null references arsse_users(id) on delete cascade on update cascade, -- owner of folder
parent integer references arsse_folders(id) on delete cascade, -- parent folder id parent integer references arsse_folders(id) on delete cascade, -- parent folder id
name text not null, -- folder name name text not null, -- folder name
modified datetime not null default CURRENT_TIMESTAMP, -- modified text not null default CURRENT_TIMESTAMP, --
unique(owner,name,parent) -- cannot have multiple folders with the same name under the same parent for the same owner unique(owner,name,parent) -- cannot have multiple folders with the same name under the same parent for the same owner
); );
@ -40,9 +40,9 @@ create table arsse_feeds(
title text, -- default title of feed title text, -- default title of feed
favicon text, -- URL of favicon favicon text, -- URL of favicon
source text, -- URL of site to which the feed belongs source text, -- URL of site to which the feed belongs
updated datetime, -- time at which the feed was last fetched updated text, -- time at which the feed was last fetched
modified datetime, -- time at which the feed last actually changed modified text, -- time at which the feed last actually changed
next_fetch datetime, -- time at which the feed should next be fetched next_fetch text, -- time at which the feed should next be fetched
etag text not null default '', -- HTTP ETag hash used for cache validation, changes each time the content changes etag text not null default '', -- HTTP ETag hash used for cache validation, changes each time the content changes
err_count integer not null default 0, -- count of successive times update resulted in error since last successful update err_count integer not null default 0, -- count of successive times update resulted in error since last successful update
err_msg text, -- last error message err_msg text, -- last error message
@ -56,8 +56,8 @@ create table arsse_subscriptions(
id integer primary key, -- sequence number id integer primary key, -- sequence number
owner text not null references arsse_users(id) on delete cascade on update cascade, -- owner of subscription owner text not null references arsse_users(id) on delete cascade on update cascade, -- owner of subscription
feed integer not null references arsse_feeds(id) on delete cascade, -- feed for the subscription feed integer not null references arsse_feeds(id) on delete cascade, -- feed for the subscription
added datetime not null default CURRENT_TIMESTAMP, -- time at which feed was added added text not null default CURRENT_TIMESTAMP, -- time at which feed was added
modified datetime not null default CURRENT_TIMESTAMP, -- date at which subscription properties were last modified modified text not null default CURRENT_TIMESTAMP, -- date at which subscription properties were last modified
title text, -- user-supplied title title text, -- user-supplied title
order_type int not null default 0, -- NextCloud sort order order_type int not null default 0, -- NextCloud sort order
pinned boolean not null default 0, -- whether feed is pinned (always sorts at top) pinned boolean not null default 0, -- whether feed is pinned (always sorts at top)
@ -72,9 +72,9 @@ create table arsse_articles(
url text, -- URL of article url text, -- URL of article
title text, -- article title title text, -- article title
author text, -- author's name author text, -- author's name
published datetime, -- time of original publication published text, -- time of original publication
edited datetime, -- time of last edit edited text, -- time of last edit
modified datetime not null default CURRENT_TIMESTAMP, -- date when article properties were last modified modified text not null default CURRENT_TIMESTAMP, -- date when article properties were last modified
content text, -- content, as (X)HTML content text, -- content, as (X)HTML
guid text, -- GUID guid text, -- GUID
url_title_hash text not null, -- hash of URL + title; used when checking for updates and for identification if there is no guid. url_title_hash text not null, -- hash of URL + title; used when checking for updates and for identification if there is no guid.
@ -96,7 +96,7 @@ create table arsse_marks(
owner text not null references arsse_users(id) on delete cascade on update cascade, owner text not null references arsse_users(id) on delete cascade on update cascade,
read boolean not null default 0, read boolean not null default 0,
starred boolean not null default 0, starred boolean not null default 0,
modified datetime not null default CURRENT_TIMESTAMP, modified text not null default CURRENT_TIMESTAMP,
unique(article,owner) unique(article,owner)
); );

1
tests/User/TestAuthorization.php

@ -48,6 +48,7 @@ class TestAuthorization extends Test\AbstractTest {
$this->clearData(); $this->clearData();
$conf = new Conf(); $conf = new Conf();
$conf->userDriver = $drv; $conf->userDriver = $drv;
$conf->userPreAuth = false;
$conf->userComposeNames = true; $conf->userComposeNames = true;
Data::$conf = $conf; Data::$conf = $conf;
if($db !== null) { if($db !== null) {

1
tests/lib/User/CommonTests.php

@ -13,6 +13,7 @@ trait CommonTests {
$this->clearData(); $this->clearData();
$conf = new Conf(); $conf = new Conf();
$conf->userDriver = $this->drv; $conf->userDriver = $this->drv;
$conf->userPreAuth = false;
Data::$conf = $conf; Data::$conf = $conf;
Data::$db = new Database(); Data::$db = new Database();
Data::$user = Phake::PartialMock(User::class); Data::$user = Phake::PartialMock(User::class);

Loading…
Cancel
Save