Prototype changes to user management
The driver itself has not been expnaded; more is probably required to ensure metadata is kept in sync and users created when the internal database does not list a user an external database claims to have
This commit is contained in:
parent
ee050e505c
commit
532ce4a502
4 changed files with 85 additions and 0 deletions
|
@ -75,6 +75,8 @@ abstract class AbstractException extends \Exception {
|
|||
"User/Exception.authFailed" => 10412,
|
||||
"User/ExceptionAuthz.notAuthorized" => 10421,
|
||||
"User/ExceptionSession.invalid" => 10431,
|
||||
"User/ExceptionInput.invalidTimezone" => 10441,
|
||||
"User/ExceptionInput.invalidBoolean" => 10442,
|
||||
"Feed/Exception.internalError" => 10500,
|
||||
"Feed/Exception.invalidCertificate" => 10501,
|
||||
"Feed/Exception.invalidUrl" => 10502,
|
||||
|
|
|
@ -37,6 +37,9 @@ use JKingWeb\Arsse\Misc\URL;
|
|||
* associations with articles. There has been an effort to keep public method
|
||||
* names consistent throughout, but protected methods, having different
|
||||
* concerns, will typically follow different conventions.
|
||||
*
|
||||
* Note that operations on users should be performed with the User class rather
|
||||
* than the Database class directly. This is to allow for alternate user sources.
|
||||
*/
|
||||
class Database {
|
||||
/** The version number of the latest schema the interface is aware of */
|
||||
|
@ -310,6 +313,35 @@ class Database {
|
|||
$this->db->prepare("UPDATE arsse_users set password = ? where id = ?", "str", "str")->run($hash, $user);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function userPropertiesGet(string $user): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
} elseif (!$this->userExists($user)) {
|
||||
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();
|
||||
settype($out['admin'], "bool");
|
||||
settype($out['sort_asc'], "bool");
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function userPropertiesSet(string $user, array $data): bool {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||
} elseif (!$this->userExists($user)) {
|
||||
throw new User\Exception("doesNotExist", ["action" => __FUNCTION__, "user" => $user]);
|
||||
}
|
||||
$allowed = [
|
||||
'admin' => "strict bool",
|
||||
'lang' => "str",
|
||||
'tz' => "strict str",
|
||||
'sort_asc' => "strict bool",
|
||||
];
|
||||
[$setClause, $setTypes, $setValues] = $this->generateSet($data, $allowed);
|
||||
return (bool) $this->$db->prepare("UPDATE arsse_users set $setClause where user = ?", $setTypes, "str")->run($setValues, $user)->changes();
|
||||
|
||||
}
|
||||
|
||||
/** Creates a new session for the given user and returns the session identifier */
|
||||
public function sessionCreate(string $user): string {
|
||||
|
|
41
lib/User.php
41
lib/User.php
|
@ -6,6 +6,7 @@
|
|||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse;
|
||||
|
||||
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
||||
use PasswordGenerator\Generator as PassGen;
|
||||
|
||||
class User {
|
||||
|
@ -120,4 +121,44 @@ class User {
|
|||
public function generatePassword(): string {
|
||||
return (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get();
|
||||
}
|
||||
|
||||
public function propertiesGet(string $user): array {
|
||||
// unconditionally retrieve from the database to get at least the user number, and anything else the driver does not provide
|
||||
$out = Arsse::$db->userPropertiesGet($user);
|
||||
// layer on the driver's data
|
||||
$extra = $this->u->userPropertiesGet($user);
|
||||
foreach (["lang", "tz", "admin", "sort_asc"] as $k) {
|
||||
if (array_key_exists($k, $extra)) {
|
||||
$out[$k] = $extra[$k] ?? $out[$k];
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function propertiesSet(string $user, array $data): bool {
|
||||
$in = [];
|
||||
if (array_key_exists("tz", $data)) {
|
||||
if (!is_string($data['tz'])) {
|
||||
throw new User\ExceptionInput("invalidTimezone");
|
||||
} elseif (!in_array($data['tz'], \DateTimeZone::listIdentifiers())) {
|
||||
throw new User\ExceptionInput("invalidTimezone", $data['tz']);
|
||||
}
|
||||
$in['tz'] = $data['tz'];
|
||||
}
|
||||
foreach (["admin", "sort_asc"] as $k) {
|
||||
if (array_key_exists($k, $data)) {
|
||||
if (($v = V::normalize($data[$k], V::T_BOOL)) === null) {
|
||||
throw new User\ExceptionInput("invalidBoolean", $k);
|
||||
}
|
||||
$in[$k] = $v;
|
||||
}
|
||||
}
|
||||
if (array_key_exists("lang", $data)) {
|
||||
$in['lang'] = V::normalize($data['lang'], V::T_STRING | M_NULL);
|
||||
}
|
||||
$out = $this->u->userPropertiesSet($user, $in);
|
||||
// synchronize the internal database
|
||||
Arsse::$db->userPropertiesSet($user, $in);
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
|
10
lib/User/ExceptionInput.php
Normal file
10
lib/User/ExceptionInput.php
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
/** @license MIT
|
||||
* Copyright 2017 J. King, Dustin Wilson et al.
|
||||
* See LICENSE and AUTHORS files for details */
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\Arsse\User;
|
||||
|
||||
class ExceptionInput extends Exception {
|
||||
}
|
Loading…
Reference in a new issue