]> source.dussan.org Git - nextcloud-server.git/commitdiff
Create the database user in a transaction 35561/head
authorThomas Citharel <tcit@tcit.fr>
Fri, 2 Dec 2022 16:46:37 +0000 (17:46 +0100)
committerJulius Härtl (Rebase PR Action) <github@juliushaertl.de>
Wed, 15 Mar 2023 11:07:07 +0000 (11:07 +0000)
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 <tcit@tcit.fr>
lib/private/User/Database.php

index 8bbbccd4540681bbc1cfb571ff5aff2d871ce4ab..944202f244e6f9d61b7d566d5f48dacf4eaaec6b 100644 (file)
@@ -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;