1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-22 21:22:40 +00:00

Strip out remnants of the authorizer

This commit is contained in:
J. King 2020-11-09 16:51:30 -05:00
parent 576d7e16a8
commit 771f79323c
19 changed files with 71 additions and 672 deletions

View file

@ -73,7 +73,6 @@ abstract class AbstractException extends \Exception {
"User/Exception.alreadyExists" => 10403, "User/Exception.alreadyExists" => 10403,
"User/Exception.authMissing" => 10411, "User/Exception.authMissing" => 10411,
"User/Exception.authFailed" => 10412, "User/Exception.authFailed" => 10412,
"User/ExceptionAuthz.notAuthorized" => 10421,
"User/ExceptionSession.invalid" => 10431, "User/ExceptionSession.invalid" => 10431,
"User/ExceptionInput.invalidTimezone" => 10441, "User/ExceptionInput.invalidTimezone" => 10441,
"User/ExceptionInput.invalidBoolean" => 10442, "User/ExceptionInput.invalidBoolean" => 10442,

View file

@ -242,9 +242,6 @@ class Database {
/** Returns whether the specified user exists in the database */ /** Returns whether the specified user exists in the database */
public function userExists(string $user): bool { 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(); 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 * @param string $passwordThe user's password in cleartext. It will be stored hashed
*/ */
public function userAdd(string $user, string $password): bool { public function userAdd(string $user, string $password): bool {
if (!Arsse::$user->authorize($user, __FUNCTION__)) { if ($this->userExists($user)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
} elseif ($this->userExists($user)) {
throw new User\Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]); throw new User\Exception("alreadyExists", ["action" => __FUNCTION__, "user" => $user]);
} }
$hash = (strlen($password) > 0) ? password_hash($password, \PASSWORD_DEFAULT) : ""; $hash = (strlen($password) > 0) ? password_hash($password, \PASSWORD_DEFAULT) : "";
@ -267,9 +262,6 @@ class Database {
/** Removes a user from the database */ /** Removes a user from the database */
public function userRemove(string $user): bool { 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) { if ($this->db->prepare("DELETE from arsse_users where id = ?", "str")->run($user)->changes() < 1) {
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); 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 */ /** Returns a flat, indexed array of all users in the database */
public function userList(): array { public function userList(): array {
$out = []; $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) { foreach ($this->db->query("SELECT id from arsse_users") as $user) {
$out[] = $user['id']; $out[] = $user['id'];
} }
@ -290,9 +279,7 @@ class Database {
/** Retrieves the hashed password of a user */ /** Retrieves the hashed password of a user */
public function userPasswordGet(string $user): ?string { public function userPasswordGet(string $user): ?string {
if (!Arsse::$user->authorize($user, __FUNCTION__)) { if (!$this->userExists($user)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
} elseif (!$this->userExists($user)) {
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $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(); 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 * @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 { public function userPasswordSet(string $user, string $password = null): bool {
if (!Arsse::$user->authorize($user, __FUNCTION__)) { if (!$this->userExists($user)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
} elseif (!$this->userExists($user)) {
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
} }
$hash = (strlen($password ?? "") > 0) ? password_hash($password, \PASSWORD_DEFAULT) : $password; $hash = (strlen($password ?? "") > 0) ? password_hash($password, \PASSWORD_DEFAULT) : $password;
@ -315,9 +300,7 @@ class Database {
} }
public function userPropertiesGet(string $user): array { public function userPropertiesGet(string $user): array {
if (!Arsse::$user->authorize($user, __FUNCTION__)) { if (!$this->userExists($user)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
} elseif (!$this->userExists($user)) {
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $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(); $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 { public function userPropertiesSet(string $user, array $data): bool {
if (!Arsse::$user->authorize($user, __FUNCTION__)) { if (!$this->userExists($user)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
} elseif (!$this->userExists($user)) {
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
} }
$allowed = [ $allowed = [
@ -339,16 +320,12 @@ class Database {
'sort_asc' => "strict bool", 'sort_asc' => "strict bool",
]; ];
[$setClause, $setTypes, $setValues] = $this->generateSet($data, $allowed); [$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 */ /** Creates a new session for the given user and returns the session identifier */
public function sessionCreate(string $user): string { 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 // generate a new session ID and expiry date
$id = UUID::mint()->hex; $id = UUID::mint()->hex;
$expires = Date::add(Arsse::$conf->userSessionTimeout); $expires = Date::add(Arsse::$conf->userSessionTimeout);
@ -367,10 +344,6 @@ class Database {
* @param string|null $id The identifier of the session to destroy * @param string|null $id The identifier of the session to destroy
*/ */
public function sessionDestroy(string $user, string $id = null): bool { 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)) { if (is_null($id)) {
// delete all sessions and report success unconditionally if no identifier was specified // delete all sessions and report success unconditionally if no identifier was specified
$this->db->prepare("DELETE FROM arsse_sessions where \"user\" = ?", "str")->run($user); $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 * @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 { 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 (!$this->userExists($user)) {
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
} elseif (!$this->userExists($user)) {
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]); throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
} }
// generate a token if it's not provided // 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 * @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 { 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)) { if (is_null($id)) {
$out = $this->db->prepare("DELETE FROM arsse_tokens where \"user\" = ? and class = ?", "str", "str")->run($user, $class)->changes(); $out = $this->db->prepare("DELETE FROM arsse_tokens where \"user\" = ? and class = ?", "str", "str")->run($user, $class)->changes();
} else { } else {
@ -484,10 +450,6 @@ class Database {
* @param array $data An associative array defining the folder * @param array $data An associative array defining the folder
*/ */
public function folderAdd(string $user, array $data): int { 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 // normalize folder's parent, if there is one
$parent = array_key_exists("parent", $data) ? $this->folderValidateId($user, $data['parent'])['id'] : null; $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 // 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) * @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 { 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 // check to make sure the parent exists, if one is specified
$parent = $this->folderValidateId($user, $parent)['id']; $parent = $this->folderValidateId($user, $parent)['id'];
$q = new Query( $q = new Query(
@ -548,9 +506,6 @@ class Database {
* @param integer $id The identifier of the folder to delete * @param integer $id The identifier of the folder to delete
*/ */
public function folderRemove(string $user, $id): bool { 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)) { if (!ValueInfo::id($id)) {
throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "folder", 'type' => "int > 0"]); 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 */ /** Returns the identifier, name, and parent of the given folder as an associative array */
public function folderPropertiesGet(string $user, $id): 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)) { if (!ValueInfo::id($id)) {
throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "folder", 'type' => "int > 0"]); 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 * @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 { 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 // verify the folder belongs to the user
$in = $this->folderValidateId($user, $id, true); $in = $this->folderValidateId($user, $id, true);
$name = array_key_exists("name", $data); $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 * @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 { 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 // 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); $feedID = $this->feedAdd($url, $fetchUser, $fetchPassword, $discover);
// Add the feed to the user's subscriptions and return the new subscription's ID. // 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 * @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 { 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 // validate inputs
$folder = $this->folderValidateId($user, $folder)['id']; $folder = $this->folderValidateId($user, $folder)['id'];
// create a complex query // create a complex query
@ -804,9 +747,6 @@ class Database {
/** Returns the number of subscriptions in a folder, counting recursively */ /** Returns the number of subscriptions in a folder, counting recursively */
public function subscriptionCount(string $user, $folder = null): int { 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 // validate inputs
$folder = $this->folderValidateId($user, $folder)['id']; $folder = $this->folderValidateId($user, $folder)['id'];
// create a complex query // create a complex query
@ -829,9 +769,6 @@ class Database {
* configurable retention period for newsfeeds * configurable retention period for newsfeeds
*/ */
public function subscriptionRemove(string $user, $id): bool { 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)) { if (!ValueInfo::id($id)) {
throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "feed", 'type' => "int > 0"]); 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 * - "unread": The number of unread articles associated with the subscription
*/ */
public function subscriptionPropertiesGet(string $user, $id): array { 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)) { if (!ValueInfo::id($id)) {
throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "feed", 'type' => "int > 0"]); 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 * @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 { 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(); $tr = $this->db->begin();
// validate the ID // validate the ID
$id = $this->subscriptionValidateId($user, $id, true)['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) * @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 { 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); $this->subscriptionValidateId($user, $id, true);
$field = !$byName ? "id" : "name"; $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(); $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 = 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); $q->setWhere("s.id = ?", "int", $id);
if (isset($user)) { if (isset($user)) {
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
}
$q->setWhere("s.owner = ?", "str", $user); $q->setWhere("s.owner = ?", "str", $user);
} }
$out = $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->getRow(); $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 */ /** 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 { 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 = 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); $q->setWhere("arsse_subscriptions.owner = ?", "str", $user);
if ($id) { if ($id) {
@ -1304,9 +1226,6 @@ class Database {
* @param string $user The user whose subscription icons are to be retrieved * @param string $user The user whose subscription icons are to be retrieved
*/ */
public function iconList(string $user): Db\Result { 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); 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 * @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 { 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 // make a base query based on context and output columns
$context = $context ?? new Context; $context = $context ?? new Context;
$q = $this->articleQuery($user, $context, $fields); $q = $this->articleQuery($user, $context, $fields);
@ -1693,9 +1609,6 @@ class Database {
* @param Context $context The search context * @param Context $context The search context
*/ */
public function articleCount(string $user, Context $context = null): int { 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; $context = $context ?? new Context;
$q = $this->articleQuery($user, $context, []); $q = $this->articleQuery($user, $context, []);
return (int) $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->getValue(); 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 * @param Context $context The query context to match articles against
*/ */
public function articleMark(string $user, array $data, Context $context = null): int { 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 = [ $data = [
'read' => $data['read'] ?? null, 'read' => $data['read'] ?? null,
'starred' => $data['starred'] ?? null, 'starred' => $data['starred'] ?? null,
@ -1800,9 +1710,6 @@ class Database {
* - "read": The count of starred articles which are read * - "read": The count of starred articles which are read
*/ */
public function articleStarred(string $user): array { 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( return $this->db->prepare(
"SELECT "SELECT
count(*) as total, 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) * @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 { 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']; $id = $this->articleValidateId($user, $id)['article'];
$field = !$byName ? "id" : "name"; $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(); $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 */ /** Returns the author-supplied categories associated with an article */
public function articleCategoriesGet(string $user, $id): array { 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']; $id = $this->articleValidateId($user, $id)['article'];
$out = $this->db->prepare("SELECT name from arsse_categories where article = ? order by name", "int")->run($id)->getAll(); $out = $this->db->prepare("SELECT name from arsse_categories where article = ? order by name", "int")->run($id)->getAll();
if (!$out) { if (!$out) {
@ -1937,9 +1838,6 @@ class Database {
/** Returns the numeric identifier of the most recent edition of an article matching the given context */ /** 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 { 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; $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); $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()) { 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 * @param array $data An associative array defining the label's properties; currently only "name" is understood
*/ */
public function labelAdd(string $user, array $data): int { 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 // validate the label name
$name = array_key_exists("name", $data) ? $data['name'] : ""; $name = array_key_exists("name", $data) ? $data['name'] : "";
$this->labelValidateName($name, true); $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 * @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 { 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( return $this->db->prepare(
"SELECT * FROM ( "SELECT * FROM (
SELECT 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) * @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 { 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); $this->labelValidateId($user, $id, $byName, false);
$field = $byName ? "name" : "id"; $field = $byName ? "name" : "id";
$type = $byName ? "str" : "int"; $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) * @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 { 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); $this->labelValidateId($user, $id, $byName, false);
$field = $byName ? "name" : "id"; $field = $byName ? "name" : "id";
$type = $byName ? "str" : "int"; $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) * @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 { 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); $this->labelValidateId($user, $id, $byName, false);
if (isset($data['name'])) { if (isset($data['name'])) {
$this->labelValidateName($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) * @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 { 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 // just do a syntactic check on the label ID
$this->labelValidateId($user, $id, $byName, false); $this->labelValidateId($user, $id, $byName, false);
$field = !$byName ? "id" : "name"; $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 { 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)); 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 // validate the tag ID, and get the numeric ID if matching by name
$id = $this->labelValidateId($user, $id, $byName, true)['id']; $id = $this->labelValidateId($user, $id, $byName, true)['id'];
// get the list of articles matching the context // 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 * @param array $data An associative array defining the tag's properties; currently only "name" is understood
*/ */
public function tagAdd(string $user, array $data): int { 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 // validate the tag name
$name = array_key_exists("name", $data) ? $data['name'] : ""; $name = array_key_exists("name", $data) ? $data['name'] : "";
$this->tagValidateName($name, true); $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 * @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 { 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( return $this->db->prepare(
"SELECT * FROM ( "SELECT * FROM (
SELECT SELECT
@ -2323,10 +2190,6 @@ class Database {
* @param string $user The user whose tags are to be listed * @param string $user The user whose tags are to be listed
*/ */
public function tagSummarize(string $user): Db\Result { 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( return $this->db->prepare(
"SELECT "SELECT
arsse_tags.id as id, 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) * @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 { 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); $this->tagValidateId($user, $id, $byName, false);
$field = $byName ? "name" : "id"; $field = $byName ? "name" : "id";
$type = $byName ? "str" : "int"; $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) * @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 { 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); $this->tagValidateId($user, $id, $byName, false);
$field = $byName ? "name" : "id"; $field = $byName ? "name" : "id";
$type = $byName ? "str" : "int"; $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) * @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 { 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); $this->tagValidateId($user, $id, $byName, false);
if (isset($data['name'])) { if (isset($data['name'])) {
$this->tagValidateName($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) * @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 { 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 // just do a syntactic check on the tag ID
$this->tagValidateId($user, $id, $byName, false); $this->tagValidateId($user, $id, $byName, false);
$field = !$byName ? "id" : "name"; $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 { 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)); 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 // validate the tag ID, and get the numeric ID if matching by name
$id = $this->tagValidateId($user, $id, $byName, true)['id']; $id = $this->tagValidateId($user, $id, $byName, true)['id'];
// an empty subscription list is a special case // an empty subscription list is a special case

View file

@ -27,11 +27,6 @@ class User {
return (string) $this->id; 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 { public function auth(string $user, string $password): bool {
$prevUser = $this->id; $prevUser = $this->id;
$this->id = $user; $this->id = $user;
@ -50,34 +45,18 @@ class User {
} }
public function list(): array { public function list(): array {
$func = "userList";
if (!$this->authorize("", $func)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => ""]);
}
return $this->u->userList(); return $this->u->userList();
} }
public function exists(string $user): bool { 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); return $this->u->userExists($user);
} }
public function add($user, $password = null): string { 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()); return $this->u->userAdd($user, $password) ?? $this->u->userAdd($user, $this->generatePassword());
} }
public function remove(string $user): bool { public function remove(string $user): bool {
$func = "userRemove";
if (!$this->authorize($user, $func)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => $func, "user" => $user]);
}
try { try {
return $this->u->userRemove($user); return $this->u->userRemove($user);
} finally { // @codeCoverageIgnore } finally { // @codeCoverageIgnore
@ -89,10 +68,6 @@ class User {
} }
public function passwordSet(string $user, string $newPassword = null, $oldPassword = null): string { 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); $out = $this->u->userPasswordSet($user, $newPassword, $oldPassword) ?? $this->u->userPasswordSet($user, $this->generatePassword(), $oldPassword);
if (Arsse::$db->userExists($user)) { if (Arsse::$db->userExists($user)) {
// if the password change was successful and the user exists, set the internal password to the same value // 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 { 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); $out = $this->u->userPasswordUnset($user, $oldPassword);
if (Arsse::$db->userExists($user)) { if (Arsse::$db->userExists($user)) {
// if the password change was successful and the user exists, set the internal password to the same value // 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)) { 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); $out = $this->u->userPropertiesSet($user, $in);
// synchronize the internal database // synchronize the internal database

View file

@ -17,8 +17,6 @@ interface Driver {
public static function driverName(): string; public static function driverName(): string;
// authenticates a user against their name and password // authenticates a user against their name and password
public function auth(string $user, string $password): bool; 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 // checks whether a user exists
public function userExists(string $user): bool; public function userExists(string $user): bool;
// adds a user // adds a user

View file

@ -32,10 +32,6 @@ class Driver implements \JKingWeb\Arsse\User\Driver {
return password_verify($password, $hash); return password_verify($password, $hash);
} }
public function authorize(string $affectedUser, string $action): bool {
return true;
}
public function userExists(string $user): bool { public function userExists(string $user): bool {
return Arsse::$db->userExists($user); return Arsse::$db->userExists($user);
} }

View file

@ -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.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.authMissing' => 'Please log in to proceed',
'Exception.JKingWeb/Arsse/User/Exception.authFailed' => 'Authentication failed', '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/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.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', 'Exception.JKingWeb/Arsse/Feed/Exception.invalidCertificate' => 'Could not download feed "{url}" because its server is serving an invalid SSL certificate',

View file

@ -74,7 +74,6 @@ abstract class AbstractTest extends \JKingWeb\Arsse\Test\AbstractTest {
Arsse::$db->driverSchemaUpdate(); Arsse::$db->driverSchemaUpdate();
// create a mock user manager // create a mock user manager
Arsse::$user = \Phake::mock(User::class); Arsse::$user = \Phake::mock(User::class);
\Phake::when(Arsse::$user)->authorize->thenReturn(true);
// call the series-specific setup method // call the series-specific setup method
$setUp = "setUp".$this->series; $setUp = "setUp".$this->series;
$this->$setUp(); $this->$setUp();

View file

@ -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 { public function testMarkNothing(): void {
$this->assertSame(0, Arsse::$db->articleMark($this->user, [])); $this->assertSame(0, Arsse::$db->articleMark($this->user, []));
} }
@ -967,12 +961,6 @@ trait SeriesArticle {
$this->compareExpectations(static::$drv, $state); $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 { public function testCountArticles(): void {
$setSize = (new \ReflectionClassConstant(Database::class, "LIMIT_SET_SIZE"))->getValue(); $setSize = (new \ReflectionClassConstant(Database::class, "LIMIT_SET_SIZE"))->getValue();
$this->assertSame(2, Arsse::$db->articleCount("john.doe@example.com", (new Context)->starred(true))); $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)))); $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 { public function testFetchStarredCounts(): void {
$exp1 = ['total' => 2, 'unread' => 1, 'read' => 1]; $exp1 = ['total' => 2, 'unread' => 1, 'read' => 1];
$exp2 = ['total' => 0, 'unread' => 0, 'read' => 0]; $exp2 = ['total' => 0, 'unread' => 0, 'read' => 0];
@ -994,12 +976,6 @@ trait SeriesArticle {
$this->assertEquals($exp2, Arsse::$db->articleStarred("jane.doe@example.com")); $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 { public function testFetchLatestEdition(): void {
$this->assertSame(1001, Arsse::$db->editionLatest($this->user)); $this->assertSame(1001, Arsse::$db->editionLatest($this->user));
$this->assertSame(4, Arsse::$db->editionLatest($this->user, (new Context)->subscription(12))); $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)); 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 { public function testListTheLabelsOfAnArticle(): void {
$this->assertEquals([1,2], Arsse::$db->articleLabelsGet("john.doe@example.com", 1)); $this->assertEquals([1,2], Arsse::$db->articleLabelsGet("john.doe@example.com", 1));
$this->assertEquals([2], Arsse::$db->articleLabelsGet("john.doe@example.com", 5)); $this->assertEquals([2], Arsse::$db->articleLabelsGet("john.doe@example.com", 5));
@ -1030,12 +1000,6 @@ trait SeriesArticle {
Arsse::$db->articleLabelsGet($this->user, 101); 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 { public function testListTheCategoriesOfAnArticle(): void {
$exp = ["Fascinating", "Logical"]; $exp = ["Fascinating", "Logical"];
$this->assertSame($exp, Arsse::$db->articleCategoriesGet($this->user, 19)); $this->assertSame($exp, Arsse::$db->articleCategoriesGet($this->user, 19));
@ -1050,12 +1014,6 @@ trait SeriesArticle {
Arsse::$db->articleCategoriesGet($this->user, 101); 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 */ /** @dataProvider provideArrayContextOptions */
public function testUseTooFewValuesInArrayContext(string $option): void { public function testUseTooFewValuesInArrayContext(string $option): void {
$this->assertException("tooShort", "Db", "ExceptionInput"); $this->assertException("tooShort", "Db", "ExceptionInput");

View file

@ -102,7 +102,6 @@ trait SeriesFolder {
$user = "john.doe@example.com"; $user = "john.doe@example.com";
$folderID = $this->nextID("arsse_folders"); $folderID = $this->nextID("arsse_folders");
$this->assertSame($folderID, Arsse::$db->folderAdd($user, ['name' => "Entertainment"])); $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 = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
$state['arsse_folders']['rows'][] = [$folderID, $user, null, "Entertainment"]; $state['arsse_folders']['rows'][] = [$folderID, $user, null, "Entertainment"];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -117,7 +116,6 @@ trait SeriesFolder {
$user = "john.doe@example.com"; $user = "john.doe@example.com";
$folderID = $this->nextID("arsse_folders"); $folderID = $this->nextID("arsse_folders");
$this->assertSame($folderID, Arsse::$db->folderAdd($user, ['name' => "GNOME", 'parent' => 2])); $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 = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
$state['arsse_folders']['rows'][] = [$folderID, $user, 2, "GNOME"]; $state['arsse_folders']['rows'][] = [$folderID, $user, 2, "GNOME"];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -153,12 +151,6 @@ trait SeriesFolder {
Arsse::$db->folderAdd("john.doe@example.com", ['name' => " "]); 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 { public function testListRootFolders(): void {
$exp = [ $exp = [
['id' => 5, 'name' => "Politics", 'parent' => null, 'children' => 0, 'feeds' => 2], ['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)); $this->assertResult($exp, Arsse::$db->folderList("jane.doe@example.com", null, false));
$exp = []; $exp = [];
$this->assertResult($exp, Arsse::$db->folderList("admin@example.net", null, false)); $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 { public function testListFoldersRecursively(): void {
@ -193,8 +182,6 @@ trait SeriesFolder {
$this->assertResult($exp, Arsse::$db->folderList("john.doe@example.com", 1, true)); $this->assertResult($exp, Arsse::$db->folderList("john.doe@example.com", 1, true));
$exp = []; $exp = [];
$this->assertResult($exp, Arsse::$db->folderList("jane.doe@example.com", 4, true)); $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 { public function testListFoldersOfAMissingParent(): void {
@ -207,15 +194,8 @@ trait SeriesFolder {
Arsse::$db->folderList("john.doe@example.com", 4); // folder ID 4 belongs to Jane 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 { public function testRemoveAFolder(): void {
$this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 6)); $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']]); $state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
array_pop($state['arsse_folders']['rows']); array_pop($state['arsse_folders']['rows']);
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -223,7 +203,6 @@ trait SeriesFolder {
public function testRemoveAFolderTree(): void { public function testRemoveAFolderTree(): void {
$this->assertTrue(Arsse::$db->folderRemove("john.doe@example.com", 1)); $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']]); $state = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
foreach ([0,1,2,5] as $index) { foreach ([0,1,2,5] as $index) {
unset($state['arsse_folders']['rows'][$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 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 { public function testGetThePropertiesOfAFolder(): void {
$exp = [ $exp = [
'id' => 6, 'id' => 6,
@ -259,7 +232,6 @@ trait SeriesFolder {
'parent' => 2, 'parent' => 2,
]; ];
$this->assertArraySubset($exp, Arsse::$db->folderPropertiesGet("john.doe@example.com", 6)); $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 { public function testGetThePropertiesOfAMissingFolder(): void {
@ -277,19 +249,12 @@ trait SeriesFolder {
Arsse::$db->folderPropertiesGet("john.doe@example.com", 4); // folder ID 4 belongs to Jane 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 { public function testMakeNoChangesToAFolder(): void {
$this->assertFalse(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, [])); $this->assertFalse(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, []));
} }
public function testRenameAFolder(): void { public function testRenameAFolder(): void {
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['name' => "Opinion"])); $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 = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
$state['arsse_folders']['rows'][5][3] = "Opinion"; $state['arsse_folders']['rows'][5][3] = "Opinion";
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -316,7 +281,6 @@ trait SeriesFolder {
public function testMoveAFolder(): void { public function testMoveAFolder(): void {
$this->assertTrue(Arsse::$db->folderPropertiesSet("john.doe@example.com", 6, ['parent' => 5])); $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 = $this->primeExpectations($this->data, ['arsse_folders' => ['id','owner', 'parent', 'name']]);
$state['arsse_folders']['rows'][5][2] = 5; // parent should have changed $state['arsse_folders']['rows'][5][2] = 5; // parent should have changed
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -371,10 +335,4 @@ trait SeriesFolder {
$this->assertException("subjectMissing", "Db", "ExceptionInput"); $this->assertException("subjectMissing", "Db", "ExceptionInput");
Arsse::$db->folderPropertiesSet("john.doe@example.com", 4, ['parent' => null]); // folder ID 4 belongs to Jane 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]);
}
} }

View file

@ -94,10 +94,4 @@ trait SeriesIcon {
]; ];
$this->assertResult($exp, Arsse::$db->iconList("jane.doe@example.com")); $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");
}
} }

View file

@ -253,7 +253,6 @@ trait SeriesLabel {
$user = "john.doe@example.com"; $user = "john.doe@example.com";
$labelID = $this->nextID("arsse_labels"); $labelID = $this->nextID("arsse_labels");
$this->assertSame($labelID, Arsse::$db->labelAdd($user, ['name' => "Entertaining"])); $this->assertSame($labelID, Arsse::$db->labelAdd($user, ['name' => "Entertaining"]));
\Phake::verify(Arsse::$user)->authorize($user, "labelAdd");
$state = $this->primeExpectations($this->data, $this->checkLabels); $state = $this->primeExpectations($this->data, $this->checkLabels);
$state['arsse_labels']['rows'][] = [$labelID, $user, "Entertaining"]; $state['arsse_labels']['rows'][] = [$labelID, $user, "Entertaining"];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -279,12 +278,6 @@ trait SeriesLabel {
Arsse::$db->labelAdd("john.doe@example.com", ['name' => " "]); 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 { public function testListLabels(): void {
$exp = [ $exp = [
['id' => 2, 'name' => "Fascinating", 'articles' => 3, 'read' => 1], ['id' => 2, 'name' => "Fascinating", 'articles' => 3, 'read' => 1],
@ -298,18 +291,10 @@ trait SeriesLabel {
$this->assertResult($exp, Arsse::$db->labelList("jane.doe@example.com")); $this->assertResult($exp, Arsse::$db->labelList("jane.doe@example.com"));
$exp = []; $exp = [];
$this->assertResult($exp, Arsse::$db->labelList("jane.doe@example.com", false)); $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 { public function testRemoveALabel(): void {
$this->assertTrue(Arsse::$db->labelRemove("john.doe@example.com", 1)); $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); $state = $this->primeExpectations($this->data, $this->checkLabels);
array_shift($state['arsse_labels']['rows']); array_shift($state['arsse_labels']['rows']);
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -317,7 +302,6 @@ trait SeriesLabel {
public function testRemoveALabelByName(): void { public function testRemoveALabelByName(): void {
$this->assertTrue(Arsse::$db->labelRemove("john.doe@example.com", "Interesting", true)); $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); $state = $this->primeExpectations($this->data, $this->checkLabels);
array_shift($state['arsse_labels']['rows']); array_shift($state['arsse_labels']['rows']);
$this->compareExpectations(static::$drv, $state); $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 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 { public function testGetThePropertiesOfALabel(): void {
$exp = [ $exp = [
'id' => 2, '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", 2));
$this->assertArraySubset($exp, Arsse::$db->labelPropertiesGet("john.doe@example.com", "Fascinating", true)); $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 { public function testGetThePropertiesOfAMissingLabel(): void {
@ -381,19 +358,12 @@ trait SeriesLabel {
Arsse::$db->labelPropertiesGet("john.doe@example.com", 3); // label ID 3 belongs to Jane 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 { public function testMakeNoChangesToALabel(): void {
$this->assertFalse(Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, [])); $this->assertFalse(Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, []));
} }
public function testRenameALabel(): void { public function testRenameALabel(): void {
$this->assertTrue(Arsse::$db->labelPropertiesSet("john.doe@example.com", 1, ['name' => "Curious"])); $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 = $this->primeExpectations($this->data, $this->checkLabels);
$state['arsse_labels']['rows'][0][2] = "Curious"; $state['arsse_labels']['rows'][0][2] = "Curious";
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -401,7 +371,6 @@ trait SeriesLabel {
public function testRenameALabelByName(): void { public function testRenameALabelByName(): void {
$this->assertTrue(Arsse::$db->labelPropertiesSet("john.doe@example.com", "Interesting", ['name' => "Curious"], true)); $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 = $this->primeExpectations($this->data, $this->checkLabels);
$state['arsse_labels']['rows'][0][2] = "Curious"; $state['arsse_labels']['rows'][0][2] = "Curious";
$this->compareExpectations(static::$drv, $state); $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 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 { public function testListLabelledArticles(): void {
$exp = [1,19]; $exp = [1,19];
$this->assertEquals($exp, Arsse::$db->labelArticlesGet("john.doe@example.com", 1)); $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); 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 { public function testApplyALabelToArticles(): void {
Arsse::$db->labelArticlesSet("john.doe@example.com", 1, (new Context)->articles([2,5])); Arsse::$db->labelArticlesSet("john.doe@example.com", 1, (new Context)->articles([2,5]));
$state = $this->primeExpectations($this->data, $this->checkMembers); $state = $this->primeExpectations($this->data, $this->checkMembers);
@ -540,10 +497,4 @@ trait SeriesLabel {
$state['arsse_label_members']['rows'][2][3] = 0; $state['arsse_label_members']['rows'][2][3] = 0;
$this->compareExpectations(static::$drv, $state); $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]));
}
} }

View file

@ -70,9 +70,6 @@ trait SeriesSession {
$state = $this->primeExpectations($this->data, ['arsse_sessions' => ["id", "created", "expires", "user"]]); $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"); $state['arsse_sessions']['rows'][3][2] = Date::transform(Date::add(Arsse::$conf->userSessionTimeout, $now), "sql");
$this->compareExpectations(static::$drv, $state); $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 { public function testResumeAMissingSession(): void {
@ -99,12 +96,6 @@ trait SeriesSession {
$this->compareExpectations(static::$drv, $state); $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 { public function testDestroyASession(): void {
$user = "jane.doe@example.com"; $user = "jane.doe@example.com";
$id = "80fa94c1a11f11e78667001e673b2560"; $id = "80fa94c1a11f11e78667001e673b2560";
@ -131,10 +122,4 @@ trait SeriesSession {
$id = "80fa94c1a11f11e78667001e673b2560"; $id = "80fa94c1a11f11e78667001e673b2560";
$this->assertFalse(Arsse::$db->sessionDestroy($user, $id)); $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");
}
} }

View file

@ -61,7 +61,11 @@ trait SeriesSubscription {
'next_fetch' => "datetime", 'next_fetch' => "datetime",
'icon' => "int", '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' => [ 'arsse_subscriptions' => [
'columns' => [ '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 // initialize a partial mock of the Database object to later manipulate the feedUpdate method
Arsse::$db = \Phake::partialMock(Database::class, static::$drv); Arsse::$db = \Phake::partialMock(Database::class, static::$drv);
$this->user = "john.doe@example.com"; $this->user = "john.doe@example.com";
@ -163,7 +162,6 @@ trait SeriesSubscription {
$subID = $this->nextID("arsse_subscriptions"); $subID = $this->nextID("arsse_subscriptions");
\Phake::when(Arsse::$db)->feedUpdate->thenReturn(true); \Phake::when(Arsse::$db)->feedUpdate->thenReturn(true);
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url)); $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); \Phake::verify(Arsse::$db, \Phake::times(0))->feedUpdate(1, true);
$state = $this->primeExpectations($this->data, [ $state = $this->primeExpectations($this->data, [
'arsse_feeds' => ['id','url','username','password'], 'arsse_feeds' => ['id','url','username','password'],
@ -179,7 +177,6 @@ trait SeriesSubscription {
$subID = $this->nextID("arsse_subscriptions"); $subID = $this->nextID("arsse_subscriptions");
\Phake::when(Arsse::$db)->feedUpdate->thenReturn(true); \Phake::when(Arsse::$db)->feedUpdate->thenReturn(true);
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url, "", "", false)); $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); \Phake::verify(Arsse::$db)->feedUpdate($feedID, true);
$state = $this->primeExpectations($this->data, [ $state = $this->primeExpectations($this->data, [
'arsse_feeds' => ['id','url','username','password'], 'arsse_feeds' => ['id','url','username','password'],
@ -197,7 +194,6 @@ trait SeriesSubscription {
$subID = $this->nextID("arsse_subscriptions"); $subID = $this->nextID("arsse_subscriptions");
\Phake::when(Arsse::$db)->feedUpdate->thenReturn(true); \Phake::when(Arsse::$db)->feedUpdate->thenReturn(true);
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url, "", "", 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); \Phake::verify(Arsse::$db)->feedUpdate($feedID, true);
$state = $this->primeExpectations($this->data, [ $state = $this->primeExpectations($this->data, [
'arsse_feeds' => ['id','url','username','password'], 'arsse_feeds' => ['id','url','username','password'],
@ -216,7 +212,6 @@ trait SeriesSubscription {
try { try {
Arsse::$db->subscriptionAdd($this->user, $url, "", "", false); Arsse::$db->subscriptionAdd($this->user, $url, "", "", false);
} finally { } finally {
\Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionAdd");
\Phake::verify(Arsse::$db)->feedUpdate($feedID, true); \Phake::verify(Arsse::$db)->feedUpdate($feedID, true);
$state = $this->primeExpectations($this->data, [ $state = $this->primeExpectations($this->data, [
'arsse_feeds' => ['id','url','username','password'], 'arsse_feeds' => ['id','url','username','password'],
@ -246,16 +241,8 @@ trait SeriesSubscription {
$this->assertSame($subID, Arsse::$db->subscriptionAdd($this->user, $url)); $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 { public function testRemoveASubscription(): void {
$this->assertTrue(Arsse::$db->subscriptionRemove($this->user, 1)); $this->assertTrue(Arsse::$db->subscriptionRemove($this->user, 1));
\Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionRemove");
$state = $this->primeExpectations($this->data, [ $state = $this->primeExpectations($this->data, [
'arsse_feeds' => ['id','url','username','password'], 'arsse_feeds' => ['id','url','username','password'],
'arsse_subscriptions' => ['id','owner','feed'], 'arsse_subscriptions' => ['id','owner','feed'],
@ -280,12 +267,6 @@ trait SeriesSubscription {
Arsse::$db->subscriptionRemove($this->user, 1); 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 { public function testListSubscriptions(): void {
$exp = [ $exp = [
[ [
@ -308,9 +289,7 @@ trait SeriesSubscription {
], ],
]; ];
$this->assertResult($exp, Arsse::$db->subscriptionList($this->user)); $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)); $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)); $this->assertArraySubset($exp[1], Arsse::$db->subscriptionPropertiesGet($this->user, 3));
} }
@ -349,12 +328,6 @@ trait SeriesSubscription {
Arsse::$db->subscriptionList($this->user, 4); 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 { public function testCountSubscriptions(): void {
$this->assertSame(2, Arsse::$db->subscriptionCount($this->user)); $this->assertSame(2, Arsse::$db->subscriptionCount($this->user));
$this->assertSame(1, Arsse::$db->subscriptionCount($this->user, 2)); $this->assertSame(1, Arsse::$db->subscriptionCount($this->user, 2));
@ -365,12 +338,6 @@ trait SeriesSubscription {
Arsse::$db->subscriptionCount($this->user, 4); 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 { public function testGetThePropertiesOfAMissingSubscription(): void {
$this->assertException("subjectMissing", "Db", "ExceptionInput"); $this->assertException("subjectMissing", "Db", "ExceptionInput");
Arsse::$db->subscriptionPropertiesGet($this->user, 2112); Arsse::$db->subscriptionPropertiesGet($this->user, 2112);
@ -381,12 +348,6 @@ trait SeriesSubscription {
Arsse::$db->subscriptionPropertiesGet($this->user, -1); 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 { public function testSetThePropertiesOfASubscription(): void {
Arsse::$db->subscriptionPropertiesSet($this->user, 1, [ Arsse::$db->subscriptionPropertiesSet($this->user, 1, [
'title' => "Ook Ook", 'title' => "Ook Ook",
@ -394,7 +355,6 @@ trait SeriesSubscription {
'pinned' => false, 'pinned' => false,
'order_type' => 0, 'order_type' => 0,
]); ]);
\Phake::verify(Arsse::$user)->authorize($this->user, "subscriptionPropertiesSet");
$state = $this->primeExpectations($this->data, [ $state = $this->primeExpectations($this->data, [
'arsse_feeds' => ['id','url','username','password','title'], 'arsse_feeds' => ['id','url','username','password','title'],
'arsse_subscriptions' => ['id','owner','feed','title','folder','pinned','order_type'], 'arsse_subscriptions' => ['id','owner','feed','title','folder','pinned','order_type'],
@ -454,22 +414,11 @@ trait SeriesSubscription {
Arsse::$db->subscriptionPropertiesSet($this->user, -1, ['folder' => null]); 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 { public function testRetrieveTheFaviconOfASubscription(): void {
$exp = "http://example.com/favicon.ico"; $exp = "http://example.com/favicon.ico";
$this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 1)['url']); $this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 1)['url']);
$this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 2)['url']); $this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 2)['url']);
$this->assertSame(null, Arsse::$db->subscriptionIcon(null, 3)['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 { public function testRetrieveTheFaviconOfAMissingSubscription(): void {
@ -493,14 +442,6 @@ trait SeriesSubscription {
$this->assertSame(null, Arsse::$db->subscriptionIcon($user, 2)['url']); $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 { public function testListTheTagsOfASubscription(): void {
$this->assertEquals([1,2], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 1)); $this->assertEquals([1,2], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 1));
$this->assertEquals([2], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 3)); $this->assertEquals([2], Arsse::$db->subscriptionTagsGet("john.doe@example.com", 3));
@ -513,12 +454,6 @@ trait SeriesSubscription {
Arsse::$db->subscriptionTagsGet($this->user, 101); 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 { public function testGetRefreshTimeOfASubscription(): void {
$user = "john.doe@example.com"; $user = "john.doe@example.com";
$this->assertTime(strtotime("now + 1 hour"), Arsse::$db->subscriptionRefreshed($user)); $this->assertTime(strtotime("now + 1 hour"), Arsse::$db->subscriptionRefreshed($user));
@ -529,10 +464,4 @@ trait SeriesSubscription {
$this->assertException("subjectMissing", "Db", "ExceptionInput"); $this->assertException("subjectMissing", "Db", "ExceptionInput");
$this->assertTime(strtotime("now - 1 hour"), Arsse::$db->subscriptionRefreshed("john.doe@example.com", 2)); $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"));
}
} }

View file

@ -113,7 +113,6 @@ trait SeriesTag {
$user = "john.doe@example.com"; $user = "john.doe@example.com";
$tagID = $this->nextID("arsse_tags"); $tagID = $this->nextID("arsse_tags");
$this->assertSame($tagID, Arsse::$db->tagAdd($user, ['name' => "Entertaining"])); $this->assertSame($tagID, Arsse::$db->tagAdd($user, ['name' => "Entertaining"]));
\Phake::verify(Arsse::$user)->authorize($user, "tagAdd");
$state = $this->primeExpectations($this->data, $this->checkTags); $state = $this->primeExpectations($this->data, $this->checkTags);
$state['arsse_tags']['rows'][] = [$tagID, $user, "Entertaining"]; $state['arsse_tags']['rows'][] = [$tagID, $user, "Entertaining"];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -139,12 +138,6 @@ trait SeriesTag {
Arsse::$db->tagAdd("john.doe@example.com", ['name' => " "]); 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 { public function testListTags(): void {
$exp = [ $exp = [
['id' => 2, 'name' => "Fascinating"], ['id' => 2, 'name' => "Fascinating"],
@ -158,18 +151,10 @@ trait SeriesTag {
$this->assertResult($exp, Arsse::$db->tagList("jane.doe@example.com")); $this->assertResult($exp, Arsse::$db->tagList("jane.doe@example.com"));
$exp = []; $exp = [];
$this->assertResult($exp, Arsse::$db->tagList("jane.doe@example.com", false)); $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 { public function testRemoveATag(): void {
$this->assertTrue(Arsse::$db->tagRemove("john.doe@example.com", 1)); $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); $state = $this->primeExpectations($this->data, $this->checkTags);
array_shift($state['arsse_tags']['rows']); array_shift($state['arsse_tags']['rows']);
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -177,7 +162,6 @@ trait SeriesTag {
public function testRemoveATagByName(): void { public function testRemoveATagByName(): void {
$this->assertTrue(Arsse::$db->tagRemove("john.doe@example.com", "Interesting", true)); $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); $state = $this->primeExpectations($this->data, $this->checkTags);
array_shift($state['arsse_tags']['rows']); array_shift($state['arsse_tags']['rows']);
$this->compareExpectations(static::$drv, $state); $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 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 { public function testGetThePropertiesOfATag(): void {
$exp = [ $exp = [
'id' => 2, '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", 2));
$this->assertArraySubset($exp, Arsse::$db->tagPropertiesGet("john.doe@example.com", "Fascinating", true)); $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 { public function testGetThePropertiesOfAMissingTag(): void {
@ -239,19 +216,12 @@ trait SeriesTag {
Arsse::$db->tagPropertiesGet("john.doe@example.com", 3); // tag ID 3 belongs to Jane 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 { public function testMakeNoChangesToATag(): void {
$this->assertFalse(Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, [])); $this->assertFalse(Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, []));
} }
public function testRenameATag(): void { public function testRenameATag(): void {
$this->assertTrue(Arsse::$db->tagPropertiesSet("john.doe@example.com", 1, ['name' => "Curious"])); $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 = $this->primeExpectations($this->data, $this->checkTags);
$state['arsse_tags']['rows'][0][2] = "Curious"; $state['arsse_tags']['rows'][0][2] = "Curious";
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -259,7 +229,6 @@ trait SeriesTag {
public function testRenameATagByName(): void { public function testRenameATagByName(): void {
$this->assertTrue(Arsse::$db->tagPropertiesSet("john.doe@example.com", "Interesting", ['name' => "Curious"], true)); $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 = $this->primeExpectations($this->data, $this->checkTags);
$state['arsse_tags']['rows'][0][2] = "Curious"; $state['arsse_tags']['rows'][0][2] = "Curious";
$this->compareExpectations(static::$drv, $state); $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 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 { public function testListTaggedSubscriptions(): void {
$exp = [1,5]; $exp = [1,5];
$this->assertEquals($exp, Arsse::$db->tagSubscriptionsGet("john.doe@example.com", 1)); $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); 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 { public function testApplyATagToSubscriptions(): void {
Arsse::$db->tagSubscriptionsSet("john.doe@example.com", 1, [3,4]); Arsse::$db->tagSubscriptionsSet("john.doe@example.com", 1, [3,4]);
$state = $this->primeExpectations($this->data, $this->checkMembers); $state = $this->primeExpectations($this->data, $this->checkMembers);
@ -399,12 +356,6 @@ trait SeriesTag {
$this->compareExpectations(static::$drv, $state); $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 { public function testSummarizeTags(): void {
$exp = [ $exp = [
['id' => 1, 'name' => "Interesting", 'subscription' => 1], ['id' => 1, 'name' => "Interesting", 'subscription' => 1],
@ -415,10 +366,4 @@ trait SeriesTag {
]; ];
$this->assertResult($exp, Arsse::$db->tagSummarize("john.doe@example.com")); $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");
}
} }

View file

@ -67,9 +67,6 @@ trait SeriesToken {
$this->assertArraySubset($exp1, Arsse::$db->tokenLookup("fever.login", "80fa94c1a11f11e78667001e673b2560")); $this->assertArraySubset($exp1, Arsse::$db->tokenLookup("fever.login", "80fa94c1a11f11e78667001e673b2560"));
$this->assertArraySubset($exp2, Arsse::$db->tokenLookup("class.class", "da772f8fa13c11e78667001e673b2560")); $this->assertArraySubset($exp2, Arsse::$db->tokenLookup("class.class", "da772f8fa13c11e78667001e673b2560"));
$this->assertArraySubset($exp3, Arsse::$db->tokenLookup("class.class", "ab3b3eb8a13311e78667001e673b2560")); $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 { public function testLookUpAMissingToken(): void {
@ -106,12 +103,6 @@ trait SeriesToken {
Arsse::$db->tokenCreate("fever.login", "jane.doe@example.biz"); 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 { public function testRevokeAToken(): void {
$user = "jane.doe@example.com"; $user = "jane.doe@example.com";
$id = "80fa94c1a11f11e78667001e673b2560"; $id = "80fa94c1a11f11e78667001e673b2560";
@ -136,10 +127,4 @@ trait SeriesToken {
// revoking tokens which do not exist is not an error // revoking tokens which do not exist is not an error
$this->assertFalse(Arsse::$db->tokenRevoke($user, "unknown.class")); $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");
}
} }

View file

@ -33,21 +33,12 @@ trait SeriesUser {
public function testCheckThatAUserExists(): void { public function testCheckThatAUserExists(): void {
$this->assertTrue(Arsse::$db->userExists("jane.doe@example.com")); $this->assertTrue(Arsse::$db->userExists("jane.doe@example.com"));
$this->assertFalse(Arsse::$db->userExists("jane.doe@example.org")); $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); $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 { public function testGetAPassword(): void {
$hash = Arsse::$db->userPasswordGet("admin@example.net"); $hash = Arsse::$db->userPasswordGet("admin@example.net");
$this->assertSame('$2y$10$PbcG2ZR3Z8TuPzM7aHTF8.v61dtCjzjK78gdZJcp4UePE8T9jEgBW', $hash); $this->assertSame('$2y$10$PbcG2ZR3Z8TuPzM7aHTF8.v61dtCjzjK78gdZJcp4UePE8T9jEgBW', $hash);
\Phake::verify(Arsse::$user)->authorize("admin@example.net", "userPasswordGet");
$this->assertTrue(password_verify("secret", $hash)); $this->assertTrue(password_verify("secret", $hash));
} }
@ -56,15 +47,8 @@ trait SeriesUser {
Arsse::$db->userPasswordGet("john.doe@example.org"); 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 { public function testAddANewUser(): void {
$this->assertTrue(Arsse::$db->userAdd("john.doe@example.org", "")); $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 = $this->primeExpectations($this->data, ['arsse_users' => ['id']]);
$state['arsse_users']['rows'][] = ["john.doe@example.org"]; $state['arsse_users']['rows'][] = ["john.doe@example.org"];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -75,15 +59,8 @@ trait SeriesUser {
Arsse::$db->userAdd("john.doe@example.com", ""); 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 { public function testRemoveAUser(): void {
$this->assertTrue(Arsse::$db->userRemove("admin@example.net")); $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']]); $state = $this->primeExpectations($this->data, ['arsse_users' => ['id']]);
array_shift($state['arsse_users']['rows']); array_shift($state['arsse_users']['rows']);
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
@ -94,22 +71,9 @@ trait SeriesUser {
Arsse::$db->userRemove("john.doe@example.org"); 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 { public function testListAllUsers(): void {
$users = ["admin@example.net", "jane.doe@example.com", "john.doe@example.com"]; $users = ["admin@example.net", "jane.doe@example.com", "john.doe@example.com"];
$this->assertSame($users, Arsse::$db->userList()); $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)); $this->assertTrue(Arsse::$db->userPasswordSet($user, $pass));
$hash = Arsse::$db->userPasswordGet($user); $hash = Arsse::$db->userPasswordGet($user);
$this->assertNotEquals("", $hash); $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'."); $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"); $this->assertException("doesNotExist", "User");
Arsse::$db->userPasswordSet("john.doe@example.org", "secret"); 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");
}
} }

View file

@ -28,7 +28,6 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest {
// create a mock user manager // create a mock user manager
Arsse::$user = \Phake::mock(\JKingWeb\Arsse\User::class); Arsse::$user = \Phake::mock(\JKingWeb\Arsse\User::class);
\Phake::when(Arsse::$user)->exists->thenReturn(true); \Phake::when(Arsse::$user)->exists->thenReturn(true);
\Phake::when(Arsse::$user)->authorize->thenReturn(true);
// create a mock Import/Export processor // create a mock Import/Export processor
$this->proc = \Phake::partialMock(AbstractImportExport::class); $this->proc = \Phake::partialMock(AbstractImportExport::class);
// initialize an SQLite memeory database // initialize an SQLite memeory database

View file

@ -33,16 +33,12 @@ class TestInternal extends \JKingWeb\Arsse\Test\AbstractTest {
* @dataProvider provideAuthentication * @dataProvider provideAuthentication
* @group slow * @group slow
*/ */
public function testAuthenticateAUser(bool $authorized, string $user, $password, bool $exp): void { public function testAuthenticateAUser(string $user, $password, bool $exp): void {
if ($authorized) { \Phake::when(Arsse::$db)->userPasswordGet("john.doe@example.com")->thenReturn('$2y$10$1zbqRJhxM8uUjeSBPp4IhO90xrqK0XjEh9Z16iIYEFRV4U.zeAFom'); // hash of "secret"
\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("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("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("kira.nerys@example.com")->thenThrow(new \JKingWeb\Arsse\User\Exception("doesNotExist")); \Phake::when(Arsse::$db)->userPasswordGet("007@example.com")->thenReturn(null);
\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)); $this->assertSame($exp, (new Driver)->auth($user, $password));
} }
@ -53,32 +49,22 @@ class TestInternal extends \JKingWeb\Arsse\Test\AbstractTest {
$kira = "kira.nerys@example.com"; $kira = "kira.nerys@example.com";
$bond = "007@example.com"; $bond = "007@example.com";
return [ return [
[false, $john, "secret", false], [$john, "secret", true],
[false, $jane, "superman", false], [$jane, "superman", true],
[false, $owen, "", false], [$owen, "", true],
[false, $kira, "ashalla", false], [$kira, "ashalla", false],
[false, $bond, "", false], [$john, "top secret", false],
[true, $john, "secret", true], [$jane, "clark kent", false],
[true, $jane, "superman", true], [$owen, "watchmaker", false],
[true, $owen, "", true], [$kira, "singha", false],
[true, $kira, "ashalla", false], [$john, "", false],
[true, $john, "top secret", false], [$jane, "", false],
[true, $jane, "clark kent", false], [$kira, "", false],
[true, $owen, "watchmaker", false], [$bond, "for England", false],
[true, $kira, "singha", false], [$bond, "", false],
[true, $john, "", false],
[true, $jane, "", false],
[true, $kira, "", false],
[true, $bond, "for England", false],
[true, $bond, "", false],
]; ];
} }
public function testAuthorizeAnAction(): void {
\Phake::verifyNoFurtherInteraction(Arsse::$db);
$this->assertTrue((new Driver)->authorize("someone", "something"));
}
public function testListUsers(): void { public function testListUsers(): void {
$john = "john.doe@example.com"; $john = "john.doe@example.com";
$jane = "jane.doe@example.com"; $jane = "jane.doe@example.com";

View file

@ -69,13 +69,9 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
} }
/** @dataProvider provideUserList */ /** @dataProvider provideUserList */
public function testListUsers(bool $authorized, $exp): void { public function testListUsers($exp): void {
$u = new User($this->drv); $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"]); \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()); $this->assertSame($exp, $u->list());
} }
@ -83,20 +79,15 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
$john = "john.doe@example.com"; $john = "john.doe@example.com";
$jane = "jane.doe@example.com"; $jane = "jane.doe@example.com";
return [ return [
[false, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")], [[$john, $jane]],
[true, [$john, $jane]],
]; ];
} }
/** @dataProvider provideExistence */ /** @dataProvider provideExistence */
public function testCheckThatAUserExists(bool $authorized, string $user, $exp): void { public function testCheckThatAUserExists(string $user, $exp): void {
$u = new User($this->drv); $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("john.doe@example.com")->thenReturn(true);
\Phake::when($this->drv)->userExists("jane.doe@example.com")->thenReturn(false); \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)); $this->assertSame($exp, $u->exists($user));
} }
@ -104,48 +95,35 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
$john = "john.doe@example.com"; $john = "john.doe@example.com";
$jane = "jane.doe@example.com"; $jane = "jane.doe@example.com";
return [ return [
[false, $john, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")], [$john, true],
[false, $jane, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")], [$jane, false],
[true, $john, true],
[true, $jane, false],
]; ];
} }
/** @dataProvider provideAdditions */ /** @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); $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("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) { \Phake::when($this->drv)->userAdd("jane.doe@example.com", $this->anything())->thenReturnCallback(function($user, $pass) {
return $pass ?? "random password"; return $pass ?? "random password";
}); });
if ($exp instanceof Exception) { if ($exp instanceof Exception) {
if ($exp instanceof \JKingWeb\Arsse\User\ExceptionAuthz) { $this->assertException("alreadyExists", "User");
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
} else {
$this->assertException("alreadyExists", "User");
}
} }
$this->assertSame($exp, $u->add($user, $password)); $this->assertSame($exp, $u->add($user, $password));
} }
/** @dataProvider provideAdditions */ /** @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); $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($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("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) { \Phake::when($this->drv)->userAdd("jane.doe@example.com", $this->logicalNot($this->isNull()))->thenReturnCallback(function($user, $pass) {
return $pass; return $pass;
}); });
if ($exp instanceof Exception) { if ($exp instanceof Exception) {
if ($exp instanceof \JKingWeb\Arsse\User\ExceptionAuthz) { $this->assertException("alreadyExists", "User");
$this->assertException("notAuthorized", "User", "ExceptionAuthz"); $calls = 2;
$calls = 0;
} else {
$this->assertException("alreadyExists", "User");
$calls = 2;
}
} else { } else {
$calls = 4; $calls = 4;
} }
@ -163,34 +141,27 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
$john = "john.doe@example.com"; $john = "john.doe@example.com";
$jane = "jane.doe@example.com"; $jane = "jane.doe@example.com";
return [ return [
[false, $john, "secret", new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")], [$john, "secret", new \JKingWeb\Arsse\User\Exception("alreadyExists")],
[false, $jane, "superman", new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")], [$jane, "superman", "superman"],
[true, $john, "secret", new \JKingWeb\Arsse\User\Exception("alreadyExists")], [$jane, null, "random password"],
[true, $jane, "superman", "superman"],
[true, $jane, null, "random password"],
]; ];
} }
/** @dataProvider provideRemovals */ /** @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); $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("john.doe@example.com")->thenReturn(true);
\Phake::when($this->drv)->userRemove("jane.doe@example.com")->thenThrow(new \JKingWeb\Arsse\User\Exception("doesNotExist")); \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)->userExists->thenReturn($exists);
\Phake::when(Arsse::$db)->userRemove->thenReturn(true); \Phake::when(Arsse::$db)->userRemove->thenReturn(true);
if ($exp instanceof Exception) { if ($exp instanceof Exception) {
if ($exp instanceof \JKingWeb\Arsse\User\ExceptionAuthz) { $this->assertException("doesNotExist", "User");
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
} else {
$this->assertException("doesNotExist", "User");
}
} }
try { try {
$this->assertSame($exp, $u->remove($user)); $this->assertSame($exp, $u->remove($user));
} finally { } finally {
\Phake::verify(Arsse::$db, \Phake::times((int) $authorized))->userExists($user); \Phake::verify(Arsse::$db, \Phake::times(1))->userExists($user);
\Phake::verify(Arsse::$db, \Phake::times((int) ($authorized && $exists)))->userRemove($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"; $john = "john.doe@example.com";
$jane = "jane.doe@example.com"; $jane = "jane.doe@example.com";
return [ return [
[false, $john, true, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")], [$john, true, true],
[false, $john, false, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")], [$john, false, true],
[false, $jane, true, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")], [$jane, true, new \JKingWeb\Arsse\User\Exception("doesNotExist")],
[false, $jane, false, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")], [$jane, false, new \JKingWeb\Arsse\User\Exception("doesNotExist")],
[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")],
]; ];
} }
/** @dataProvider providePasswordChanges */ /** @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); $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) { \Phake::when($this->drv)->userPasswordSet("john.doe@example.com", $this->anything(), $this->anything())->thenReturnCallback(function($user, $pass, $old) {
return $pass ?? "random password"; 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($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); \Phake::when(Arsse::$db)->userExists->thenReturn($exists);
if ($exp instanceof Exception) { if ($exp instanceof Exception) {
if ($exp instanceof \JKingWeb\Arsse\User\ExceptionAuthz) { $this->assertException("doesNotExist", "User");
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
} else {
$this->assertException("doesNotExist", "User");
}
$calls = 0; $calls = 0;
} else { } else {
$calls = 1; $calls = 1;
@ -237,9 +199,8 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
} }
/** @dataProvider providePasswordChanges */ /** @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); $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($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) { \Phake::when($this->drv)->userPasswordSet("john.doe@example.com", $this->logicalNot($this->isNull()), $this->anything())->thenReturnCallback(function($user, $pass, $old) {
return $pass ?? "random password"; 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($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); \Phake::when(Arsse::$db)->userExists->thenReturn($exists);
if ($exp instanceof Exception) { if ($exp instanceof Exception) {
if ($exp instanceof \JKingWeb\Arsse\User\ExceptionAuthz) { $this->assertException("doesNotExist", "User");
$this->assertException("notAuthorized", "User", "ExceptionAuthz"); $calls = 2;
$calls = 0;
} else {
$this->assertException("doesNotExist", "User");
$calls = 2;
}
} else { } else {
$calls = 4; $calls = 4;
} }
@ -278,19 +234,16 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
$john = "john.doe@example.com"; $john = "john.doe@example.com";
$jane = "jane.doe@example.com"; $jane = "jane.doe@example.com";
return [ return [
[false, $john, "secret", true, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")], [$john, "superman", true, "superman"],
[false, $jane, "superman", false, new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized")], [$john, null, true, "random password"],
[true, $john, "superman", true, "superman"], [$john, "superman", false, "superman"],
[true, $john, null, true, "random password"], [$john, null, false, "random password"],
[true, $john, "superman", false, "superman"], [$jane, "secret", true, new \JKingWeb\Arsse\User\Exception("doesNotExist")],
[true, $john, null, false, "random password"],
[true, $jane, "secret", true, new \JKingWeb\Arsse\User\Exception("doesNotExist")],
]; ];
} }
/** @dataProvider providePasswordClearings */ /** @dataProvider providePasswordClearings */
public function testClearAPassword(bool $authorized, bool $exists, string $user, $exp): void { public function testClearAPassword(bool $exists, string $user, $exp): void {
\Phake::when($this->drv)->authorize->thenReturn($authorized);
\Phake::when($this->drv)->userPasswordUnset->thenReturn(true); \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($this->drv)->userPasswordUnset("jane.doe@example.net", null)->thenThrow(new \JKingWeb\Arsse\User\Exception("doesNotExist"));
\Phake::when(Arsse::$db)->userExists->thenReturn($exists); \Phake::when(Arsse::$db)->userExists->thenReturn($exists);
@ -303,26 +256,19 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest {
$this->assertSame($exp, $u->passwordUnset($user)); $this->assertSame($exp, $u->passwordUnset($user));
} }
} finally { } 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 { public function providePasswordClearings(): iterable {
$forbidden = new \JKingWeb\Arsse\User\ExceptionAuthz("notAuthorized");
$missing = new \JKingWeb\Arsse\User\Exception("doesNotExist"); $missing = new \JKingWeb\Arsse\User\Exception("doesNotExist");
return [ return [
[false, true, "jane.doe@example.com", $forbidden], [true, "jane.doe@example.com", true],
[false, true, "john.doe@example.com", $forbidden], [true, "john.doe@example.com", true],
[false, true, "jane.doe@example.net", $forbidden], [true, "jane.doe@example.net", $missing],
[false, false, "jane.doe@example.com", $forbidden], [false, "jane.doe@example.com", true],
[false, false, "john.doe@example.com", $forbidden], [false, "john.doe@example.com", true],
[false, false, "jane.doe@example.net", $forbidden], [false, "jane.doe@example.net", $missing],
[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],
]; ];
} }
} }