From d4674c61b2f4cc62b9fe74d79f2ab01ad3e1e412 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Sat, 15 Jul 2017 13:33:17 -0400 Subject: [PATCH] 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 --- lib/Conf.php | 4 +++- lib/Database.php | 2 +- lib/Feed.php | 18 +++++++----------- lib/Misc/DateFormatter.php | 3 ++- lib/User.php | 16 ++++++++++++---- sql/SQLite3/0.sql | 20 ++++++++++---------- tests/User/TestAuthorization.php | 1 + tests/lib/User/CommonTests.php | 1 + 8 files changed, 37 insertions(+), 28 deletions(-) diff --git a/lib/Conf.php b/lib/Conf.php index 55024669..5f0c9d95 100644 --- a/lib/Conf.php +++ b/lib/Conf.php @@ -23,11 +23,13 @@ class Conf { public $dbMySQLDb = "arsse"; public $userDriver = User\Internal\Driver::class; + public $userPreAuth = true; public $userComposeNames = true; public $userTempPasswordLength = 20; - public $serviceDriver = Service\Curl\Driver::class; + public $serviceDriver = Service\Internal\Driver::class; public $serviceFrequency = "PT2M"; + public $serviceQueueWidth = 5; public $serviceCurlBase = "http://localhost/"; public $serviceCurlUser = null; public $serviceCurlPassword = null; diff --git a/lib/Database.php b/lib/Database.php index 848f08ca..ee4a2520 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -442,7 +442,7 @@ class Database { // 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 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 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); diff --git a/lib/Feed.php b/lib/Feed.php index f9f6552a..e5f12193 100644 --- a/lib/Feed.php +++ b/lib/Feed.php @@ -209,7 +209,8 @@ class Feed { } $articles = Data::$db->feedMatchIds($feedID, $ids, $hashesUT, $hashesUC, $hashesTC)->getAll(); 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 return true; @@ -255,7 +256,7 @@ class Feed { } public function computeNextFetch(): \DateTime { - $now = new \DateTime(); + $now = $this->dateNormalize(time()); if(!$this->modified) { $diff = $now->getTimestamp() - $this->lastModified->getTimestamp(); $offset = $this->normalizeDateDiff($diff); @@ -294,7 +295,7 @@ class Feed { } else { $offset = "1 day"; } - return new \DateTime("now + ".$offset); + return self::dateNormalize("now + ".$offset); } protected function normalizeDateDiff(int $diff): string { @@ -313,15 +314,10 @@ class Feed { } public function computeLastModified() { - if(!$this->modified) { - return $this->lastModified; - } else { - $dates = $this->gatherDates(); - } + if(!$this->modified) return $this->lastModified; + $dates = $this->gatherDates(); if(sizeof($dates)) { - $now = new \DateTime(); - $now->setTimestamp($dates[0]); - return $now; + return $this->dateNormalize($dates[0]); } else { return null; } diff --git a/lib/Misc/DateFormatter.php b/lib/Misc/DateFormatter.php index 6bb44850..a72e2f32 100644 --- a/lib/Misc/DateFormatter.php +++ b/lib/Misc/DateFormatter.php @@ -51,7 +51,8 @@ trait DateFormatter { } else { $time = (int) $date; } - $d = new \DateTime(); + $tz = (!$inLocal) ? new \DateTimeZone("UTC") : null; + $d = new \DateTime("now", $tz); $d->setTimestamp($time); return $d; } diff --git a/lib/User.php b/lib/User.php index ac0e5ae3..68118473 100644 --- a/lib/User.php +++ b/lib/User.php @@ -111,11 +111,20 @@ class User { $this->actor = []; switch($this->u->driverFunctions("auth")) { 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); return $out; 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: return false; } @@ -125,8 +134,7 @@ class User { public function authHTTP(): bool { $cred = $this->credentials(); if(!$cred["user"]) return false; - if(!$this->auth($cred["user"], $cred["password"])) return false; - return true; + return $this->auth($cred["user"], $cred["password"]); } public function driverFunctions(string $function = null) { diff --git a/sql/SQLite3/0.sql b/sql/SQLite3/0.sql index f33154ba..f42f7c89 100644 --- a/sql/SQLite3/0.sql +++ b/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 parent integer references arsse_folders(id) on delete cascade, -- parent folder id 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 ); @@ -40,9 +40,9 @@ create table arsse_feeds( title text, -- default title of feed favicon text, -- URL of favicon source text, -- URL of site to which the feed belongs - updated datetime, -- time at which the feed was last fetched - modified datetime, -- time at which the feed last actually changed - next_fetch datetime, -- time at which the feed should next be fetched + updated text, -- time at which the feed was last fetched + modified text, -- time at which the feed last actually changed + 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 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 @@ -56,8 +56,8 @@ create table arsse_subscriptions( id integer primary key, -- sequence number 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 - added datetime 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 + added text not null default CURRENT_TIMESTAMP, -- time at which feed was added + modified text not null default CURRENT_TIMESTAMP, -- date at which subscription properties were last modified title text, -- user-supplied title order_type int not null default 0, -- NextCloud sort order 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 title text, -- article title author text, -- author's name - published datetime, -- time of original publication - edited datetime, -- time of last edit - modified datetime not null default CURRENT_TIMESTAMP, -- date when article properties were last modified + published text, -- time of original publication + edited text, -- time of last edit + modified text not null default CURRENT_TIMESTAMP, -- date when article properties were last modified content text, -- content, as (X)HTML 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. @@ -96,7 +96,7 @@ create table arsse_marks( owner text not null references arsse_users(id) on delete cascade on update cascade, read 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) ); diff --git a/tests/User/TestAuthorization.php b/tests/User/TestAuthorization.php index f8e322f3..0cf8a6e8 100644 --- a/tests/User/TestAuthorization.php +++ b/tests/User/TestAuthorization.php @@ -48,6 +48,7 @@ class TestAuthorization extends Test\AbstractTest { $this->clearData(); $conf = new Conf(); $conf->userDriver = $drv; + $conf->userPreAuth = false; $conf->userComposeNames = true; Data::$conf = $conf; if($db !== null) { diff --git a/tests/lib/User/CommonTests.php b/tests/lib/User/CommonTests.php index c7d66970..ed506c77 100644 --- a/tests/lib/User/CommonTests.php +++ b/tests/lib/User/CommonTests.php @@ -13,6 +13,7 @@ trait CommonTests { $this->clearData(); $conf = new Conf(); $conf->userDriver = $this->drv; + $conf->userPreAuth = false; Data::$conf = $conf; Data::$db = new Database(); Data::$user = Phake::PartialMock(User::class);