From: Thomas Citharel Date: Fri, 2 Dec 2022 16:46:37 +0000 (+0100) Subject: Create the database user in a transaction X-Git-Tag: v27.0.0beta1~330^2 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=refs%2Fpull%2F35561%2Fhead;p=nextcloud-server.git Create the database user in a transaction In OC\User\Manager::createUserFromBackend the newly created user is read using getUserObject($uid, $backend) but that can cause causal read issues (wrote in DB primary, not yet in secondary). In OC\User\Database user backend the user cache is unset after the insert, so it can't be used by getRealUID() (which is called by getUserObject()). To avoid that we make sure the user cache is repopulated in a transaction. Signed-off-by: Thomas Citharel --- diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php index 8bbbccd4540..944202f244e 100644 --- a/lib/private/User/Database.php +++ b/lib/private/User/Database.php @@ -45,6 +45,7 @@ declare(strict_types=1); */ namespace OC\User; +use OCP\AppFramework\Db\TTransactional; use OCP\Cache\CappedMemoryCache; use OCP\EventDispatcher\IEventDispatcher; use OCP\IDBConnection; @@ -85,6 +86,8 @@ class Database extends ABackend implements /** @var string */ private $table; + use TTransactional; + /** * \OC\User\Database constructor. * @@ -122,20 +125,24 @@ class Database extends ABackend implements if (!$this->userExists($uid)) { $this->eventDispatcher->dispatchTyped(new ValidatePasswordPolicyEvent($password)); - $qb = $this->dbConn->getQueryBuilder(); - $qb->insert($this->table) - ->values([ - 'uid' => $qb->createNamedParameter($uid), - 'password' => $qb->createNamedParameter(\OC::$server->getHasher()->hash($password)), - 'uid_lower' => $qb->createNamedParameter(mb_strtolower($uid)), - ]); + return $this->atomic(function () use ($uid, $password) { + $qb = $this->dbConn->getQueryBuilder(); + $qb->insert($this->table) + ->values([ + 'uid' => $qb->createNamedParameter($uid), + 'password' => $qb->createNamedParameter(\OC::$server->getHasher()->hash($password)), + 'uid_lower' => $qb->createNamedParameter(mb_strtolower($uid)), + ]); - $result = $qb->execute(); + $result = $qb->executeStatement(); - // Clear cache - unset($this->cache[$uid]); + // Clear cache + unset($this->cache[$uid]); + // Repopulate the cache + $this->loadUser($uid); - return $result ? true : false; + return (bool) $result; + }, $this->dbConn); } return false;