mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 13:12:41 +00:00
Strip out remnants of the authorizer
This commit is contained in:
parent
576d7e16a8
commit
771f79323c
19 changed files with 71 additions and 672 deletions
|
@ -73,7 +73,6 @@ abstract class AbstractException extends \Exception {
|
|||
"User/Exception.alreadyExists" => 10403,
|
||||
"User/Exception.authMissing" => 10411,
|
||||
"User/Exception.authFailed" => 10412,
|
||||
"User/ExceptionAuthz.notAuthorized" => 10421,
|
||||
"User/ExceptionSession.invalid" => 10431,
|
||||
"User/ExceptionInput.invalidTimezone" => 10441,
|
||||
"User/ExceptionInput.invalidBoolean" => 10442,
|
||||
|
|
166
lib/Database.php
166
lib/Database.php
|
@ -242,9 +242,6 @@ class Database {
|
|||
|
||||
/** Returns whether the specified user exists in the database */
|
||||
public function userExists(string $user): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
return (bool) $this->db->prepare("SELECT count(*) from arsse_users where id = ?", "str")->run($user)->getValue();
|
||||
}
|
||||
|
||||
|
@ -254,9 +251,7 @@ class Database {
|
|||
* @param string $passwordThe user's password in cleartext. It will be stored hashed
|
||||
*/
|
||||
public function userAdd(string $user, string $password): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
} elseif ($this->userExists($user)) {
|
||||
if ($this->userExists($user)) {
|
||||
throw new User\Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$hash = (strlen($password) > 0) ? password_hash($password, \PASSWORD_DEFAULT) : "";
|
||||
|
@ -267,9 +262,6 @@ class Database {
|
|||
|
||||
/** Removes a user from the database */
|
||||
public function userRemove(string $user): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
if ($this->db->prepare("DELETE from arsse_users where id = ?", "str")->run($user)->changes() < 1) {
|
||||
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
|
@ -279,9 +271,6 @@ class Database {
|
|||
/** Returns a flat, indexed array of all users in the database */
|
||||
public function userList(): array {
|
||||
$out = [];
|
||||
if (!Arsse::$user->authorize("", __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => ""]);
|
||||
}
|
||||
foreach ($this->db->query("SELECT id from arsse_users") as $user) {
|
||||
$out[] = $user['id'];
|
||||
}
|
||||
|
@ -290,9 +279,7 @@ class Database {
|
|||
|
||||
/** Retrieves the hashed password of a user */
|
||||
public function userPasswordGet(string $user): ?string {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
} elseif (!$this->userExists($user)) {
|
||||
if (!$this->userExists($user)) {
|
||||
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
return $this->db->prepare("SELECT password from arsse_users where id = ?", "str")->run($user)->getValue();
|
||||
|
@ -304,9 +291,7 @@ class Database {
|
|||
* @param string $password The new password, in cleartext. The password will be stored hashed. If null is passed, the password is unset and authentication not possible
|
||||
*/
|
||||
public function userPasswordSet(string $user, string $password = null): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
} elseif (!$this->userExists($user)) {
|
||||
if (!$this->userExists($user)) {
|
||||
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$hash = (strlen($password ?? "") > 0) ? password_hash($password, \PASSWORD_DEFAULT) : $password;
|
||||
|
@ -315,9 +300,7 @@ class Database {
|
|||
}
|
||||
|
||||
public function userPropertiesGet(string $user): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
} elseif (!$this->userExists($user)) {
|
||||
if (!$this->userExists($user)) {
|
||||
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$out = $this->db->prepare("SELECT num, admin, lang, tz, sort_asc from arsse_users where id = ?", "str")->run($user)->getRow();
|
||||
|
@ -327,9 +310,7 @@ class Database {
|
|||
}
|
||||
|
||||
public function userPropertiesSet(string $user, array $data): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
} elseif (!$this->userExists($user)) {
|
||||
if (!$this->userExists($user)) {
|
||||
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$allowed = [
|
||||
|
@ -339,16 +320,12 @@ class Database {
|
|||
'sort_asc' => "strict bool",
|
||||
];
|
||||
[$setClause, $setTypes, $setValues] = $this->generateSet($data, $allowed);
|
||||
return (bool) $this->$db->prepare("UPDATE arsse_users set $setClause where user = ?", $setTypes, "str")->run($setValues, $user)->changes();
|
||||
return (bool) $this->db->prepare("UPDATE arsse_users set $setClause where user = ?", $setTypes, "str")->run($setValues, $user)->changes();
|
||||
|
||||
}
|
||||
|
||||
/** Creates a new session for the given user and returns the session identifier */
|
||||
public function sessionCreate(string $user): string {
|
||||
// If the user isn't authorized to perform this action then throw an exception.
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// generate a new session ID and expiry date
|
||||
$id = UUID::mint()->hex;
|
||||
$expires = Date::add(Arsse::$conf->userSessionTimeout);
|
||||
|
@ -367,10 +344,6 @@ class Database {
|
|||
* @param string|null $id The identifier of the session to destroy
|
||||
*/
|
||||
public function sessionDestroy(string $user, string $id = null): bool {
|
||||
// If the user isn't authorized to perform this action then throw an exception.
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
if (is_null($id)) {
|
||||
// delete all sessions and report success unconditionally if no identifier was specified
|
||||
$this->db->prepare("DELETE FROM arsse_sessions where \"user\" = ?", "str")->run($user);
|
||||
|
@ -424,10 +397,7 @@ class Database {
|
|||
* @param \DateTimeInterface|null $expires An optional expiry date and time for the token
|
||||
*/
|
||||
public function tokenCreate(string $user, string $class, string $id = null, \DateTimeInterface $expires = null): string {
|
||||
// If the user isn't authorized to perform this action then throw an exception.
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
} elseif (!$this->userExists($user)) {
|
||||
if (!$this->userExists($user)) {
|
||||
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// generate a token if it's not provided
|
||||
|
@ -445,10 +415,6 @@ class Database {
|
|||
* @param string|null $id The ID of a specific token, or null for all tokens in the class
|
||||
*/
|
||||
public function tokenRevoke(string $user, string $class, string $id = null): bool {
|
||||
// If the user isn't authorized to perform this action then throw an exception.
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
if (is_null($id)) {
|
||||
$out = $this->db->prepare("DELETE FROM arsse_tokens where \"user\" = ? and class = ?", "str", "str")->run($user, $class)->changes();
|
||||
} else {
|
||||
|
@ -484,10 +450,6 @@ class Database {
|
|||
* @param array $data An associative array defining the folder
|
||||
*/
|
||||
public function folderAdd(string $user, array $data): int {
|
||||
// If the user isn't authorized to perform this action then throw an exception.
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// normalize folder's parent, if there is one
|
||||
$parent = array_key_exists("parent", $data) ? $this->folderValidateId($user, $data['parent'])['id'] : null;
|
||||
// validate the folder name and parent (if specified); this also checks for duplicates
|
||||
|
@ -512,10 +474,6 @@ class Database {
|
|||
* @param boolean $recursive Whether to list all descendents (true) or only direct children (false)
|
||||
*/
|
||||
public function folderList(string $user, $parent = null, bool $recursive = true): Db\Result {
|
||||
// if the user isn't authorized to perform this action then throw an exception.
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// check to make sure the parent exists, if one is specified
|
||||
$parent = $this->folderValidateId($user, $parent)['id'];
|
||||
$q = new Query(
|
||||
|
@ -548,9 +506,6 @@ class Database {
|
|||
* @param integer $id The identifier of the folder to delete
|
||||
*/
|
||||
public function folderRemove(string $user, $id): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
if (!ValueInfo::id($id)) {
|
||||
throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "folder", 'type' => "int > 0"]);
|
||||
}
|
||||
|
@ -563,9 +518,6 @@ class Database {
|
|||
|
||||
/** Returns the identifier, name, and parent of the given folder as an associative array */
|
||||
public function folderPropertiesGet(string $user, $id): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
if (!ValueInfo::id($id)) {
|
||||
throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "folder", 'type' => "int > 0"]);
|
||||
}
|
||||
|
@ -590,9 +542,6 @@ class Database {
|
|||
* @param array $data An associative array of properties to modify. Anything not specified will remain unchanged
|
||||
*/
|
||||
public function folderPropertiesSet(string $user, $id, array $data): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// verify the folder belongs to the user
|
||||
$in = $this->folderValidateId($user, $id, true);
|
||||
$name = array_key_exists("name", $data);
|
||||
|
@ -739,9 +688,6 @@ class Database {
|
|||
* @param boolean $discover Whether to perform newsfeed discovery if $url points to an HTML document
|
||||
*/
|
||||
public function subscriptionAdd(string $user, string $url, string $fetchUser = "", string $fetchPassword = "", bool $discover = true): int {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// get the ID of the underlying feed, or add it if it's not yet in the database
|
||||
$feedID = $this->feedAdd($url, $fetchUser, $fetchPassword, $discover);
|
||||
// Add the feed to the user's subscriptions and return the new subscription's ID.
|
||||
|
@ -756,9 +702,6 @@ class Database {
|
|||
* @param integer|null $id The numeric identifier of a particular subscription; used internally by subscriptionPropertiesGet
|
||||
*/
|
||||
public function subscriptionList(string $user, $folder = null, bool $recursive = true, int $id = null): Db\Result {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// validate inputs
|
||||
$folder = $this->folderValidateId($user, $folder)['id'];
|
||||
// create a complex query
|
||||
|
@ -804,9 +747,6 @@ class Database {
|
|||
|
||||
/** Returns the number of subscriptions in a folder, counting recursively */
|
||||
public function subscriptionCount(string $user, $folder = null): int {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// validate inputs
|
||||
$folder = $this->folderValidateId($user, $folder)['id'];
|
||||
// create a complex query
|
||||
|
@ -829,9 +769,6 @@ class Database {
|
|||
* configurable retention period for newsfeeds
|
||||
*/
|
||||
public function subscriptionRemove(string $user, $id): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
if (!ValueInfo::id($id)) {
|
||||
throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "feed", 'type' => "int > 0"]);
|
||||
}
|
||||
|
@ -861,9 +798,6 @@ class Database {
|
|||
* - "unread": The number of unread articles associated with the subscription
|
||||
*/
|
||||
public function subscriptionPropertiesGet(string $user, $id): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
if (!ValueInfo::id($id)) {
|
||||
throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "feed", 'type' => "int > 0"]);
|
||||
}
|
||||
|
@ -888,9 +822,6 @@ class Database {
|
|||
* @param array $data An associative array of properties to modify; any keys not specified will be left unchanged
|
||||
*/
|
||||
public function subscriptionPropertiesSet(string $user, $id, array $data): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$tr = $this->db->begin();
|
||||
// validate the ID
|
||||
$id = $this->subscriptionValidateId($user, $id, true)['id'];
|
||||
|
@ -934,9 +865,6 @@ class Database {
|
|||
* @param boolean $byName Whether to return the tag names (true) instead of the numeric tag identifiers (false)
|
||||
*/
|
||||
public function subscriptionTagsGet(string $user, $id, bool $byName = false): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$this->subscriptionValidateId($user, $id, true);
|
||||
$field = !$byName ? "id" : "name";
|
||||
$out = $this->db->prepare("SELECT $field from arsse_tags where id in (select tag from arsse_tag_members where subscription = ? and assigned = 1) order by $field", "int")->run($id)->getAll();
|
||||
|
@ -961,9 +889,6 @@ class Database {
|
|||
$q = new Query("SELECT i.id, i.url, i.type, $data from arsse_subscriptions as s join arsse_feeds as f on s.feed = f.id left join arsse_icons as i on f.icon = i.id");
|
||||
$q->setWhere("s.id = ?", "int", $id);
|
||||
if (isset($user)) {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$q->setWhere("s.owner = ?", "str", $user);
|
||||
}
|
||||
$out = $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->getRow();
|
||||
|
@ -975,9 +900,6 @@ class Database {
|
|||
|
||||
/** Returns the time at which any of a user's subscriptions (or a specific subscription) was last refreshed, as a DateTimeImmutable object */
|
||||
public function subscriptionRefreshed(string $user, int $id = null): ?\DateTimeImmutable {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$q = new Query("SELECT max(arsse_feeds.updated) from arsse_feeds join arsse_subscriptions on arsse_subscriptions.feed = arsse_feeds.id");
|
||||
$q->setWhere("arsse_subscriptions.owner = ?", "str", $user);
|
||||
if ($id) {
|
||||
|
@ -1304,9 +1226,6 @@ class Database {
|
|||
* @param string $user The user whose subscription icons are to be retrieved
|
||||
*/
|
||||
public function iconList(string $user): Db\Result {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
return $this->db->prepare("SELECT distinct i.id, i.url, i.type, i.data from arsse_icons as i join arsse_feeds as f on i.id = f.icon join arsse_subscriptions as s on s.feed = f.id where s.owner = ?", "str")->run($user);
|
||||
}
|
||||
|
||||
|
@ -1646,9 +1565,6 @@ class Database {
|
|||
* @param array $sort The columns to sort the result by eg. "edition desc" in decreasing order of importance
|
||||
*/
|
||||
public function articleList(string $user, Context $context = null, array $fields = ["id"], array $sort = []): Db\Result {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// make a base query based on context and output columns
|
||||
$context = $context ?? new Context;
|
||||
$q = $this->articleQuery($user, $context, $fields);
|
||||
|
@ -1693,9 +1609,6 @@ class Database {
|
|||
* @param Context $context The search context
|
||||
*/
|
||||
public function articleCount(string $user, Context $context = null): int {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$context = $context ?? new Context;
|
||||
$q = $this->articleQuery($user, $context, []);
|
||||
return (int) $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->getValue();
|
||||
|
@ -1714,9 +1627,6 @@ class Database {
|
|||
* @param Context $context The query context to match articles against
|
||||
*/
|
||||
public function articleMark(string $user, array $data, Context $context = null): int {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$data = [
|
||||
'read' => $data['read'] ?? null,
|
||||
'starred' => $data['starred'] ?? null,
|
||||
|
@ -1800,9 +1710,6 @@ class Database {
|
|||
* - "read": The count of starred articles which are read
|
||||
*/
|
||||
public function articleStarred(string $user): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
return $this->db->prepare(
|
||||
"SELECT
|
||||
count(*) as total,
|
||||
|
@ -1822,9 +1729,6 @@ class Database {
|
|||
* @param boolean $byName Whether to return the label names (true) instead of the numeric label identifiers (false)
|
||||
*/
|
||||
public function articleLabelsGet(string $user, $id, bool $byName = false): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$id = $this->articleValidateId($user, $id)['article'];
|
||||
$field = !$byName ? "id" : "name";
|
||||
$out = $this->db->prepare("SELECT $field from arsse_labels join arsse_label_members on arsse_label_members.label = arsse_labels.id where owner = ? and article = ? and assigned = 1 order by $field", "str", "int")->run($user, $id)->getAll();
|
||||
|
@ -1833,9 +1737,6 @@ class Database {
|
|||
|
||||
/** Returns the author-supplied categories associated with an article */
|
||||
public function articleCategoriesGet(string $user, $id): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$id = $this->articleValidateId($user, $id)['article'];
|
||||
$out = $this->db->prepare("SELECT name from arsse_categories where article = ? order by name", "int")->run($id)->getAll();
|
||||
if (!$out) {
|
||||
|
@ -1937,9 +1838,6 @@ class Database {
|
|||
|
||||
/** Returns the numeric identifier of the most recent edition of an article matching the given context */
|
||||
public function editionLatest(string $user, Context $context = null): int {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$context = $context ?? new Context;
|
||||
$q = new Query("SELECT max(arsse_editions.id) from arsse_editions left join arsse_articles on article = arsse_articles.id join arsse_subscriptions on arsse_articles.feed = arsse_subscriptions.feed and arsse_subscriptions.owner = ?", "str", $user);
|
||||
if ($context->subscription()) {
|
||||
|
@ -1968,10 +1866,6 @@ class Database {
|
|||
* @param array $data An associative array defining the label's properties; currently only "name" is understood
|
||||
*/
|
||||
public function labelAdd(string $user, array $data): int {
|
||||
// if the user isn't authorized to perform this action then throw an exception.
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// validate the label name
|
||||
$name = array_key_exists("name", $data) ? $data['name'] : "";
|
||||
$this->labelValidateName($name, true);
|
||||
|
@ -1992,10 +1886,6 @@ class Database {
|
|||
* @param boolean $includeEmpty Whether to include (true) or supress (false) labels which have no articles assigned to them
|
||||
*/
|
||||
public function labelList(string $user, bool $includeEmpty = true): Db\Result {
|
||||
// if the user isn't authorized to perform this action then throw an exception.
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
return $this->db->prepare(
|
||||
"SELECT * FROM (
|
||||
SELECT
|
||||
|
@ -2032,9 +1922,6 @@ class Database {
|
|||
* @param boolean $byName Whether to interpret the $id parameter as the label's name (true) or identifier (false)
|
||||
*/
|
||||
public function labelRemove(string $user, $id, bool $byName = false): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$this->labelValidateId($user, $id, $byName, false);
|
||||
$field = $byName ? "name" : "id";
|
||||
$type = $byName ? "str" : "int";
|
||||
|
@ -2059,9 +1946,6 @@ class Database {
|
|||
* @param boolean $byName Whether to interpret the $id parameter as the label's name (true) or identifier (false)
|
||||
*/
|
||||
public function labelPropertiesGet(string $user, $id, bool $byName = false): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$this->labelValidateId($user, $id, $byName, false);
|
||||
$field = $byName ? "name" : "id";
|
||||
$type = $byName ? "str" : "int";
|
||||
|
@ -2101,9 +1985,6 @@ class Database {
|
|||
* @param boolean $byName Whether to interpret the $id parameter as the label's name (true) or identifier (false)
|
||||
*/
|
||||
public function labelPropertiesSet(string $user, $id, array $data, bool $byName = false): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$this->labelValidateId($user, $id, $byName, false);
|
||||
if (isset($data['name'])) {
|
||||
$this->labelValidateName($data['name']);
|
||||
|
@ -2132,9 +2013,6 @@ class Database {
|
|||
* @param boolean $byName Whether to interpret the $id parameter as the label's name (true) or identifier (false)
|
||||
*/
|
||||
public function labelArticlesGet(string $user, $id, bool $byName = false): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// just do a syntactic check on the label ID
|
||||
$this->labelValidateId($user, $id, $byName, false);
|
||||
$field = !$byName ? "id" : "name";
|
||||
|
@ -2161,9 +2039,6 @@ class Database {
|
|||
*/
|
||||
public function labelArticlesSet(string $user, $id, Context $context, int $mode = self::ASSOC_ADD, bool $byName = false): int {
|
||||
assert(in_array($mode, [self::ASSOC_ADD, self::ASSOC_REMOVE, self::ASSOC_REPLACE]), new Exception("constantUnknown", $mode));
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// validate the tag ID, and get the numeric ID if matching by name
|
||||
$id = $this->labelValidateId($user, $id, $byName, true)['id'];
|
||||
// get the list of articles matching the context
|
||||
|
@ -2269,10 +2144,6 @@ class Database {
|
|||
* @param array $data An associative array defining the tag's properties; currently only "name" is understood
|
||||
*/
|
||||
public function tagAdd(string $user, array $data): int {
|
||||
// if the user isn't authorized to perform this action then throw an exception.
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// validate the tag name
|
||||
$name = array_key_exists("name", $data) ? $data['name'] : "";
|
||||
$this->tagValidateName($name, true);
|
||||
|
@ -2292,10 +2163,6 @@ class Database {
|
|||
* @param boolean $includeEmpty Whether to include (true) or supress (false) tags which have no subscriptions assigned to them
|
||||
*/
|
||||
public function tagList(string $user, bool $includeEmpty = true): Db\Result {
|
||||
// if the user isn't authorized to perform this action then throw an exception.
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
return $this->db->prepare(
|
||||
"SELECT * FROM (
|
||||
SELECT
|
||||
|
@ -2323,10 +2190,6 @@ class Database {
|
|||
* @param string $user The user whose tags are to be listed
|
||||
*/
|
||||
public function tagSummarize(string $user): Db\Result {
|
||||
// if the user isn't authorized to perform this action then throw an exception.
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
return $this->db->prepare(
|
||||
"SELECT
|
||||
arsse_tags.id as id,
|
||||
|
@ -2348,9 +2211,6 @@ class Database {
|
|||
* @param boolean $byName Whether to interpret the $id parameter as the tag's name (true) or identifier (false)
|
||||
*/
|
||||
public function tagRemove(string $user, $id, bool $byName = false): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$this->tagValidateId($user, $id, $byName, false);
|
||||
$field = $byName ? "name" : "id";
|
||||
$type = $byName ? "str" : "int";
|
||||
|
@ -2374,9 +2234,6 @@ class Database {
|
|||
* @param boolean $byName Whether to interpret the $id parameter as the tag's name (true) or identifier (false)
|
||||
*/
|
||||
public function tagPropertiesGet(string $user, $id, bool $byName = false): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$this->tagValidateId($user, $id, $byName, false);
|
||||
$field = $byName ? "name" : "id";
|
||||
$type = $byName ? "str" : "int";
|
||||
|
@ -2404,9 +2261,6 @@ class Database {
|
|||
* @param boolean $byName Whether to interpret the $id parameter as the tag's name (true) or identifier (false)
|
||||
*/
|
||||
public function tagPropertiesSet(string $user, $id, array $data, bool $byName = false): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$this->tagValidateId($user, $id, $byName, false);
|
||||
if (isset($data['name'])) {
|
||||
$this->tagValidateName($data['name']);
|
||||
|
@ -2435,9 +2289,6 @@ class Database {
|
|||
* @param boolean $byName Whether to interpret the $id parameter as the tag's name (true) or identifier (false)
|
||||
*/
|
||||
public function tagSubscriptionsGet(string $user, $id, bool $byName = false): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// just do a syntactic check on the tag ID
|
||||
$this->tagValidateId($user, $id, $byName, false);
|
||||
$field = !$byName ? "id" : "name";
|
||||
|
@ -2464,9 +2315,6 @@ class Database {
|
|||
*/
|
||||
public function tagSubscriptionsSet(string $user, $id, array $subscriptions, int $mode = self::ASSOC_ADD, bool $byName = false): int {
|
||||
assert(in_array($mode, [self::ASSOC_ADD, self::ASSOC_REMOVE, self::ASSOC_REPLACE]), new Exception("constantUnknown", $mode));
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
// validate the tag ID, and get the numeric ID if matching by name
|
||||
$id = $this->tagValidateId($user, $id, $byName, true)['id'];
|
||||
// an empty subscription list is a special case
|
||||
|
|
31
lib/User.php
31
lib/User.php
|
@ -27,11 +27,6 @@ class User {
|
|||
return (string) $this->id;
|
||||
}
|
||||
|
||||
public function authorize(string $affectedUser, string $action): bool {
|
||||
// at one time there was a complicated authorization system; it exists vestigially to support a later revival if desired
|
||||
return $this->u->authorize($affectedUser, $action);
|
||||
}
|
||||
|
||||
public function auth(string $user, string $password): bool {
|
||||
$prevUser = $this->id;
|
||||
$this->id = $user;
|
||||
|
@ -50,34 +45,18 @@ class User {
|
|||
}
|
||||
|
||||
public function list(): array {
|
||||
$func = "userList";
|
||||
if (!$this->authorize("", $func)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => ""]);
|
||||
}
|
||||
return $this->u->userList();
|
||||
}
|
||||
|
||||
public function exists(string $user): bool {
|
||||
$func = "userExists";
|
||||
if (!$this->authorize($user, $func)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]);
|
||||
}
|
||||
return $this->u->userExists($user);
|
||||
}
|
||||
|
||||
public function add($user, $password = null): string {
|
||||
$func = "userAdd";
|
||||
if (!$this->authorize($user, $func)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]);
|
||||
}
|
||||
return $this->u->userAdd($user, $password) ?? $this->u->userAdd($user, $this->generatePassword());
|
||||
}
|
||||
|
||||
public function remove(string $user): bool {
|
||||
$func = "userRemove";
|
||||
if (!$this->authorize($user, $func)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]);
|
||||
}
|
||||
try {
|
||||
return $this->u->userRemove($user);
|
||||
} finally { // @codeCoverageIgnore
|
||||
|
@ -89,10 +68,6 @@ class User {
|
|||
}
|
||||
|
||||
public function passwordSet(string $user, string $newPassword = null, $oldPassword = null): string {
|
||||
$func = "userPasswordSet";
|
||||
if (!$this->authorize($user, $func)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]);
|
||||
}
|
||||
$out = $this->u->userPasswordSet($user, $newPassword, $oldPassword) ?? $this->u->userPasswordSet($user, $this->generatePassword(), $oldPassword);
|
||||
if (Arsse::$db->userExists($user)) {
|
||||
// if the password change was successful and the user exists, set the internal password to the same value
|
||||
|
@ -104,10 +79,6 @@ class User {
|
|||
}
|
||||
|
||||
public function passwordUnset(string $user, $oldPassword = null): bool {
|
||||
$func = "userPasswordUnset";
|
||||
if (!$this->authorize($user, $func)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]);
|
||||
}
|
||||
$out = $this->u->userPasswordUnset($user, $oldPassword);
|
||||
if (Arsse::$db->userExists($user)) {
|
||||
// if the password change was successful and the user exists, set the internal password to the same value
|
||||
|
@ -154,7 +125,7 @@ class User {
|
|||
}
|
||||
}
|
||||
if (array_key_exists("lang", $data)) {
|
||||
$in['lang'] = V::normalize($data['lang'], V::T_STRING | M_NULL);
|
||||
$in['lang'] = V::normalize($data['lang'], V::T_STRING | V::M_NULL);
|
||||
}
|
||||
$out = $this->u->userPropertiesSet($user, $in);
|
||||
// synchronize the internal database
|
||||
|
|
|
@ -17,8 +17,6 @@ interface Driver {
|
|||
public static function driverName(): string;
|
||||
// authenticates a user against their name and password
|
||||
public function auth(string $user, string $password): bool;
|
||||
// check whether a user is authorized to perform a certain action; not currently used and subject to change
|
||||
public function authorize(string $affectedUser, string $action): bool;
|
||||
// checks whether a user exists
|
||||
public function userExists(string $user): bool;
|
||||
// adds a user
|
||||
|
|
|
@ -32,10 +32,6 @@ class Driver implements \JKingWeb\Arsse\User\Driver {
|
|||
return password_verify($password, $hash);
|
||||
}
|
||||
|
||||
public function authorize(string $affectedUser, string $action): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function userExists(string $user): bool {
|
||||
return Arsse::$db->userExists($user);
|
||||
}
|
||||
|
|
|
@ -138,11 +138,6 @@ return [
|
|||
'Exception.JKingWeb/Arsse/User/Exception.doesNotExist' => 'Could not perform action "{action}" because the user {user} does not exist',
|
||||
'Exception.JKingWeb/Arsse/User/Exception.authMissing' => 'Please log in to proceed',
|
||||
'Exception.JKingWeb/Arsse/User/Exception.authFailed' => 'Authentication failed',
|
||||
'Exception.JKingWeb/Arsse/User/ExceptionAuthz.notAuthorized' =>
|
||||
'{action, select,
|
||||
userList {Authenticated user is not authorized to view the user list}
|
||||
other {Authenticated user is not authorized to perform the action "{action}" on behalf of {user}}
|
||||
}',
|
||||
'Exception.JKingWeb/Arsse/User/ExceptionSession.invalid' => 'Session with ID {0} does not exist',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.internalError' => 'Could not download feed "{url}" because of an internal error which is probably a bug',
|
||||
'Exception.JKingWeb/Arsse/Feed/Exception.invalidCertificate' => 'Could not download feed "{url}" because its server is serving an invalid SSL certificate',
|
||||
|
|
|
@ -74,7 +74,6 @@ abstract class AbstractTest extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
Arsse::$db->driverSchemaUpdate();
|
||||
// create a mock user manager
|
||||
Arsse::$user = \Phake::mock(User::class);
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(true);
|
||||
// call the series-specific setup method
|
||||
$setUp = "setUp".$this->series;
|
||||
$this->$setUp();
|
||||
|
|
|
@ -597,12 +597,6 @@ trait SeriesArticle {
|
|||
];
|
||||
}
|
||||
|
||||
public function testListArticlesWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->articleList($this->user);
|
||||
}
|
||||
|
||||
public function testMarkNothing(): void {
|
||||
$this->assertSame(0, Arsse::$db->articleMark($this->user, []));
|
||||
}
|
||||
|
@ -967,12 +961,6 @@ trait SeriesArticle {
|
|||
$this->compareExpectations(static::$drv, $state);
|
||||
}
|
||||
|
||||
public function testMarkArticlesWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->articleMark($this->user, ['read' => false]);
|
||||
}
|
||||
|
||||
public function testCountArticles(): void {
|
||||
$setSize = (new \ReflectionClassConstant(Database::class, "LIMIT_SET_SIZE"))->getValue();
|
||||
$this->assertSame(2, Arsse::$db->articleCount("john.doe@example.com", (new Context)->starred(true)));
|
||||
|
@ -981,12 +969,6 @@ trait SeriesArticle {
|
|||
$this->assertSame(10, Arsse::$db->articleCount("john.doe@example.com", (new Context)->articles(range(1, $setSize * 3))));
|
||||
}
|
||||
|
||||
public function testCountArticlesWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->articleCount($this->user);
|
||||
}
|
||||
|
||||
public function testFetchStarredCounts(): void {
|
||||
$exp1 = ['total' => 2, 'unread' => 1, 'read' => 1];
|
||||
$exp2 = ['total' => 0, 'unread' => 0, 'read' => 0];
|
||||
|
@ -994,12 +976,6 @@ trait SeriesArticle {
|
|||
$this->assertEquals($exp2, Arsse::$db->articleStarred("jane.doe@example.com"));
|
||||
}
|
||||
|
||||
public function testFetchStarredCountsWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->articleStarred($this->user);
|
||||
}
|
||||
|
||||
public function testFetchLatestEdition(): void {
|
||||
$this->assertSame(1001, Arsse::$db->editionLatest($this->user));
|
||||
$this->assertSame(4, Arsse::$db->editionLatest($this->user, (new Context)->subscription(12)));
|
||||
|
@ -1010,12 +986,6 @@ trait SeriesArticle {
|
|||
Arsse::$db->editionLatest($this->user, (new Context)->subscription(1));
|
||||
}
|
||||
|
||||
public function testFetchLatestEditionWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->editionLatest($this->user);
|
||||
}
|
||||
|
||||
public function testListTheLabelsOfAnArticle(): void {
|
||||
$this->assertEquals([1,2], Arsse::$db->articleLabelsGet("john.doe@example.com", 1));
|
||||
$this->assertEquals([2], Arsse::$db->articleLabelsGet("john.doe@example.com", 5));
|
||||
|
@ -1030,12 +1000,6 @@ trait SeriesArticle {
|
|||
Arsse::$db->articleLabelsGet($this->user, 101);
|
||||
}
|
||||
|
||||
public function testListTheLabelsOfAnArticleWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->articleLabelsGet("john.doe@example.com", 1);
|
||||
}
|
||||
|
||||
public function testListTheCategoriesOfAnArticle(): void {
|
||||
$exp = ["Fascinating", "Logical"];
|
||||
$this->assertSame($exp, Arsse::$db->articleCategoriesGet($this->user, 19));
|
||||
|
@ -1050,12 +1014,6 @@ trait SeriesArticle {
|
|||
Arsse::$db->articleCategoriesGet($this->user, 101);
|
||||
}
|
||||
|
||||
public function testListTheCategoriesOfAnArticleWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->articleCategoriesGet($this->user, 19);
|
||||
}
|
||||
|
||||
/** @dataProvider provideArrayContextOptions */
|
||||
public function testUseTooFewValuesInArrayContext(string $option): void {
|
||||
$this->assertException("tooShort", "Db", "ExceptionInput");
|
||||
|
|
|
@ -102,7 +102,6 @@ trait SeriesFolder {
|
|||
$user = "john.doe@example.com";
|
||||
$folderID = $this->nextID("arsse_folders");
|
||||
$this->assertSame($folderID, Arsse::$db->folderAdd($user, ['name' => "Entertainment"]));
|
||||
\Phake::verify(Arsse::$user)->authorize($user, "folderAdd");
|
||||
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
||||
$state['arsse_folders']['rows'][] = [$folderID, $user, null, "Entertainment"];
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -117,7 +116,6 @@ trait SeriesFolder {
|
|||
$user = "john.doe@example.com";
|
||||
$folderID = $this->nextID("arsse_folders");
|
||||
$this->assertSame($folderID, Arsse::$db->folderAdd($user, ['name' => "GNOME", 'parent' => 2]));
|
||||
\Phake::verify(Arsse::$user)->authorize($user, "folderAdd");
|
||||
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
||||
$state['arsse_folders']['rows'][] = [$folderID, $user, 2, "GNOME"];
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -153,12 +151,6 @@ trait SeriesFolder {
|
|||
Arsse::$db->folderAdd("john.doe@example.com", ['name' => " "]);
|
||||
}
|
||||
|
||||
public function testAddAFolderWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->folderAdd("john.doe@example.com", ['name' => "Sociology"]);
|
||||
}
|
||||
|
||||
public function testListRootFolders(): void {
|
||||
$exp = [
|
||||
['id' => 5, 'name' => "Politics", 'parent' => null, 'children' => 0, 'feeds' => 2],
|
||||
|
@ -171,9 +163,6 @@ trait SeriesFolder {
|
|||
$this->assertResult($exp, Arsse::$db->folderList("jane.doe@example.com", null, false));
|
||||
$exp = [];
|
||||
$this->assertResult($exp, Arsse::$db->folderList("admin@example.net", null, false));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderList");
|
||||
\Phake::verify(Arsse::$user)->authorize("jane.doe@example.com", "folderList");
|
||||
\Phake::verify(Arsse::$user)->authorize("admin@example.net", "folderList");
|
||||
}
|
||||
|
||||
public function testListFoldersRecursively(): void {
|
||||
|
@ -193,8 +182,6 @@ trait SeriesFolder {
|
|||
$this->assertResult($exp, Arsse::$db->folderList("john.doe@example.com", 1, true));
|
||||
$exp = [];
|
||||
$this->assertResult($exp, Arsse::$db->folderList("jane.doe@example.com", 4, true));
|
||||
\Phake::verify(Arsse::$user, \Phake::times(2))->authorize("john.doe@example.com", "folderList");
|
||||
\Phake::verify(Arsse::$user)->authorize("jane.doe@example.com", "folderList");
|
||||
}
|
||||
|
||||
public function testListFoldersOfAMissingParent(): void {
|
||||
|
@ -207,15 +194,8 @@ trait SeriesFolder {
|
|||
Arsse::$db->folderList("john.doe@example.com", 4); // folder ID 4 belongs to Jane
|
||||
}
|
||||
|
||||
public function testListFoldersWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->folderList("john.doe@example.com");
|
||||
}
|
||||
|
||||
public function testRemoveAFolder(): void {
|
||||
$this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 6));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderRemove");
|
||||
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
||||
array_pop($state['arsse_folders']['rows']);
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -223,7 +203,6 @@ trait SeriesFolder {
|
|||
|
||||
public function testRemoveAFolderTree(): void {
|
||||
$this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 1));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderRemove");
|
||||
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
||||
foreach ([0,1,2,5] as $index) {
|
||||
unset($state['arsse_folders']['rows'][$index]);
|
||||
|
@ -246,12 +225,6 @@ trait SeriesFolder {
|
|||
Arsse::$db->folderRemove("john.doe@example.com", 4); // folder ID 4 belongs to Jane
|
||||
}
|
||||
|
||||
public function testRemoveAFolderWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->folderRemove("john.doe@example.com", 1);
|
||||
}
|
||||
|
||||
public function testGetThePropertiesOfAFolder(): void {
|
||||
$exp = [
|
||||
'id' => 6,
|
||||
|
@ -259,7 +232,6 @@ trait SeriesFolder {
|
|||
'parent' => 2,
|
||||
];
|
||||
$this->assertArraySubset($exp, Arsse::$db->folderPropertiesGet("john.doe@example.com", 6));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesGet");
|
||||
}
|
||||
|
||||
public function testGetThePropertiesOfAMissingFolder(): void {
|
||||
|
@ -277,19 +249,12 @@ trait SeriesFolder {
|
|||
Arsse::$db->folderPropertiesGet("john.doe@example.com", 4); // folder ID 4 belongs to Jane
|
||||
}
|
||||
|
||||
public function testGetThePropertiesOfAFolderWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->folderPropertiesGet("john.doe@example.com", 1);
|
||||
}
|
||||
|
||||
public function testMakeNoChangesToAFolder(): void {
|
||||
$this->assertFalse(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, []));
|
||||
}
|
||||
|
||||
public function testRenameAFolder(): void {
|
||||
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => "Opinion"]));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesSet");
|
||||
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
||||
$state['arsse_folders']['rows'][5][3] = "Opinion";
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -316,7 +281,6 @@ trait SeriesFolder {
|
|||
|
||||
public function testMoveAFolder(): void {
|
||||
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['parent' => 5]));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "folderPropertiesSet");
|
||||
$state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
|
||||
$state['arsse_folders']['rows'][5][2] = 5; // parent should have changed
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -371,10 +335,4 @@ trait SeriesFolder {
|
|||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||
Arsse::$db->folderPropertiesSet("john.doe@example.com", 4, ['parent' => null]); // folder ID 4 belongs to Jane
|
||||
}
|
||||
|
||||
public function testSetThePropertiesOfAFolderWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->folderPropertiesSet("john.doe@example.com", 1, ['parent' => null]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,10 +94,4 @@ trait SeriesIcon {
|
|||
];
|
||||
$this->assertResult($exp, Arsse::$db->iconList("jane.doe@example.com"));
|
||||
}
|
||||
|
||||
public function testListTheIconsOfAUserWithoutAuthority() {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->iconList("jane.doe@example.com");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,7 +253,6 @@ trait SeriesLabel {
|
|||
$user = "john.doe@example.com";
|
||||
$labelID = $this->nextID("arsse_labels");
|
||||
$this->assertSame($labelID, Arsse::$db->labelAdd($user, ['name' => "Entertaining"]));
|
||||
\Phake::verify(Arsse::$user)->authorize($user, "labelAdd");
|
||||
$state = $this->primeExpectations($this->data, $this->checkLabels);
|
||||
$state['arsse_labels']['rows'][] = [$labelID, $user, "Entertaining"];
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -279,12 +278,6 @@ trait SeriesLabel {
|
|||
Arsse::$db->labelAdd("john.doe@example.com", ['name' => " "]);
|
||||
}
|
||||
|
||||
public function testAddALabelWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->labelAdd("john.doe@example.com", ['name' => "Boring"]);
|
||||
}
|
||||
|
||||
public function testListLabels(): void {
|
||||
$exp = [
|
||||
['id' => 2, 'name' => "Fascinating", 'articles' => 3, 'read' => 1],
|
||||
|
@ -298,18 +291,10 @@ trait SeriesLabel {
|
|||
$this->assertResult($exp, Arsse::$db->labelList("jane.doe@example.com"));
|
||||
$exp = [];
|
||||
$this->assertResult($exp, Arsse::$db->labelList("jane.doe@example.com", false));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "labelList");
|
||||
}
|
||||
|
||||
public function testListLabelsWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->labelList("john.doe@example.com");
|
||||
}
|
||||
|
||||
public function testRemoveALabel(): void {
|
||||
$this->assertTrue(Arsse::$db->labelRemove("john.doe@example.com", 1));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "labelRemove");
|
||||
$state = $this->primeExpectations($this->data, $this->checkLabels);
|
||||
array_shift($state['arsse_labels']['rows']);
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -317,7 +302,6 @@ trait SeriesLabel {
|
|||
|
||||
public function testRemoveALabelByName(): void {
|
||||
$this->assertTrue(Arsse::$db->labelRemove("john.doe@example.com", "Interesting", true));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "labelRemove");
|
||||
$state = $this->primeExpectations($this->data, $this->checkLabels);
|
||||
array_shift($state['arsse_labels']['rows']);
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -343,12 +327,6 @@ trait SeriesLabel {
|
|||
Arsse::$db->labelRemove("john.doe@example.com", 3); // label ID 3 belongs to Jane
|
||||
}
|
||||
|
||||
public function testRemoveALabelWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->labelRemove("john.doe@example.com", 1);
|
||||
}
|
||||
|
||||
public function testGetThePropertiesOfALabel(): void {
|
||||
$exp = [
|
||||
'id' => 2,
|
||||
|
@ -358,7 +336,6 @@ trait SeriesLabel {
|
|||
];
|
||||
$this->assertArraySubset($exp, Arsse::$db->labelPropertiesGet("john.doe@example.com", 2));
|
||||
$this->assertArraySubset($exp, Arsse::$db->labelPropertiesGet("john.doe@example.com", "Fascinating", true));
|
||||
\Phake::verify(Arsse::$user, \Phake::times(2))->authorize("john.doe@example.com", "labelPropertiesGet");
|
||||
}
|
||||
|
||||
public function testGetThePropertiesOfAMissingLabel(): void {
|
||||
|
@ -381,19 +358,12 @@ trait SeriesLabel {
|
|||
Arsse::$db->labelPropertiesGet("john.doe@example.com", 3); // label ID 3 belongs to Jane
|
||||
}
|
||||
|
||||
public function testGetThePropertiesOfALabelWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->labelPropertiesGet("john.doe@example.com", 1);
|
||||
}
|
||||
|
||||
public function testMakeNoChangesToALabel(): void {
|
||||
$this->assertFalse(Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, []));
|
||||
}
|
||||
|
||||
public function testRenameALabel(): void {
|
||||
$this->assertTrue(Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, ['name' => "Curious"]));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "labelPropertiesSet");
|
||||
$state = $this->primeExpectations($this->data, $this->checkLabels);
|
||||
$state['arsse_labels']['rows'][0][2] = "Curious";
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -401,7 +371,6 @@ trait SeriesLabel {
|
|||
|
||||
public function testRenameALabelByName(): void {
|
||||
$this->assertTrue(Arsse::$db->labelPropertiesSet("john.doe@example.com", "Interesting", ['name' => "Curious"], true));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "labelPropertiesSet");
|
||||
$state = $this->primeExpectations($this->data, $this->checkLabels);
|
||||
$state['arsse_labels']['rows'][0][2] = "Curious";
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -447,12 +416,6 @@ trait SeriesLabel {
|
|||
Arsse::$db->labelPropertiesSet("john.doe@example.com", 3, ['name' => "Exciting"]); // label ID 3 belongs to Jane
|
||||
}
|
||||
|
||||
public function testSetThePropertiesOfALabelWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, ['name' => "Exciting"]);
|
||||
}
|
||||
|
||||
public function testListLabelledArticles(): void {
|
||||
$exp = [1,19];
|
||||
$this->assertEquals($exp, Arsse::$db->labelArticlesGet("john.doe@example.com", 1));
|
||||
|
@ -475,12 +438,6 @@ trait SeriesLabel {
|
|||
Arsse::$db->labelArticlesGet("john.doe@example.com", -1);
|
||||
}
|
||||
|
||||
public function testListLabelledArticlesWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->labelArticlesGet("john.doe@example.com", 1);
|
||||
}
|
||||
|
||||
public function testApplyALabelToArticles(): void {
|
||||
Arsse::$db->labelArticlesSet("john.doe@example.com", 1, (new Context)->articles([2,5]));
|
||||
$state = $this->primeExpectations($this->data, $this->checkMembers);
|
||||
|
@ -540,10 +497,4 @@ trait SeriesLabel {
|
|||
$state['arsse_label_members']['rows'][2][3] = 0;
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
}
|
||||
|
||||
public function testApplyALabelToArticlesWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->labelArticlesSet("john.doe@example.com", 1, (new Context)->articles([2,5]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,9 +70,6 @@ trait SeriesSession {
|
|||
$state = $this->primeExpectations($this->data, ['arsse_sessions' => ["id", "created", "expires", "user"]]);
|
||||
$state['arsse_sessions']['rows'][3][2] = Date::transform(Date::add(Arsse::$conf->userSessionTimeout, $now), "sql");
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
// session resumption should not check authorization
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertArraySubset($exp1, Arsse::$db->sessionResume("80fa94c1a11f11e78667001e673b2560"));
|
||||
}
|
||||
|
||||
public function testResumeAMissingSession(): void {
|
||||
|
@ -99,12 +96,6 @@ trait SeriesSession {
|
|||
$this->compareExpectations(static::$drv, $state);
|
||||
}
|
||||
|
||||
public function testCreateASessionWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->sessionCreate("jane.doe@example.com");
|
||||
}
|
||||
|
||||
public function testDestroyASession(): void {
|
||||
$user = "jane.doe@example.com";
|
||||
$id = "80fa94c1a11f11e78667001e673b2560";
|
||||
|
@ -131,10 +122,4 @@ trait SeriesSession {
|
|||
$id = "80fa94c1a11f11e78667001e673b2560";
|
||||
$this->assertFalse(Arsse::$db->sessionDestroy($user, $id));
|
||||
}
|
||||
|
||||
public function testDestroyASessionWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->sessionDestroy("jane.doe@example.com", "80fa94c1a11f11e78667001e673b2560");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,11 @@ trait SeriesSubscription {
|
|||
'next_fetch' => "datetime",
|
||||
'icon' => "int",
|
||||
],
|
||||
'rows' => [], // filled in the series setup
|
||||
'rows' => [
|
||||
[1,"http://example.com/feed1", "Ook", "", "",strtotime("now"),strtotime("now"),null],
|
||||
[2,"http://example.com/feed2", "eek", "", "",strtotime("now - 1 hour"),strtotime("now - 1 hour"),1],
|
||||
[3,"http://example.com/feed3", "Ack", "", "",strtotime("now + 1 hour"),strtotime("now + 1 hour"),null],
|
||||
],
|
||||
],
|
||||
'arsse_subscriptions' => [
|
||||
'columns' => [
|
||||
|
@ -144,11 +148,6 @@ trait SeriesSubscription {
|
|||
],
|
||||
],
|
||||
];
|
||||
$this->data['arsse_feeds']['rows'] = [
|
||||
[1,"http://example.com/feed1", "Ook", "", "",strtotime("now"),strtotime("now"),null],
|
||||
[2,"http://example.com/feed2", "eek", "", "",strtotime("now - 1 hour"),strtotime("now - 1 hour"),1],
|
||||
[3,"http://example.com/feed3", "Ack", "", "",strtotime("now + 1 hour"),strtotime("now + 1 hour"),null],
|
||||
];
|
||||
// initialize a partial mock of the Database object to later manipulate the feedUpdate method
|
||||
Arsse::$db = \Phake::partialMock(Database::class, static::$drv);
|
||||
$this->user = "john.doe@example.com";
|
||||
|
@ -163,7 +162,6 @@ trait SeriesSubscription {
|
|||
$subID = $this->nextID("arsse_subscriptions");
|
||||
\Phake::when(Arsse::$db)->feedUpdate->thenReturn(true);
|
||||
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url));
|
||||
\Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd");
|
||||
\Phake::verify(Arsse::$db, \Phake::times(0))->feedUpdate(1, true);
|
||||
$state = $this->primeExpectations($this->data, [
|
||||
'arsse_feeds' => ['id','url','username','password'],
|
||||
|
@ -179,7 +177,6 @@ trait SeriesSubscription {
|
|||
$subID = $this->nextID("arsse_subscriptions");
|
||||
\Phake::when(Arsse::$db)->feedUpdate->thenReturn(true);
|
||||
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url, "", "", false));
|
||||
\Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd");
|
||||
\Phake::verify(Arsse::$db)->feedUpdate($feedID, true);
|
||||
$state = $this->primeExpectations($this->data, [
|
||||
'arsse_feeds' => ['id','url','username','password'],
|
||||
|
@ -197,7 +194,6 @@ trait SeriesSubscription {
|
|||
$subID = $this->nextID("arsse_subscriptions");
|
||||
\Phake::when(Arsse::$db)->feedUpdate->thenReturn(true);
|
||||
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url, "", "", true));
|
||||
\Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd");
|
||||
\Phake::verify(Arsse::$db)->feedUpdate($feedID, true);
|
||||
$state = $this->primeExpectations($this->data, [
|
||||
'arsse_feeds' => ['id','url','username','password'],
|
||||
|
@ -216,7 +212,6 @@ trait SeriesSubscription {
|
|||
try {
|
||||
Arsse::$db->subscriptionAdd($this->user, $url, "", "", false);
|
||||
} finally {
|
||||
\Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd");
|
||||
\Phake::verify(Arsse::$db)->feedUpdate($feedID, true);
|
||||
$state = $this->primeExpectations($this->data, [
|
||||
'arsse_feeds' => ['id','url','username','password'],
|
||||
|
@ -246,16 +241,8 @@ trait SeriesSubscription {
|
|||
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url));
|
||||
}
|
||||
|
||||
public function testAddASubscriptionWithoutAuthority(): void {
|
||||
$url = "http://example.com/feed1";
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->subscriptionAdd($this->user, $url);
|
||||
}
|
||||
|
||||
public function testRemoveASubscription(): void {
|
||||
$this->assertTrue(Arsse::$db->subscriptionRemove($this->user, 1));
|
||||
\Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionRemove");
|
||||
$state = $this->primeExpectations($this->data, [
|
||||
'arsse_feeds' => ['id','url','username','password'],
|
||||
'arsse_subscriptions' => ['id','owner','feed'],
|
||||
|
@ -280,12 +267,6 @@ trait SeriesSubscription {
|
|||
Arsse::$db->subscriptionRemove($this->user, 1);
|
||||
}
|
||||
|
||||
public function testRemoveASubscriptionWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->subscriptionRemove($this->user, 1);
|
||||
}
|
||||
|
||||
public function testListSubscriptions(): void {
|
||||
$exp = [
|
||||
[
|
||||
|
@ -308,9 +289,7 @@ trait SeriesSubscription {
|
|||
],
|
||||
];
|
||||
$this->assertResult($exp, Arsse::$db->subscriptionList($this->user));
|
||||
\Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionList");
|
||||
$this->assertArraySubset($exp[0], Arsse::$db->subscriptionPropertiesGet($this->user, 1));
|
||||
\Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionPropertiesGet");
|
||||
$this->assertArraySubset($exp[1], Arsse::$db->subscriptionPropertiesGet($this->user, 3));
|
||||
}
|
||||
|
||||
|
@ -349,12 +328,6 @@ trait SeriesSubscription {
|
|||
Arsse::$db->subscriptionList($this->user, 4);
|
||||
}
|
||||
|
||||
public function testListSubscriptionsWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->subscriptionList($this->user);
|
||||
}
|
||||
|
||||
public function testCountSubscriptions(): void {
|
||||
$this->assertSame(2, Arsse::$db->subscriptionCount($this->user));
|
||||
$this->assertSame(1, Arsse::$db->subscriptionCount($this->user, 2));
|
||||
|
@ -365,12 +338,6 @@ trait SeriesSubscription {
|
|||
Arsse::$db->subscriptionCount($this->user, 4);
|
||||
}
|
||||
|
||||
public function testCountSubscriptionsWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->subscriptionCount($this->user);
|
||||
}
|
||||
|
||||
public function testGetThePropertiesOfAMissingSubscription(): void {
|
||||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||
Arsse::$db->subscriptionPropertiesGet($this->user, 2112);
|
||||
|
@ -381,12 +348,6 @@ trait SeriesSubscription {
|
|||
Arsse::$db->subscriptionPropertiesGet($this->user, -1);
|
||||
}
|
||||
|
||||
public function testGetThePropertiesOfASubscriptionWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->subscriptionPropertiesGet($this->user, 1);
|
||||
}
|
||||
|
||||
public function testSetThePropertiesOfASubscription(): void {
|
||||
Arsse::$db->subscriptionPropertiesSet($this->user, 1, [
|
||||
'title' => "Ook Ook",
|
||||
|
@ -394,7 +355,6 @@ trait SeriesSubscription {
|
|||
'pinned' => false,
|
||||
'order_type' => 0,
|
||||
]);
|
||||
\Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionPropertiesSet");
|
||||
$state = $this->primeExpectations($this->data, [
|
||||
'arsse_feeds' => ['id','url','username','password','title'],
|
||||
'arsse_subscriptions' => ['id','owner','feed','title','folder','pinned','order_type'],
|
||||
|
@ -454,22 +414,11 @@ trait SeriesSubscription {
|
|||
Arsse::$db->subscriptionPropertiesSet($this->user, -1, ['folder' => null]);
|
||||
}
|
||||
|
||||
public function testSetThePropertiesOfASubscriptionWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->subscriptionPropertiesSet($this->user, 1, ['folder' => null]);
|
||||
}
|
||||
|
||||
public function testRetrieveTheFaviconOfASubscription(): void {
|
||||
$exp = "http://example.com/favicon.ico";
|
||||
$this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 1)['url']);
|
||||
$this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 2)['url']);
|
||||
$this->assertSame(null, Arsse::$db->subscriptionIcon(null, 3)['url']);
|
||||
// authorization shouldn't have any bearing on this function
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 1)['url']);
|
||||
$this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 2)['url']);
|
||||
$this->assertSame(null, Arsse::$db->subscriptionIcon(null, 3)['url']);
|
||||
}
|
||||
|
||||
public function testRetrieveTheFaviconOfAMissingSubscription(): void {
|
||||
|
@ -493,14 +442,6 @@ trait SeriesSubscription {
|
|||
$this->assertSame(null, Arsse::$db->subscriptionIcon($user, 2)['url']);
|
||||
}
|
||||
|
||||
public function testRetrieveTheFaviconOfASubscriptionWithUserWithoutAuthority(): void {
|
||||
$exp = "http://example.com/favicon.ico";
|
||||
$user = "john.doe@example.com";
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->subscriptionIcon($user, -2112);
|
||||
}
|
||||
|
||||
public function testListTheTagsOfASubscription(): void {
|
||||
$this->assertEquals([1,2], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 1));
|
||||
$this->assertEquals([2], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 3));
|
||||
|
@ -513,12 +454,6 @@ trait SeriesSubscription {
|
|||
Arsse::$db->subscriptionTagsGet($this->user, 101);
|
||||
}
|
||||
|
||||
public function testListTheTagsOfASubscriptionWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->subscriptionTagsGet("john.doe@example.com", 1);
|
||||
}
|
||||
|
||||
public function testGetRefreshTimeOfASubscription(): void {
|
||||
$user = "john.doe@example.com";
|
||||
$this->assertTime(strtotime("now + 1 hour"), Arsse::$db->subscriptionRefreshed($user));
|
||||
|
@ -529,10 +464,4 @@ trait SeriesSubscription {
|
|||
$this->assertException("subjectMissing", "Db", "ExceptionInput");
|
||||
$this->assertTime(strtotime("now - 1 hour"), Arsse::$db->subscriptionRefreshed("john.doe@example.com", 2));
|
||||
}
|
||||
|
||||
public function testGetRefreshTimeOfASubscriptionWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
$this->assertTime(strtotime("now + 1 hour"), Arsse::$db->subscriptionRefreshed("john.doe@example.com"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,7 +113,6 @@ trait SeriesTag {
|
|||
$user = "john.doe@example.com";
|
||||
$tagID = $this->nextID("arsse_tags");
|
||||
$this->assertSame($tagID, Arsse::$db->tagAdd($user, ['name' => "Entertaining"]));
|
||||
\Phake::verify(Arsse::$user)->authorize($user, "tagAdd");
|
||||
$state = $this->primeExpectations($this->data, $this->checkTags);
|
||||
$state['arsse_tags']['rows'][] = [$tagID, $user, "Entertaining"];
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -139,12 +138,6 @@ trait SeriesTag {
|
|||
Arsse::$db->tagAdd("john.doe@example.com", ['name' => " "]);
|
||||
}
|
||||
|
||||
public function testAddATagWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->tagAdd("john.doe@example.com", ['name' => "Boring"]);
|
||||
}
|
||||
|
||||
public function testListTags(): void {
|
||||
$exp = [
|
||||
['id' => 2, 'name' => "Fascinating"],
|
||||
|
@ -158,18 +151,10 @@ trait SeriesTag {
|
|||
$this->assertResult($exp, Arsse::$db->tagList("jane.doe@example.com"));
|
||||
$exp = [];
|
||||
$this->assertResult($exp, Arsse::$db->tagList("jane.doe@example.com", false));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "tagList");
|
||||
}
|
||||
|
||||
public function testListTagsWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->tagList("john.doe@example.com");
|
||||
}
|
||||
|
||||
public function testRemoveATag(): void {
|
||||
$this->assertTrue(Arsse::$db->tagRemove("john.doe@example.com", 1));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "tagRemove");
|
||||
$state = $this->primeExpectations($this->data, $this->checkTags);
|
||||
array_shift($state['arsse_tags']['rows']);
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -177,7 +162,6 @@ trait SeriesTag {
|
|||
|
||||
public function testRemoveATagByName(): void {
|
||||
$this->assertTrue(Arsse::$db->tagRemove("john.doe@example.com", "Interesting", true));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "tagRemove");
|
||||
$state = $this->primeExpectations($this->data, $this->checkTags);
|
||||
array_shift($state['arsse_tags']['rows']);
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -203,12 +187,6 @@ trait SeriesTag {
|
|||
Arsse::$db->tagRemove("john.doe@example.com", 3); // tag ID 3 belongs to Jane
|
||||
}
|
||||
|
||||
public function testRemoveATagWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->tagRemove("john.doe@example.com", 1);
|
||||
}
|
||||
|
||||
public function testGetThePropertiesOfATag(): void {
|
||||
$exp = [
|
||||
'id' => 2,
|
||||
|
@ -216,7 +194,6 @@ trait SeriesTag {
|
|||
];
|
||||
$this->assertArraySubset($exp, Arsse::$db->tagPropertiesGet("john.doe@example.com", 2));
|
||||
$this->assertArraySubset($exp, Arsse::$db->tagPropertiesGet("john.doe@example.com", "Fascinating", true));
|
||||
\Phake::verify(Arsse::$user, \Phake::times(2))->authorize("john.doe@example.com", "tagPropertiesGet");
|
||||
}
|
||||
|
||||
public function testGetThePropertiesOfAMissingTag(): void {
|
||||
|
@ -239,19 +216,12 @@ trait SeriesTag {
|
|||
Arsse::$db->tagPropertiesGet("john.doe@example.com", 3); // tag ID 3 belongs to Jane
|
||||
}
|
||||
|
||||
public function testGetThePropertiesOfATagWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->tagPropertiesGet("john.doe@example.com", 1);
|
||||
}
|
||||
|
||||
public function testMakeNoChangesToATag(): void {
|
||||
$this->assertFalse(Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, []));
|
||||
}
|
||||
|
||||
public function testRenameATag(): void {
|
||||
$this->assertTrue(Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, ['name' => "Curious"]));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "tagPropertiesSet");
|
||||
$state = $this->primeExpectations($this->data, $this->checkTags);
|
||||
$state['arsse_tags']['rows'][0][2] = "Curious";
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -259,7 +229,6 @@ trait SeriesTag {
|
|||
|
||||
public function testRenameATagByName(): void {
|
||||
$this->assertTrue(Arsse::$db->tagPropertiesSet("john.doe@example.com", "Interesting", ['name' => "Curious"], true));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.com", "tagPropertiesSet");
|
||||
$state = $this->primeExpectations($this->data, $this->checkTags);
|
||||
$state['arsse_tags']['rows'][0][2] = "Curious";
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -305,12 +274,6 @@ trait SeriesTag {
|
|||
Arsse::$db->tagPropertiesSet("john.doe@example.com", 3, ['name' => "Exciting"]); // tag ID 3 belongs to Jane
|
||||
}
|
||||
|
||||
public function testSetThePropertiesOfATagWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, ['name' => "Exciting"]);
|
||||
}
|
||||
|
||||
public function testListTaggedSubscriptions(): void {
|
||||
$exp = [1,5];
|
||||
$this->assertEquals($exp, Arsse::$db->tagSubscriptionsGet("john.doe@example.com", 1));
|
||||
|
@ -333,12 +296,6 @@ trait SeriesTag {
|
|||
Arsse::$db->tagSubscriptionsGet("john.doe@example.com", -1);
|
||||
}
|
||||
|
||||
public function testListTaggedSubscriptionsWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->tagSubscriptionsGet("john.doe@example.com", 1);
|
||||
}
|
||||
|
||||
public function testApplyATagToSubscriptions(): void {
|
||||
Arsse::$db->tagSubscriptionsSet("john.doe@example.com", 1, [3,4]);
|
||||
$state = $this->primeExpectations($this->data, $this->checkMembers);
|
||||
|
@ -399,12 +356,6 @@ trait SeriesTag {
|
|||
$this->compareExpectations(static::$drv, $state);
|
||||
}
|
||||
|
||||
public function testApplyATagToSubscriptionsWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->tagSubscriptionsSet("john.doe@example.com", 1, [3,4]);
|
||||
}
|
||||
|
||||
public function testSummarizeTags(): void {
|
||||
$exp = [
|
||||
['id' => 1, 'name' => "Interesting", 'subscription' => 1],
|
||||
|
@ -415,10 +366,4 @@ trait SeriesTag {
|
|||
];
|
||||
$this->assertResult($exp, Arsse::$db->tagSummarize("john.doe@example.com"));
|
||||
}
|
||||
|
||||
public function testSummarizeTagsWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->tagSummarize("john.doe@example.com");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,9 +67,6 @@ trait SeriesToken {
|
|||
$this->assertArraySubset($exp1, Arsse::$db->tokenLookup("fever.login", "80fa94c1a11f11e78667001e673b2560"));
|
||||
$this->assertArraySubset($exp2, Arsse::$db->tokenLookup("class.class", "da772f8fa13c11e78667001e673b2560"));
|
||||
$this->assertArraySubset($exp3, Arsse::$db->tokenLookup("class.class", "ab3b3eb8a13311e78667001e673b2560"));
|
||||
// token lookup should not check authorization
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertArraySubset($exp1, Arsse::$db->tokenLookup("fever.login", "80fa94c1a11f11e78667001e673b2560"));
|
||||
}
|
||||
|
||||
public function testLookUpAMissingToken(): void {
|
||||
|
@ -106,12 +103,6 @@ trait SeriesToken {
|
|||
Arsse::$db->tokenCreate("fever.login", "jane.doe@example.biz");
|
||||
}
|
||||
|
||||
public function testCreateATokenWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->tokenCreate("fever.login", "jane.doe@example.com");
|
||||
}
|
||||
|
||||
public function testRevokeAToken(): void {
|
||||
$user = "jane.doe@example.com";
|
||||
$id = "80fa94c1a11f11e78667001e673b2560";
|
||||
|
@ -136,10 +127,4 @@ trait SeriesToken {
|
|||
// revoking tokens which do not exist is not an error
|
||||
$this->assertFalse(Arsse::$db->tokenRevoke($user, "unknown.class"));
|
||||
}
|
||||
|
||||
public function testRevokeATokenWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->tokenRevoke("jane.doe@example.com", "fever.login");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,21 +33,12 @@ trait SeriesUser {
|
|||
public function testCheckThatAUserExists(): void {
|
||||
$this->assertTrue(Arsse::$db->userExists("jane.doe@example.com"));
|
||||
$this->assertFalse(Arsse::$db->userExists("jane.doe@example.org"));
|
||||
\Phake::verify(Arsse::$user)->authorize("jane.doe@example.com", "userExists");
|
||||
\Phake::verify(Arsse::$user)->authorize("jane.doe@example.org", "userExists");
|
||||
$this->compareExpectations(static::$drv, $this->data);
|
||||
}
|
||||
|
||||
public function testCheckThatAUserExistsWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->userExists("jane.doe@example.com");
|
||||
}
|
||||
|
||||
public function testGetAPassword(): void {
|
||||
$hash = Arsse::$db->userPasswordGet("admin@example.net");
|
||||
$this->assertSame('$2y$10$PbcG2ZR3Z8TuPzM7aHTF8.v61dtCjzjK78gdZJcp4UePE8T9jEgBW', $hash);
|
||||
\Phake::verify(Arsse::$user)->authorize("admin@example.net", "userPasswordGet");
|
||||
$this->assertTrue(password_verify("secret", $hash));
|
||||
}
|
||||
|
||||
|
@ -56,15 +47,8 @@ trait SeriesUser {
|
|||
Arsse::$db->userPasswordGet("john.doe@example.org");
|
||||
}
|
||||
|
||||
public function testGetAPasswordWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->userPasswordGet("admin@example.net");
|
||||
}
|
||||
|
||||
public function testAddANewUser(): void {
|
||||
$this->assertTrue(Arsse::$db->userAdd("john.doe@example.org", ""));
|
||||
\Phake::verify(Arsse::$user)->authorize("john.doe@example.org", "userAdd");
|
||||
$state = $this->primeExpectations($this->data, ['arsse_users' => ['id']]);
|
||||
$state['arsse_users']['rows'][] = ["john.doe@example.org"];
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -75,15 +59,8 @@ trait SeriesUser {
|
|||
Arsse::$db->userAdd("john.doe@example.com", "");
|
||||
}
|
||||
|
||||
public function testAddANewUserWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->userAdd("john.doe@example.org", "");
|
||||
}
|
||||
|
||||
public function testRemoveAUser(): void {
|
||||
$this->assertTrue(Arsse::$db->userRemove("admin@example.net"));
|
||||
\Phake::verify(Arsse::$user)->authorize("admin@example.net", "userRemove");
|
||||
$state = $this->primeExpectations($this->data, ['arsse_users' => ['id']]);
|
||||
array_shift($state['arsse_users']['rows']);
|
||||
$this->compareExpectations(static::$drv, $state);
|
||||
|
@ -94,22 +71,9 @@ trait SeriesUser {
|
|||
Arsse::$db->userRemove("john.doe@example.org");
|
||||
}
|
||||
|
||||
public function testRemoveAUserWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->userRemove("admin@example.net");
|
||||
}
|
||||
|
||||
public function testListAllUsers(): void {
|
||||
$users = ["admin@example.net", "jane.doe@example.com", "john.doe@example.com"];
|
||||
$this->assertSame($users, Arsse::$db->userList());
|
||||
\Phake::verify(Arsse::$user)->authorize("", "userList");
|
||||
}
|
||||
|
||||
public function testListAllUsersWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->userList();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,7 +86,6 @@ trait SeriesUser {
|
|||
$this->assertTrue(Arsse::$db->userPasswordSet($user, $pass));
|
||||
$hash = Arsse::$db->userPasswordGet($user);
|
||||
$this->assertNotEquals("", $hash);
|
||||
\Phake::verify(Arsse::$user)->authorize($user, "userPasswordSet");
|
||||
$this->assertTrue(password_verify($pass, $hash), "Failed verifying password of $user '$pass' against hash '$hash'.");
|
||||
}
|
||||
|
||||
|
@ -137,10 +100,4 @@ trait SeriesUser {
|
|||
$this->assertException("doesNotExist", "User");
|
||||
Arsse::$db->userPasswordSet("john.doe@example.org", "secret");
|
||||
}
|
||||
|
||||
public function testSetAPasswordWithoutAuthority(): void {
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(false);
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
Arsse::$db->userPasswordSet("john.doe@example.com", "secret");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
// create a mock user manager
|
||||
Arsse::$user = \Phake::mock(\JKingWeb\Arsse\User::class);
|
||||
\Phake::when(Arsse::$user)->exists->thenReturn(true);
|
||||
\Phake::when(Arsse::$user)->authorize->thenReturn(true);
|
||||
// create a mock Import/Export processor
|
||||
$this->proc = \Phake::partialMock(AbstractImportExport::class);
|
||||
// initialize an SQLite memeory database
|
||||
|
|
|
@ -33,16 +33,12 @@ class TestInternal extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
* @dataProvider provideAuthentication
|
||||
* @group slow
|
||||
*/
|
||||
public function testAuthenticateAUser(bool $authorized, string $user, $password, bool $exp): void {
|
||||
if ($authorized) {
|
||||
public function testAuthenticateAUser(string $user, $password, bool $exp): void {
|
||||
\Phake::when(Arsse::$db)->userPasswordGet("john.doe@example.com")->thenReturn('$2y$10$1zbqRJhxM8uUjeSBPp4IhO90xrqK0XjEh9Z16iIYEFRV4U.zeAFom'); // hash of "secret"
|
||||
\Phake::when(Arsse::$db)->userPasswordGet("jane.doe@example.com")->thenReturn('$2y$10$bK1ljXfTSyc2D.NYvT.Eq..OpehLRXVbglW.23ihVuyhgwJCd.7Im'); // hash of "superman"
|
||||
\Phake::when(Arsse::$db)->userPasswordGet("owen.hardy@example.com")->thenReturn("");
|
||||
\Phake::when(Arsse::$db)->userPasswordGet("kira.nerys@example.com")->thenThrow(new \JKingWeb\Arsse\User\Exception("doesNotExist"));
|
||||
\Phake::when(Arsse::$db)->userPasswordGet("007@example.com")->thenReturn(null);
|
||||
} else {
|
||||
\Phake::when(Arsse::$db)->userPasswordGet->thenThrow(new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized"));
|
||||
}
|
||||
$this->assertSame($exp, (new Driver)->auth($user, $password));
|
||||
}
|
||||
|
||||
|
@ -53,32 +49,22 @@ class TestInternal extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$kira = "kira.nerys@example.com";
|
||||
$bond = "007@example.com";
|
||||
return [
|
||||
[false, $john, "secret", false],
|
||||
[false, $jane, "superman", false],
|
||||
[false, $owen, "", false],
|
||||
[false, $kira, "ashalla", false],
|
||||
[false, $bond, "", false],
|
||||
[true, $john, "secret", true],
|
||||
[true, $jane, "superman", true],
|
||||
[true, $owen, "", true],
|
||||
[true, $kira, "ashalla", false],
|
||||
[true, $john, "top secret", false],
|
||||
[true, $jane, "clark kent", false],
|
||||
[true, $owen, "watchmaker", false],
|
||||
[true, $kira, "singha", false],
|
||||
[true, $john, "", false],
|
||||
[true, $jane, "", false],
|
||||
[true, $kira, "", false],
|
||||
[true, $bond, "for England", false],
|
||||
[true, $bond, "", false],
|
||||
[$john, "secret", true],
|
||||
[$jane, "superman", true],
|
||||
[$owen, "", true],
|
||||
[$kira, "ashalla", false],
|
||||
[$john, "top secret", false],
|
||||
[$jane, "clark kent", false],
|
||||
[$owen, "watchmaker", false],
|
||||
[$kira, "singha", false],
|
||||
[$john, "", false],
|
||||
[$jane, "", false],
|
||||
[$kira, "", false],
|
||||
[$bond, "for England", false],
|
||||
[$bond, "", false],
|
||||
];
|
||||
}
|
||||
|
||||
public function testAuthorizeAnAction(): void {
|
||||
\Phake::verifyNoFurtherInteraction(Arsse::$db);
|
||||
$this->assertTrue((new Driver)->authorize("someone", "something"));
|
||||
}
|
||||
|
||||
public function testListUsers(): void {
|
||||
$john = "john.doe@example.com";
|
||||
$jane = "jane.doe@example.com";
|
||||
|
|
|
@ -69,13 +69,9 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
/** @dataProvider provideUserList */
|
||||
public function testListUsers(bool $authorized, $exp): void {
|
||||
public function testListUsers($exp): void {
|
||||
$u = new User($this->drv);
|
||||
\Phake::when($this->drv)->authorize->thenReturn($authorized);
|
||||
\Phake::when($this->drv)->userList->thenReturn(["john.doe@example.com", "jane.doe@example.com"]);
|
||||
if ($exp instanceof Exception) {
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
}
|
||||
$this->assertSame($exp, $u->list());
|
||||
}
|
||||
|
||||
|
@ -83,20 +79,15 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$john = "john.doe@example.com";
|
||||
$jane = "jane.doe@example.com";
|
||||
return [
|
||||
[false, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")],
|
||||
[true, [$john, $jane]],
|
||||
[[$john, $jane]],
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider provideExistence */
|
||||
public function testCheckThatAUserExists(bool $authorized, string $user, $exp): void {
|
||||
public function testCheckThatAUserExists(string $user, $exp): void {
|
||||
$u = new User($this->drv);
|
||||
\Phake::when($this->drv)->authorize->thenReturn($authorized);
|
||||
\Phake::when($this->drv)->userExists("john.doe@example.com")->thenReturn(true);
|
||||
\Phake::when($this->drv)->userExists("jane.doe@example.com")->thenReturn(false);
|
||||
if ($exp instanceof Exception) {
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
}
|
||||
$this->assertSame($exp, $u->exists($user));
|
||||
}
|
||||
|
||||
|
@ -104,48 +95,35 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$john = "john.doe@example.com";
|
||||
$jane = "jane.doe@example.com";
|
||||
return [
|
||||
[false, $john, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")],
|
||||
[false, $jane, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")],
|
||||
[true, $john, true],
|
||||
[true, $jane, false],
|
||||
[$john, true],
|
||||
[$jane, false],
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider provideAdditions */
|
||||
public function testAddAUser(bool $authorized, string $user, $password, $exp): void {
|
||||
public function testAddAUser(string $user, $password, $exp): void {
|
||||
$u = new User($this->drv);
|
||||
\Phake::when($this->drv)->authorize->thenReturn($authorized);
|
||||
\Phake::when($this->drv)->userAdd("john.doe@example.com", $this->anything())->thenThrow(new \JKingWeb\Arsse\User\Exception("alreadyExists"));
|
||||
\Phake::when($this->drv)->userAdd("jane.doe@example.com", $this->anything())->thenReturnCallback(function($user, $pass) {
|
||||
return $pass ?? "random password";
|
||||
});
|
||||
if ($exp instanceof Exception) {
|
||||
if ($exp instanceof \JKingWeb\Arsse\User\ExceptionAuthz) {
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
} else {
|
||||
$this->assertException("alreadyExists", "User");
|
||||
}
|
||||
}
|
||||
$this->assertSame($exp, $u->add($user, $password));
|
||||
}
|
||||
|
||||
/** @dataProvider provideAdditions */
|
||||
public function testAddAUserWithARandomPassword(bool $authorized, string $user, $password, $exp): void {
|
||||
public function testAddAUserWithARandomPassword(string $user, $password, $exp): void {
|
||||
$u = \Phake::partialMock(User::class, $this->drv);
|
||||
\Phake::when($this->drv)->authorize->thenReturn($authorized);
|
||||
\Phake::when($this->drv)->userAdd($this->anything(), $this->isNull())->thenReturn(null);
|
||||
\Phake::when($this->drv)->userAdd("john.doe@example.com", $this->logicalNot($this->isNull()))->thenThrow(new \JKingWeb\Arsse\User\Exception("alreadyExists"));
|
||||
\Phake::when($this->drv)->userAdd("jane.doe@example.com", $this->logicalNot($this->isNull()))->thenReturnCallback(function($user, $pass) {
|
||||
return $pass;
|
||||
});
|
||||
if ($exp instanceof Exception) {
|
||||
if ($exp instanceof \JKingWeb\Arsse\User\ExceptionAuthz) {
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
$calls = 0;
|
||||
} else {
|
||||
$this->assertException("alreadyExists", "User");
|
||||
$calls = 2;
|
||||
}
|
||||
} else {
|
||||
$calls = 4;
|
||||
}
|
||||
|
@ -163,34 +141,27 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$john = "john.doe@example.com";
|
||||
$jane = "jane.doe@example.com";
|
||||
return [
|
||||
[false, $john, "secret", new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")],
|
||||
[false, $jane, "superman", new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")],
|
||||
[true, $john, "secret", new \JKingWeb\Arsse\User\Exception("alreadyExists")],
|
||||
[true, $jane, "superman", "superman"],
|
||||
[true, $jane, null, "random password"],
|
||||
[$john, "secret", new \JKingWeb\Arsse\User\Exception("alreadyExists")],
|
||||
[$jane, "superman", "superman"],
|
||||
[$jane, null, "random password"],
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider provideRemovals */
|
||||
public function testRemoveAUser(bool $authorized, string $user, bool $exists, $exp): void {
|
||||
public function testRemoveAUser(string $user, bool $exists, $exp): void {
|
||||
$u = new User($this->drv);
|
||||
\Phake::when($this->drv)->authorize->thenReturn($authorized);
|
||||
\Phake::when($this->drv)->userRemove("john.doe@example.com")->thenReturn(true);
|
||||
\Phake::when($this->drv)->userRemove("jane.doe@example.com")->thenThrow(new \JKingWeb\Arsse\User\Exception("doesNotExist"));
|
||||
\Phake::when(Arsse::$db)->userExists->thenReturn($exists);
|
||||
\Phake::when(Arsse::$db)->userRemove->thenReturn(true);
|
||||
if ($exp instanceof Exception) {
|
||||
if ($exp instanceof \JKingWeb\Arsse\User\ExceptionAuthz) {
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
} else {
|
||||
$this->assertException("doesNotExist", "User");
|
||||
}
|
||||
}
|
||||
try {
|
||||
$this->assertSame($exp, $u->remove($user));
|
||||
} finally {
|
||||
\Phake::verify(Arsse::$db, \Phake::times((int) $authorized))->userExists($user);
|
||||
\Phake::verify(Arsse::$db, \Phake::times((int) ($authorized && $exists)))->userRemove($user);
|
||||
\Phake::verify(Arsse::$db, \Phake::times(1))->userExists($user);
|
||||
\Phake::verify(Arsse::$db, \Phake::times((int) $exists))->userRemove($user);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,32 +169,23 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$john = "john.doe@example.com";
|
||||
$jane = "jane.doe@example.com";
|
||||
return [
|
||||
[false, $john, true, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")],
|
||||
[false, $john, false, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")],
|
||||
[false, $jane, true, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")],
|
||||
[false, $jane, false, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")],
|
||||
[true, $john, true, true],
|
||||
[true, $john, false, true],
|
||||
[true, $jane, true, new \JKingWeb\Arsse\User\Exception("doesNotExist")],
|
||||
[true, $jane, false, new \JKingWeb\Arsse\User\Exception("doesNotExist")],
|
||||
[$john, true, true],
|
||||
[$john, false, true],
|
||||
[$jane, true, new \JKingWeb\Arsse\User\Exception("doesNotExist")],
|
||||
[$jane, false, new \JKingWeb\Arsse\User\Exception("doesNotExist")],
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider providePasswordChanges */
|
||||
public function testChangeAPassword(bool $authorized, string $user, $password, bool $exists, $exp): void {
|
||||
public function testChangeAPassword(string $user, $password, bool $exists, $exp): void {
|
||||
$u = new User($this->drv);
|
||||
\Phake::when($this->drv)->authorize->thenReturn($authorized);
|
||||
\Phake::when($this->drv)->userPasswordSet("john.doe@example.com", $this->anything(), $this->anything())->thenReturnCallback(function($user, $pass, $old) {
|
||||
return $pass ?? "random password";
|
||||
});
|
||||
\Phake::when($this->drv)->userPasswordSet("jane.doe@example.com", $this->anything(), $this->anything())->thenThrow(new \JKingWeb\Arsse\User\Exception("doesNotExist"));
|
||||
\Phake::when(Arsse::$db)->userExists->thenReturn($exists);
|
||||
if ($exp instanceof Exception) {
|
||||
if ($exp instanceof \JKingWeb\Arsse\User\ExceptionAuthz) {
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
} else {
|
||||
$this->assertException("doesNotExist", "User");
|
||||
}
|
||||
$calls = 0;
|
||||
} else {
|
||||
$calls = 1;
|
||||
|
@ -237,9 +199,8 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
}
|
||||
|
||||
/** @dataProvider providePasswordChanges */
|
||||
public function testChangeAPasswordToARandomPassword(bool $authorized, string $user, $password, bool $exists, $exp): void {
|
||||
public function testChangeAPasswordToARandomPassword(string $user, $password, bool $exists, $exp): void {
|
||||
$u = \Phake::partialMock(User::class, $this->drv);
|
||||
\Phake::when($this->drv)->authorize->thenReturn($authorized);
|
||||
\Phake::when($this->drv)->userPasswordSet($this->anything(), $this->isNull(), $this->anything())->thenReturn(null);
|
||||
\Phake::when($this->drv)->userPasswordSet("john.doe@example.com", $this->logicalNot($this->isNull()), $this->anything())->thenReturnCallback(function($user, $pass, $old) {
|
||||
return $pass ?? "random password";
|
||||
|
@ -247,13 +208,8 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
\Phake::when($this->drv)->userPasswordSet("jane.doe@example.com", $this->logicalNot($this->isNull()), $this->anything())->thenThrow(new \JKingWeb\Arsse\User\Exception("doesNotExist"));
|
||||
\Phake::when(Arsse::$db)->userExists->thenReturn($exists);
|
||||
if ($exp instanceof Exception) {
|
||||
if ($exp instanceof \JKingWeb\Arsse\User\ExceptionAuthz) {
|
||||
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
|
||||
$calls = 0;
|
||||
} else {
|
||||
$this->assertException("doesNotExist", "User");
|
||||
$calls = 2;
|
||||
}
|
||||
} else {
|
||||
$calls = 4;
|
||||
}
|
||||
|
@ -278,19 +234,16 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$john = "john.doe@example.com";
|
||||
$jane = "jane.doe@example.com";
|
||||
return [
|
||||
[false, $john, "secret", true, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")],
|
||||
[false, $jane, "superman", false, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")],
|
||||
[true, $john, "superman", true, "superman"],
|
||||
[true, $john, null, true, "random password"],
|
||||
[true, $john, "superman", false, "superman"],
|
||||
[true, $john, null, false, "random password"],
|
||||
[true, $jane, "secret", true, new \JKingWeb\Arsse\User\Exception("doesNotExist")],
|
||||
[$john, "superman", true, "superman"],
|
||||
[$john, null, true, "random password"],
|
||||
[$john, "superman", false, "superman"],
|
||||
[$john, null, false, "random password"],
|
||||
[$jane, "secret", true, new \JKingWeb\Arsse\User\Exception("doesNotExist")],
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider providePasswordClearings */
|
||||
public function testClearAPassword(bool $authorized, bool $exists, string $user, $exp): void {
|
||||
\Phake::when($this->drv)->authorize->thenReturn($authorized);
|
||||
public function testClearAPassword(bool $exists, string $user, $exp): void {
|
||||
\Phake::when($this->drv)->userPasswordUnset->thenReturn(true);
|
||||
\Phake::when($this->drv)->userPasswordUnset("jane.doe@example.net", null)->thenThrow(new \JKingWeb\Arsse\User\Exception("doesNotExist"));
|
||||
\Phake::when(Arsse::$db)->userExists->thenReturn($exists);
|
||||
|
@ -303,26 +256,19 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
|
|||
$this->assertSame($exp, $u->passwordUnset($user));
|
||||
}
|
||||
} finally {
|
||||
\Phake::verify(Arsse::$db, \Phake::times((int) ($authorized && $exists && is_bool($exp))))->userPasswordSet($user, null);
|
||||
\Phake::verify(Arsse::$db, \Phake::times((int) ($exists && is_bool($exp))))->userPasswordSet($user, null);
|
||||
}
|
||||
}
|
||||
|
||||
public function providePasswordClearings(): iterable {
|
||||
$forbidden = new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized");
|
||||
$missing = new \JKingWeb\Arsse\User\Exception("doesNotExist");
|
||||
return [
|
||||
[false, true, "jane.doe@example.com", $forbidden],
|
||||
[false, true, "john.doe@example.com", $forbidden],
|
||||
[false, true, "jane.doe@example.net", $forbidden],
|
||||
[false, false, "jane.doe@example.com", $forbidden],
|
||||
[false, false, "john.doe@example.com", $forbidden],
|
||||
[false, false, "jane.doe@example.net", $forbidden],
|
||||
[true, true, "jane.doe@example.com", true],
|
||||
[true, true, "john.doe@example.com", true],
|
||||
[true, true, "jane.doe@example.net", $missing],
|
||||
[true, false, "jane.doe@example.com", true],
|
||||
[true, false, "john.doe@example.com", true],
|
||||
[true, false, "jane.doe@example.net", $missing],
|
||||
[true, "jane.doe@example.com", true],
|
||||
[true, "john.doe@example.com", true],
|
||||
[true, "jane.doe@example.net", $missing],
|
||||
[false, "jane.doe@example.com", true],
|
||||
[false, "john.doe@example.com", true],
|
||||
[false, "jane.doe@example.net", $missing],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue