mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 21:22:40 +00:00
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/Exception.authFailed" => 10412,
|
||||||
"User/ExceptionAuthz.notAuthorized" => 10421,
|
"User/ExceptionAuthz.notAuthorized" => 10421,
|
||||||
"User/ExceptionSession.invalid" => 10431,
|
"User/ExceptionSession.invalid" => 10431,
|
||||||
|
"User/ExceptionInput.invalidTimezone" => 10441,
|
||||||
|
"User/ExceptionInput.invalidBoolean" => 10442,
|
||||||
"Feed/Exception.internalError" => 10500,
|
"Feed/Exception.internalError" => 10500,
|
||||||
"Feed/Exception.invalidCertificate" => 10501,
|
"Feed/Exception.invalidCertificate" => 10501,
|
||||||
"Feed/Exception.invalidUrl" => 10502,
|
"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
|
* associations with articles. There has been an effort to keep public method
|
||||||
* names consistent throughout, but protected methods, having different
|
* names consistent throughout, but protected methods, having different
|
||||||
* concerns, will typically follow different conventions.
|
* 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 {
|
class Database {
|
||||||
/** The version number of the latest schema the interface is aware of */
|
/** The version number of the latest schema the interface is aware of */
|
||||||
|
@ -311,6 +314,35 @@ class Database {
|
||||||
return true;
|
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 */
|
/** 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 the user isn't authorized to perform this action then throw an exception.
|
||||||
|
|
41
lib/User.php
41
lib/User.php
|
@ -6,6 +6,7 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\Arsse;
|
namespace JKingWeb\Arsse;
|
||||||
|
|
||||||
|
use JKingWeb\Arsse\Misc\ValueInfo as V;
|
||||||
use PasswordGenerator\Generator as PassGen;
|
use PasswordGenerator\Generator as PassGen;
|
||||||
|
|
||||||
class User {
|
class User {
|
||||||
|
@ -120,4 +121,44 @@ class User {
|
||||||
public function generatePassword(): string {
|
public function generatePassword(): string {
|
||||||
return (new PassGen)->length(Arsse::$conf->userTempPasswordLength)->get();
|
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