aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPytal <24800714+Pytal@users.noreply.github.com>2024-07-09 08:00:01 -0700
committerGitHub <noreply@github.com>2024-07-09 08:00:01 -0700
commit3a97dbf248b3e581b5782a638743958eb6f2a640 (patch)
tree83d6d8da3f595d5d6b99b827ef3b19dbbb17b01d /lib
parent025a7849b487351d0240d89833b3ab825897097d (diff)
parentc390ae94ff21c553fadc6645ca311eb42a46195f (diff)
downloadnextcloud-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.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/private/User/Database.php39
-rw-r--r--lib/private/User/LazyUser.php8
-rw-r--r--lib/private/User/User.php15
-rw-r--r--lib/public/IUser.php17
-rw-r--r--lib/public/User/Backend/IPasswordHashBackend.php30
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;
+}