diff --git a/apps/user_ldap/tests/LDAPProviderTest.php b/apps/user_ldap/tests/LDAPProviderTest.php index eec5f73273..0f1480d693 100644 --- a/apps/user_ldap/tests/LDAPProviderTest.php +++ b/apps/user_ldap/tests/LDAPProviderTest.php @@ -35,6 +35,7 @@ use OCA\User_LDAP\Connection; use OCA\User_LDAP\IGroupLDAP; use OCA\User_LDAP\IUserLDAP; use OCP\EventDispatcher\IEventDispatcher; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IServerContainer; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -78,7 +79,8 @@ class LDAPProviderTest extends \Test\TestCase { ->setConstructorArgs([ $this->createMock(IConfig::class), $this->createMock(EventDispatcherInterface::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), ]) ->getMock(); $userManager->expects($this->any()) diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index e447b0bfcf..036d2703d3 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -38,6 +38,8 @@ use OC\HintException; use OC\Hooks\PublicEmitter; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\IEventDispatcher; +use OCP\ICache; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IGroup; use OCP\IUser; @@ -84,14 +86,19 @@ class Manager extends PublicEmitter implements IUserManager { /** @var EventDispatcherInterface */ private $dispatcher; + /** @var ICache */ + private $cache; + /** @var IEventDispatcher */ private $eventDispatcher; public function __construct(IConfig $config, EventDispatcherInterface $oldDispatcher, + ICacheFactory $cacheFactory, IEventDispatcher $eventDispatcher) { $this->config = $config; $this->dispatcher = $oldDispatcher; + $this->cache = $cacheFactory->createDistributed('user_backend_map'); $cachedUsers = &$this->cachedUsers; $this->listen('\OC\User', 'postDelete', function ($user) use (&$cachedUsers) { /** @var \OC\User\User $user */ @@ -150,11 +157,27 @@ class Manager extends PublicEmitter implements IUserManager { if (isset($this->cachedUsers[$uid])) { //check the cache first to prevent having to loop over the backends return $this->cachedUsers[$uid]; } - foreach ($this->backends as $backend) { + + $cachedBackend = $this->cache->get($uid); + if ($cachedBackend !== null && isset($this->backends[$cachedBackend])) { + // Cache has the info of the user backend already, so ask that one directly + $backend = $this->backends[$cachedBackend]; if ($backend->userExists($uid)) { return $this->getUserObject($uid, $backend); } } + + foreach ($this->backends as $i => $backend) { + if ($i === $cachedBackend) { + // Tried that one already + continue; + } + + if ($backend->userExists($uid)) { + $this->cache->set($uid, $i, 300); + return $this->getUserObject($uid, $backend); + } + } return null; } diff --git a/tests/lib/Files/Config/UserMountCacheTest.php b/tests/lib/Files/Config/UserMountCacheTest.php index 2bea4f8389..d170049aab 100644 --- a/tests/lib/Files/Config/UserMountCacheTest.php +++ b/tests/lib/Files/Config/UserMountCacheTest.php @@ -15,6 +15,7 @@ use OC\Log; use OC\User\Manager; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Config\ICachedMountInfo; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IDBConnection; use OCP\IUserManager; @@ -46,7 +47,7 @@ class UserMountCacheTest extends TestCase { protected function setUp(): void { $this->fileIds = []; $this->connection = \OC::$server->getDatabaseConnection(); - $this->userManager = new Manager($this->createMock(IConfig::class), $this->createMock(EventDispatcherInterface::class), $this->createMock(IEventDispatcher::class)); + $this->userManager = new Manager($this->createMock(IConfig::class), $this->createMock(EventDispatcherInterface::class), $this->createMock(ICacheFactory::class), $this->createMock(IEventDispatcher::class)); $userBackend = new Dummy(); $userBackend->createUser('u1', ''); $userBackend->createUser('u2', ''); diff --git a/tests/lib/Files/Storage/Wrapper/EncryptionTest.php b/tests/lib/Files/Storage/Wrapper/EncryptionTest.php index eccec7c28d..8bdb48fd85 100644 --- a/tests/lib/Files/Storage/Wrapper/EncryptionTest.php +++ b/tests/lib/Files/Storage/Wrapper/EncryptionTest.php @@ -17,6 +17,7 @@ use OCP\Encryption\Keys\IStorage; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Cache\ICache; use OCP\Files\Mount\IMountPoint; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\ILogger; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -131,7 +132,12 @@ class EncryptionTest extends Storage { $this->util = $this->getMockBuilder('\OC\Encryption\Util') ->setMethods(['getUidAndFilename', 'isFile', 'isExcluded']) - ->setConstructorArgs([new View(), new Manager($this->config, $this->createMock(EventDispatcherInterface::class), $this->createMock(IEventDispatcher::class)), $this->groupManager, $this->config, $this->arrayCache]) + ->setConstructorArgs([new View(), new Manager( + $this->config, + $this->createMock(EventDispatcherInterface::class), + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class) + ), $this->groupManager, $this->config, $this->arrayCache]) ->getMock(); $this->util->expects($this->any()) ->method('getUidAndFilename') @@ -567,7 +573,12 @@ class EncryptionTest extends Storage { ->setConstructorArgs( [ new View(), - new Manager($this->config, $this->createMock(EventDispatcherInterface::class), $this->createMock(IEventDispatcher::class)), + new Manager( + $this->config, + $this->createMock(EventDispatcherInterface::class), + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class) + ), $this->groupManager, $this->config, $this->arrayCache @@ -635,7 +646,12 @@ class EncryptionTest extends Storage { ->willReturn($exists); $util = $this->getMockBuilder('\OC\Encryption\Util') - ->setConstructorArgs([new View(), new Manager($this->config, $this->createMock(EventDispatcherInterface::class), $this->createMock(IEventDispatcher::class)), $this->groupManager, $this->config, $this->arrayCache]) + ->setConstructorArgs([new View(), new Manager( + $this->config, + $this->createMock(EventDispatcherInterface::class), + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class) + ), $this->groupManager, $this->config, $this->arrayCache]) ->getMock(); $cache = $this->getMockBuilder('\OC\Files\Cache\Cache') diff --git a/tests/lib/Files/Stream/EncryptionTest.php b/tests/lib/Files/Stream/EncryptionTest.php index 08264f07fc..5516c0bf65 100644 --- a/tests/lib/Files/Stream/EncryptionTest.php +++ b/tests/lib/Files/Stream/EncryptionTest.php @@ -7,6 +7,7 @@ use OC\Files\View; use OC\Memcache\ArrayCache; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Cache\ICache; +use OCP\ICacheFactory; use OCP\IConfig; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -49,7 +50,12 @@ class EncryptionTest extends \Test\TestCase { $file->expects($this->any())->method('getAccessList')->willReturn([]); $util = $this->getMockBuilder('\OC\Encryption\Util') ->setMethods(['getUidAndFilename']) - ->setConstructorArgs([new View(), new \OC\User\Manager($config, $this->createMock(EventDispatcherInterface::class), $this->createMock(IEventDispatcher::class)), $groupManager, $config, $arrayCache]) + ->setConstructorArgs([new View(), new \OC\User\Manager( + $config, + $this->createMock(EventDispatcherInterface::class), + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class) + ), $groupManager, $config, $arrayCache]) ->getMock(); $util->expects($this->any()) ->method('getUidAndFilename') diff --git a/tests/lib/User/ManagerTest.php b/tests/lib/User/ManagerTest.php index 6037277932..cfdecba980 100644 --- a/tests/lib/User/ManagerTest.php +++ b/tests/lib/User/ManagerTest.php @@ -13,6 +13,8 @@ use OC\AllConfig; use OC\User\Database; use OC\User\Manager; use OCP\EventDispatcher\IEventDispatcher; +use OCP\ICache; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IUser; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -33,6 +35,10 @@ class ManagerTest extends TestCase { private $oldDispatcher; /** @var IEventDispatcher */ private $eventDispatcher; + /** @var ICacheFactory */ + private $cacheFactory; + /** @var ICache */ + private $cache; protected function setUp(): void { parent::setUp(); @@ -40,11 +46,17 @@ class ManagerTest extends TestCase { $this->config = $this->createMock(IConfig::class); $this->oldDispatcher = $this->createMock(EventDispatcherInterface::class); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); + $this->cacheFactory = $this->createMock(ICacheFactory::class); + $this->cache = $this->createMock(ICache::class); + + $this->cacheFactory->method('createDistributed') + ->with('user_backend_map') + ->willReturn($this->cache); } public function testGetBackends() { $userDummyBackend = $this->createMock(\Test\Util\User\Dummy::class); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($userDummyBackend); $this->assertEquals([$userDummyBackend], $manager->getBackends()); $dummyDatabaseBackend = $this->createMock(Database::class); @@ -63,7 +75,7 @@ class ManagerTest extends TestCase { ->with($this->equalTo('foo')) ->willReturn(true); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $this->assertTrue($manager->userExists('foo')); @@ -79,14 +91,14 @@ class ManagerTest extends TestCase { ->with($this->equalTo('foo')) ->willReturn(false); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $this->assertFalse($manager->userExists('foo')); } public function testUserExistsNoBackends() { - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $this->assertFalse($manager->userExists('foo')); } @@ -110,7 +122,7 @@ class ManagerTest extends TestCase { ->with($this->equalTo('foo')) ->willReturn(true); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend1); $manager->registerBackend($backend2); @@ -134,7 +146,7 @@ class ManagerTest extends TestCase { $backend2->expects($this->never()) ->method('userExists'); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend1); $manager->registerBackend($backend2); @@ -161,7 +173,7 @@ class ManagerTest extends TestCase { } }); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $user = $manager->checkPassword('foo', 'bar'); @@ -180,7 +192,7 @@ class ManagerTest extends TestCase { ->method('implementsActions') ->willReturn(false); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $this->assertFalse($manager->checkPassword('foo', 'bar')); @@ -198,7 +210,7 @@ class ManagerTest extends TestCase { $backend->expects($this->never()) ->method('loginName2UserName'); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $this->assertEquals('foo', $manager->get('foo')->getUID()); @@ -214,7 +226,7 @@ class ManagerTest extends TestCase { ->with($this->equalTo('foo')) ->willReturn(false); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $this->assertEquals(null, $manager->get('foo')); @@ -232,7 +244,7 @@ class ManagerTest extends TestCase { $backend->expects($this->never()) ->method('loginName2UserName'); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $this->assertEquals('bLeNdEr', $manager->get('bLeNdEr')->getUID()); @@ -250,7 +262,7 @@ class ManagerTest extends TestCase { $backend->expects($this->never()) ->method('loginName2UserName'); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $result = $manager->search('fo'); @@ -284,7 +296,7 @@ class ManagerTest extends TestCase { $backend2->expects($this->never()) ->method('loginName2UserName'); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend1); $manager->registerBackend($backend2); @@ -338,7 +350,7 @@ class ManagerTest extends TestCase { ->willReturn(true); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $this->expectException(\InvalidArgumentException::class, $exception); @@ -365,7 +377,7 @@ class ManagerTest extends TestCase { $backend->expects($this->never()) ->method('loginName2UserName'); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $user = $manager->createUser('foo', 'bar'); @@ -392,7 +404,7 @@ class ManagerTest extends TestCase { ->with($this->equalTo('foo')) ->willReturn(true); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $manager->createUser('foo', 'bar'); @@ -413,14 +425,14 @@ class ManagerTest extends TestCase { $backend->expects($this->never()) ->method('userExists'); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $this->assertFalse($manager->createUser('foo', 'bar')); } public function testCreateUserNoBackends() { - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $this->assertFalse($manager->createUser('foo', 'bar')); } @@ -440,7 +452,7 @@ class ManagerTest extends TestCase { ->with('MyUid', 'MyPassword') ->willReturn(false); - $manager = new Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->createUserFromBackend('MyUid', 'MyPassword', $backend); } @@ -480,7 +492,7 @@ class ManagerTest extends TestCase { ->with($this->equalTo('foo')) ->willReturn(true); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend1); $manager->registerBackend($backend2); @@ -488,7 +500,7 @@ class ManagerTest extends TestCase { } public function testCountUsersNoBackend() { - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $result = $manager->countUsers(); $this->assertTrue(is_array($result)); @@ -513,7 +525,7 @@ class ManagerTest extends TestCase { ->method('getBackendName') ->willReturn('Mock_Test_Util_User_Dummy'); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $result = $manager->countUsers(); @@ -554,7 +566,7 @@ class ManagerTest extends TestCase { ->method('getBackendName') ->willReturn('Mock_Test_Util_User_Dummy'); - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend1); $manager->registerBackend($backend2); @@ -655,7 +667,7 @@ class ManagerTest extends TestCase { } public function testDeleteUser() { - $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($this->config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $backend = new \Test\Util\User\Dummy(); $manager->registerBackend($backend); @@ -689,7 +701,7 @@ class ManagerTest extends TestCase { ->with($this->equalTo('uid2')) ->willReturn(true); - $manager = new \OC\User\Manager($config, $this->oldDispatcher, $this->eventDispatcher); + $manager = new \OC\User\Manager($config, $this->oldDispatcher, $this->cacheFactory, $this->eventDispatcher); $manager->registerBackend($backend); $users = $manager->getByEmail('test@example.com'); diff --git a/tests/lib/User/SessionTest.php b/tests/lib/User/SessionTest.php index d2aa0ee025..8f72ba06b9 100644 --- a/tests/lib/User/SessionTest.php +++ b/tests/lib/User/SessionTest.php @@ -21,6 +21,7 @@ use OC\User\User; use OCA\DAV\Connector\Sabre\Auth; use OCP\AppFramework\Utility\ITimeFactory; use OCP\EventDispatcher\IEventDispatcher; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\ILogger; use OCP\IRequest; @@ -232,7 +233,8 @@ class SessionTest extends \Test\TestCase { ->setConstructorArgs([ $this->config, $this->createMock(EventDispatcherInterface::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), ]) ->getMock(); @@ -298,7 +300,8 @@ class SessionTest extends \Test\TestCase { ->setConstructorArgs([ $this->config, $this->createMock(EventDispatcherInterface::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), ]) ->getMock(); @@ -331,7 +334,8 @@ class SessionTest extends \Test\TestCase { ->setConstructorArgs([ $this->config, $this->createMock(EventDispatcherInterface::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), ]) ->getMock(); $backend = $this->createMock(\Test\Util\User\Dummy::class); @@ -574,7 +578,8 @@ class SessionTest extends \Test\TestCase { ->setConstructorArgs([ $this->config, $this->createMock(EventDispatcherInterface::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), ]) ->getMock(); $userSession = $this->getMockBuilder(Session::class) @@ -663,7 +668,8 @@ class SessionTest extends \Test\TestCase { ->setConstructorArgs([ $this->config, $this->createMock(EventDispatcherInterface::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), ]) ->getMock(); $userSession = $this->getMockBuilder(Session::class) @@ -727,7 +733,8 @@ class SessionTest extends \Test\TestCase { ->setConstructorArgs([ $this->config, $this->createMock(EventDispatcherInterface::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), ]) ->getMock(); $userSession = $this->getMockBuilder(Session::class) @@ -779,7 +786,8 @@ class SessionTest extends \Test\TestCase { ->setConstructorArgs([ $this->config, $this->createMock(EventDispatcherInterface::class), - $this->createMock(IEventDispatcher::class) + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), ]) ->getMock(); $userSession = $this->getMockBuilder(Session::class)