diff --git a/lib/User.php b/lib/User.php index 56e716b..afe4920 100644 --- a/lib/User.php +++ b/lib/User.php @@ -90,10 +90,10 @@ class User { } public function propertiesGet(string $user): array { + $extra = $this->u->userPropertiesGet($user); // 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]; @@ -102,7 +102,7 @@ class User { return $out; } - public function propertiesSet(string $user, array $data): bool { + public function propertiesSet(string $user, array $data): array { $in = []; if (array_key_exists("tz", $data)) { if (!is_string($data['tz'])) { @@ -125,7 +125,7 @@ class User { } $out = $this->u->userPropertiesSet($user, $in); // synchronize the internal database - Arsse::$db->userPropertiesSet($user, $in); + Arsse::$db->userPropertiesSet($user, $out); return $out; } } diff --git a/lib/User/Driver.php b/lib/User/Driver.php index 6bfa25b..dbf8ad6 100644 --- a/lib/User/Driver.php +++ b/lib/User/Driver.php @@ -33,7 +33,7 @@ interface Driver { /** Lists all users */ public function userList(): array; - /** sets a user's password + /** Sets a user's password * * When given no password the implementation may return null; the user * manager will then generate a random password and try again with that @@ -46,10 +46,35 @@ interface Driver { */ public function userPasswordSet(string $user, ?string $newPassword, string $oldPassword = null); - /** removes a user's password; this makes authentication fail unconditionally + /** Removes a user's password; this makes authentication fail unconditionally * * @param string $user The user for whom to change the password * @param string|null $oldPassword The user's previous password, if known */ public function userPasswordUnset(string $user, string $oldPassword = null): bool; + + /** Retrieves metadata about a user + * + * Any expected keys not returned by the driver are taken from the internal + * database instead; the expected keys at this time are: + * + * - admin: A boolean denoting whether the user has administrator privileges + * - lang: A BCP 47 language tag e.g. "en", "hy-Latn-IT-arevela" + * - tz: A zoneinfo timezone e.g. "Asia/Jakarta", "America/Argentina/La_Rioja" + * - sort_asc: A boolean denoting whether the user prefers articles to be sorted oldest-first + * + * Any other keys will be ignored. + */ + public function userPropertiesGet(string $user): array; + + /** Sets metadata about a user + * + * Output should be the same as the input, unless input is changed prior to storage + * (if it is, for instance, normalized in some way), which which case the changes + * should be reflected in the output. + * + * @param string $user The user for which to set metadata + * @param array $data The input data; see userPropertiesGet for keys + */ + public function userPropertiesSet(string $user, array $data): array; } diff --git a/lib/User/Internal/Driver.php b/lib/User/Internal/Driver.php index 5114498..6b8e443 100644 --- a/lib/User/Internal/Driver.php +++ b/lib/User/Internal/Driver.php @@ -70,4 +70,22 @@ class Driver implements \JKingWeb\Arsse\User\Driver { protected function userExists(string $user): bool { return Arsse::$db->userExists($user); } + + public function userPropertiesGet(string $user): array { + // do nothing: the internal database will retrieve everything for us + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ['action' => "userPasswordUnset", 'user' => $user]); + } else { + return []; + } + } + + public function userPropertiesSet(string $user, array $data): array { + // do nothing: the internal database will set everything for us + if (!$this->userExists($user)) { + throw new Exception("doesNotExist", ['action' => "userPasswordUnset", 'user' => $user]); + } else { + return $data; + } + } }