diff options
author | Pytal <24800714+Pytal@users.noreply.github.com> | 2024-07-09 08:00:01 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-09 08:00:01 -0700 |
commit | 3a97dbf248b3e581b5782a638743958eb6f2a640 (patch) | |
tree | 83d6d8da3f595d5d6b99b827ef3b19dbbb17b01d /lib | |
parent | 025a7849b487351d0240d89833b3ab825897097d (diff) | |
parent | c390ae94ff21c553fadc6645ca311eb42a46195f (diff) | |
download | nextcloud-server-3a97dbf248b3e581b5782a638743958eb6f2a640.tar.gz nextcloud-server-3a97dbf248b3e581b5782a638743958eb6f2a640.zip |
Merge pull request #46123 from nextcloud/feat/user-password-hash
feat: Allow getting/setting the password hash of a user
Diffstat (limited to 'lib')
-rw-r--r-- | lib/composer/composer/autoload_classmap.php | 1 | ||||
-rw-r--r-- | lib/composer/composer/autoload_static.php | 1 | ||||
-rw-r--r-- | lib/private/User/Database.php | 39 | ||||
-rw-r--r-- | lib/private/User/LazyUser.php | 8 | ||||
-rw-r--r-- | lib/private/User/User.php | 15 | ||||
-rw-r--r-- | lib/public/IUser.php | 17 | ||||
-rw-r--r-- | lib/public/User/Backend/IPasswordHashBackend.php | 30 |
7 files changed, 110 insertions, 1 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index f0addbcdaa8..6bee8c52568 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -799,6 +799,7 @@ return array( 'OCP\\User\\Backend\\IGetHomeBackend' => $baseDir . '/lib/public/User/Backend/IGetHomeBackend.php', 'OCP\\User\\Backend\\IGetRealUIDBackend' => $baseDir . '/lib/public/User/Backend/IGetRealUIDBackend.php', 'OCP\\User\\Backend\\IPasswordConfirmationBackend' => $baseDir . '/lib/public/User/Backend/IPasswordConfirmationBackend.php', + 'OCP\\User\\Backend\\IPasswordHashBackend' => $baseDir . '/lib/public/User/Backend/IPasswordHashBackend.php', 'OCP\\User\\Backend\\IProvideAvatarBackend' => $baseDir . '/lib/public/User/Backend/IProvideAvatarBackend.php', 'OCP\\User\\Backend\\IProvideEnabledStateBackend' => $baseDir . '/lib/public/User/Backend/IProvideEnabledStateBackend.php', 'OCP\\User\\Backend\\ISearchKnownUsersBackend' => $baseDir . '/lib/public/User/Backend/ISearchKnownUsersBackend.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 51044d28a46..31191f982ff 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -832,6 +832,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\User\\Backend\\IGetHomeBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetHomeBackend.php', 'OCP\\User\\Backend\\IGetRealUIDBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetRealUIDBackend.php', 'OCP\\User\\Backend\\IPasswordConfirmationBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordConfirmationBackend.php', + 'OCP\\User\\Backend\\IPasswordHashBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordHashBackend.php', 'OCP\\User\\Backend\\IProvideAvatarBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IProvideAvatarBackend.php', 'OCP\\User\\Backend\\IProvideEnabledStateBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IProvideEnabledStateBackend.php', 'OCP\\User\\Backend\\ISearchKnownUsersBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ISearchKnownUsersBackend.php', diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php index cc7050f2da8..bd6aa7ba2c2 100644 --- a/lib/private/User/Database.php +++ b/lib/private/User/Database.php @@ -8,6 +8,7 @@ declare(strict_types=1); */ namespace OC\User; +use InvalidArgumentException; use OCP\AppFramework\Db\TTransactional; use OCP\Cache\CappedMemoryCache; use OCP\EventDispatcher\IEventDispatcher; @@ -21,6 +22,7 @@ use OCP\User\Backend\ICreateUserBackend; use OCP\User\Backend\IGetDisplayNameBackend; use OCP\User\Backend\IGetHomeBackend; use OCP\User\Backend\IGetRealUIDBackend; +use OCP\User\Backend\IPasswordHashBackend; use OCP\User\Backend\ISearchKnownUsersBackend; use OCP\User\Backend\ISetDisplayNameBackend; use OCP\User\Backend\ISetPasswordBackend; @@ -37,7 +39,8 @@ class Database extends ABackend implements IGetHomeBackend, ICountUsersBackend, ISearchKnownUsersBackend, - IGetRealUIDBackend { + IGetRealUIDBackend, + IPasswordHashBackend { /** @var CappedMemoryCache */ private $cache; @@ -176,6 +179,40 @@ class Database extends ABackend implements return false; } + public function getPasswordHash(string $userId): ?string { + $this->fixDI(); + if (!$this->userExists($userId)) { + return null; + } + if (!empty($this->cache[$userId]['password'])) { + return $this->cache[$userId]['password']; + } + $qb = $this->dbConn->getQueryBuilder(); + $qb->select('password') + ->from($this->table) + ->where($qb->expr()->eq('uid_lower', $qb->createNamedParameter(mb_strtolower($userId)))); + /** @var false|string $hash */ + $hash = $qb->executeQuery()->fetchOne(); + if ($hash === false) { + return null; + } + $this->cache[$userId]['password'] = $hash; + return $hash; + } + + public function setPasswordHash(string $userId, string $passwordHash): bool { + if (!\OCP\Server::get(IHasher::class)->validate($passwordHash)) { + throw new InvalidArgumentException(); + } + $this->fixDI(); + $result = $this->updatePassword($userId, $passwordHash); + if (!$result) { + return false; + } + $this->cache[$userId]['password'] = $passwordHash; + return true; + } + /** * Set display name * diff --git a/lib/private/User/LazyUser.php b/lib/private/User/LazyUser.php index 80b2bfe510f..cd3e268be48 100644 --- a/lib/private/User/LazyUser.php +++ b/lib/private/User/LazyUser.php @@ -73,6 +73,14 @@ class LazyUser implements IUser { return $this->getUser()->setPassword($password, $recoveryPassword); } + public function getPasswordHash(): ?string { + return $this->getUser()->getPasswordHash(); + } + + public function setPasswordHash(string $passwordHash): bool { + return $this->getUser()->setPasswordHash($passwordHash); + } + public function getHome() { return $this->getUser()->getHome(); } diff --git a/lib/private/User/User.php b/lib/private/User/User.php index 644d3e27f88..6495b5cf276 100644 --- a/lib/private/User/User.php +++ b/lib/private/User/User.php @@ -25,6 +25,7 @@ use OCP\IUser; use OCP\IUserBackend; use OCP\Notification\IManager as INotificationManager; use OCP\User\Backend\IGetHomeBackend; +use OCP\User\Backend\IPasswordHashBackend; use OCP\User\Backend\IProvideAvatarBackend; use OCP\User\Backend\IProvideEnabledStateBackend; use OCP\User\Backend\ISetDisplayNameBackend; @@ -319,6 +320,20 @@ class User implements IUser { } } + public function getPasswordHash(): ?string { + if (!($this->backend instanceof IPasswordHashBackend)) { + return null; + } + return $this->backend->getPasswordHash($this->uid); + } + + public function setPasswordHash(string $passwordHash): bool { + if (!($this->backend instanceof IPasswordHashBackend)) { + return false; + } + return $this->backend->setPasswordHash($this->uid, $passwordHash); + } + /** * get the users home folder to mount * diff --git a/lib/public/IUser.php b/lib/public/IUser.php index 2ed2d0d87b2..4ba9a89f064 100644 --- a/lib/public/IUser.php +++ b/lib/public/IUser.php @@ -77,6 +77,23 @@ interface IUser { public function setPassword($password, $recoveryPassword = null); /** + * Get the password hash of the user + * + * @return ?string the password hash hashed by `\OCP\Security\IHasher::hash()` + * @since 30.0.0 + */ + public function getPasswordHash(): ?string; + + /** + * Set the password hash of the user + * + * @param string $passwordHash the password hash hashed by `\OCP\Security\IHasher::hash()` + * @throws InvalidArgumentException when `$passwordHash` is not a valid hash + * @since 30.0.0 + */ + public function setPasswordHash(string $passwordHash): bool; + + /** * get the users home folder to mount * * @return string diff --git a/lib/public/User/Backend/IPasswordHashBackend.php b/lib/public/User/Backend/IPasswordHashBackend.php new file mode 100644 index 00000000000..2525b4e45ea --- /dev/null +++ b/lib/public/User/Backend/IPasswordHashBackend.php @@ -0,0 +1,30 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\User\Backend; + +use InvalidArgumentException; + +/** + * @since 30.0.0 + */ +interface IPasswordHashBackend { + /** + * @return ?string the password hash hashed by `\OCP\Security\IHasher::hash()` + * @since 30.0.0 + */ + public function getPasswordHash(string $userId): ?string; + + /** + * @param string $passwordHash the password hash hashed by `\OCP\Security\IHasher::hash()` + * @throws InvalidArgumentException when `$passwordHash` is not a valid hash + * @since 30.0.0 + */ + public function setPasswordHash(string $userId, string $passwordHash): bool; +} |