diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 90e7fe51fa74a..36c346eeee766 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -1220,6 +1220,7 @@ 'OC\\Files\\ObjectStore\\Mapper' => $baseDir . '/lib/private/Files/ObjectStore/Mapper.php', 'OC\\Files\\ObjectStore\\NoopScanner' => $baseDir . '/lib/private/Files/ObjectStore/NoopScanner.php', 'OC\\Files\\ObjectStore\\ObjectStoreStorage' => $baseDir . '/lib/private/Files/ObjectStore/ObjectStoreStorage.php', + 'OC\\Files\\ObjectStore\\PrimaryObjectStoreConfig' => $baseDir . '/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php', 'OC\\Files\\ObjectStore\\S3' => $baseDir . '/lib/private/Files/ObjectStore/S3.php', 'OC\\Files\\ObjectStore\\S3ConnectionTrait' => $baseDir . '/lib/private/Files/ObjectStore/S3ConnectionTrait.php', 'OC\\Files\\ObjectStore\\S3ObjectTrait' => $baseDir . '/lib/private/Files/ObjectStore/S3ObjectTrait.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 8cef29efc39bc..ffc09ad71aba5 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -1253,6 +1253,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Files\\ObjectStore\\Mapper' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/Mapper.php', 'OC\\Files\\ObjectStore\\NoopScanner' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/NoopScanner.php', 'OC\\Files\\ObjectStore\\ObjectStoreStorage' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/ObjectStoreStorage.php', + 'OC\\Files\\ObjectStore\\PrimaryObjectStoreConfig' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php', 'OC\\Files\\ObjectStore\\S3' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/S3.php', 'OC\\Files\\ObjectStore\\S3ConnectionTrait' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/S3ConnectionTrait.php', 'OC\\Files\\ObjectStore\\S3ObjectTrait' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/S3ObjectTrait.php', diff --git a/lib/private/Files/Mount/ObjectHomeMountProvider.php b/lib/private/Files/Mount/ObjectHomeMountProvider.php index 77912adfd34ed..0afe573232e98 100644 --- a/lib/private/Files/Mount/ObjectHomeMountProvider.php +++ b/lib/private/Files/Mount/ObjectHomeMountProvider.php @@ -24,117 +24,40 @@ */ namespace OC\Files\Mount; +use OC\Files\ObjectStore\HomeObjectStoreStorage; +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; use OCP\Files\Config\IHomeMountProvider; +use OCP\Files\Mount\IMountPoint; use OCP\Files\Storage\IStorageFactory; -use OCP\IConfig; use OCP\IUser; -use Psr\Log\LoggerInterface; /** * Mount provider for object store home storages */ class ObjectHomeMountProvider implements IHomeMountProvider { - /** - * @var IConfig - */ - private $config; + private PrimaryObjectStoreConfig $objectStoreConfig; - /** - * ObjectStoreHomeMountProvider constructor. - * - * @param IConfig $config - */ - public function __construct(IConfig $config) { - $this->config = $config; + public function __construct(PrimaryObjectStoreConfig $objectStoreConfig) { + $this->objectStoreConfig = $objectStoreConfig; } /** - * Get the cache mount for a user + * Get the home mount for a user * * @param IUser $user * @param IStorageFactory $loader - * @return \OCP\Files\Mount\IMountPoint - */ - public function getHomeMountForUser(IUser $user, IStorageFactory $loader) { - $config = $this->getMultiBucketObjectStoreConfig($user); - if ($config === null) { - $config = $this->getSingleBucketObjectStoreConfig($user); - } - - if ($config === null) { - return null; - } - - return new MountPoint('\OC\Files\ObjectStore\HomeObjectStoreStorage', '/' . $user->getUID(), $config['arguments'], $loader, null, null, self::class); - } - - /** - * @param IUser $user - * @return array|null - */ - private function getSingleBucketObjectStoreConfig(IUser $user) { - $config = $this->config->getSystemValue('objectstore'); - if (!is_array($config)) { - return null; - } - - // sanity checks - if (empty($config['class'])) { - \OC::$server->get(LoggerInterface::class)->error('No class given for objectstore', ['app' => 'files']); - } - if (!isset($config['arguments'])) { - $config['arguments'] = []; - } - // instantiate object store implementation - $config['arguments']['objectstore'] = new $config['class']($config['arguments']); - - $config['arguments']['user'] = $user; - - return $config; - } - - /** - * @param IUser $user - * @return array|null + * @return ?IMountPoint */ - private function getMultiBucketObjectStoreConfig(IUser $user) { - $config = $this->config->getSystemValue('objectstore_multibucket'); - if (!is_array($config)) { + public function getHomeMountForUser(IUser $user, IStorageFactory $loader): ?IMountPoint { + $objectStore = $this->objectStoreConfig->getObjectStoreForUser($user); + if ($objectStore === null) { return null; } + $arguments = array_merge($this->objectStoreConfig->getObjectStoreArgumentsForUser($user), [ + 'objectstore' => $objectStore, + 'user' => $user, + ]); - // sanity checks - if (empty($config['class'])) { - \OC::$server->get(LoggerInterface::class)->error('No class given for objectstore', ['app' => 'files']); - } - if (!isset($config['arguments'])) { - $config['arguments'] = []; - } - - $bucket = $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'bucket', null); - - if ($bucket === null) { - /* - * Use any provided bucket argument as prefix - * and add the mapping from username => bucket - */ - if (!isset($config['arguments']['bucket'])) { - $config['arguments']['bucket'] = ''; - } - $mapper = new \OC\Files\ObjectStore\Mapper($user, $this->config); - $numBuckets = isset($config['arguments']['num_buckets']) ? $config['arguments']['num_buckets'] : 64; - $config['arguments']['bucket'] .= $mapper->getBucket($numBuckets); - - $this->config->setUserValue($user->getUID(), 'homeobjectstore', 'bucket', $config['arguments']['bucket']); - } else { - $config['arguments']['bucket'] = $bucket; - } - - // instantiate object store implementation - $config['arguments']['objectstore'] = new $config['class']($config['arguments']); - - $config['arguments']['user'] = $user; - - return $config; + return new MountPoint(HomeObjectStoreStorage::class, '/' . $user->getUID(), $arguments, $loader, null, null, self::class); } } diff --git a/lib/private/Files/Mount/RootMountProvider.php b/lib/private/Files/Mount/RootMountProvider.php index b301fc6dd149d..c3e302541a4a2 100644 --- a/lib/private/Files/Mount/RootMountProvider.php +++ b/lib/private/Files/Mount/RootMountProvider.php @@ -25,79 +25,42 @@ use OC; use OC\Files\ObjectStore\ObjectStoreStorage; +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; use OC\Files\Storage\LocalRootStorage; -use OC_App; use OCP\Files\Config\IRootMountProvider; +use OCP\Files\ObjectStore\IObjectStore; use OCP\Files\Storage\IStorageFactory; use OCP\IConfig; -use Psr\Log\LoggerInterface; class RootMountProvider implements IRootMountProvider { + private PrimaryObjectStoreConfig $objectStoreConfig; private IConfig $config; - private LoggerInterface $logger; - public function __construct(IConfig $config, LoggerInterface $logger) { + public function __construct(PrimaryObjectStoreConfig $objectStoreConfig, IConfig $config) { + $this->objectStoreConfig = $objectStoreConfig; $this->config = $config; - $this->logger = $logger; } public function getRootMounts(IStorageFactory $loader): array { - $objectStore = $this->config->getSystemValue('objectstore', null); - $objectStoreMultiBucket = $this->config->getSystemValue('objectstore_multibucket', null); + $objectStore = $this->objectStoreConfig->getObjectStoreForRoot(); - if ($objectStoreMultiBucket) { - return [$this->getMultiBucketStoreRootMount($loader, $objectStoreMultiBucket)]; - } elseif ($objectStore) { + if ($objectStore) { return [$this->getObjectStoreRootMount($loader, $objectStore)]; } else { return [$this->getLocalRootMount($loader)]; } } - private function validateObjectStoreConfig(array &$config) { - if (empty($config['class'])) { - $this->logger->error('No class given for objectstore', ['app' => 'files']); - } - if (!isset($config['arguments'])) { - $config['arguments'] = []; - } - - // instantiate object store implementation - $name = $config['class']; - if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) { - $segments = explode('\\', $name); - OC_App::loadApp(strtolower($segments[1])); - } - } - private function getLocalRootMount(IStorageFactory $loader): MountPoint { $configDataDirectory = $this->config->getSystemValue("datadirectory", OC::$SERVERROOT . "/data"); return new MountPoint(LocalRootStorage::class, '/', ['datadir' => $configDataDirectory], $loader, null, null, self::class); } - private function getObjectStoreRootMount(IStorageFactory $loader, array $config): MountPoint { - $this->validateObjectStoreConfig($config); - - $config['arguments']['objectstore'] = new $config['class']($config['arguments']); - // mount with plain / root object store implementation - $config['class'] = ObjectStoreStorage::class; - - return new MountPoint($config['class'], '/', $config['arguments'], $loader, null, null, self::class); - } - - private function getMultiBucketStoreRootMount(IStorageFactory $loader, array $config): MountPoint { - $this->validateObjectStoreConfig($config); - - if (!isset($config['arguments']['bucket'])) { - $config['arguments']['bucket'] = ''; - } - // put the root FS always in first bucket for multibucket configuration - $config['arguments']['bucket'] .= '0'; - - $config['arguments']['objectstore'] = new $config['class']($config['arguments']); - // mount with plain / root object store implementation - $config['class'] = ObjectStoreStorage::class; + private function getObjectStoreRootMount(IStorageFactory $loader, IObjectStore $objectStore): MountPoint { + $arguments = array_merge($this->objectStoreConfig->getObjectStoreArgumentsForRoot(), [ + 'objectstore' => $objectStore, + ]); - return new MountPoint($config['class'], '/', $config['arguments'], $loader, null, null, self::class); + return new MountPoint(ObjectStoreStorage::class, '/', $arguments, $loader, null, null, self::class); } } diff --git a/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php b/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php index afc0ac96abc80..73317ef2791f3 100644 --- a/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php +++ b/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php @@ -25,7 +25,7 @@ */ namespace OC\Files\ObjectStore; -use OC\User\User; +use OCP\IUser; class HomeObjectStoreStorage extends ObjectStoreStorage implements \OCP\Files\IHomeStorage { @@ -34,7 +34,7 @@ class HomeObjectStoreStorage extends ObjectStoreStorage implements \OCP\Files\IH * @param array $params */ public function __construct($params) { - if (! isset($params['user']) || ! $params['user'] instanceof User) { + if (! isset($params['user']) || ! $params['user'] instanceof IUser) { throw new \Exception('missing user object in parameters'); } $this->user = $params['user']; diff --git a/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php b/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php new file mode 100644 index 0000000000000..5fe1a3c447dfc --- /dev/null +++ b/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php @@ -0,0 +1,173 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\Files\ObjectStore; + +use OCP\Files\ObjectStore\IObjectStore; +use OCP\IConfig; +use OCP\IUser; +use Psr\Log\LoggerInterface; + +class PrimaryObjectStoreConfig { + private IConfig $config; + private LoggerInterface $logger; + + public function __construct(IConfig $config, LoggerInterface $logger) { + $this->config = $config; + $this->logger = $logger; + } + + public function getObjectStoreForRoot(): ?IObjectStore { + $config = $this->getObjectStoreConfigForRoot(); + if (!$config) { + return null; + } + + if ($config['multibucket']) { + if (!isset($config['arguments']['bucket'])) { + $config['arguments']['bucket'] = ''; + } + + // put the root FS always in first bucket for multibucket configuration + $config['arguments']['bucket'] .= '0'; + } + + return new $config['class']($config['arguments']); + } + + public function getObjectStoreForUser(IUser $user): ?IObjectStore { + $config = $this->getObjectStoreConfigForUser($user); + if (!$config) { + return null; + } + + if ($config['arguments']['multibucket']) { + $config['arguments']['bucket'] = $this->getBucketForUser($user, $config); + } + + // instantiate object store implementation + return new $config['class']($config['arguments']); + } + + public function getObjectStoreArgumentsForRoot(): array { + $config = $this->getObjectStoreConfigForRoot(); + if ($config === null) { + return []; + } + return $config['arguments'] ?? []; + } + + public function getObjectStoreArgumentsForUser(IUser $user): array { + $config = $this->getObjectStoreConfigForUser($user); + if ($config === null) { + return []; + } + return $config['arguments'] ?? []; + } + + private function getObjectStoreConfigForRoot(): ?array { + $configs = $this->getObjectStoreConfig(); + + return $configs['root'] ?? $configs['default']; + } + + private function getObjectStoreConfigForUser(IUser $user): ?array { + $configs = $this->getObjectStoreConfig(); + $store = $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'objectstore', null); + + if ($store) { + return $configs[$store]; + } else { + return $configs['default']; + } + } + + private function getObjectStoreConfig(): ?array { + $objectStore = $this->config->getSystemValue('objectstore', null); + $objectStoreMultiBucket = $this->config->getSystemValue('objectstore_multibucket', null); + + // new-style multibucket config uses the same 'objectstore' key but sets `'multibucket' => true`, transparently upgrade older style config + if ($objectStoreMultiBucket) { + $objectStoreMultiBucket['multibucket'] = true; + $objectStore = [ + 'default' => $objectStoreMultiBucket, + ]; + } + if ($objectStore === null) { + return ['default' => null]; + } + + if (!isset($objectStore['default'])) { + $objectStore = [ + 'default' => $objectStore, + ]; + } + + foreach ($objectStore as &$config) { + if (!isset($config['multibucket'])) { + $config['multibucket'] = false; + } + + $this->validateObjectStoreConfig($config); + } + + return $objectStore; + } + + private function validateObjectStoreConfig(array &$config) { + if (empty($config['class'])) { + $this->logger->error('No class given for objectstore', ['app' => 'files']); + } + if (!isset($config['arguments'])) { + $config['arguments'] = []; + } + + // instantiate object store implementation + $name = $config['class']; + if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) { + $segments = explode('\\', $name); + \OC_App::loadApp(strtolower($segments[1])); + } + } + + private function getBucketForUser(IUser $user, array $config): string { + $bucket = $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'bucket', null); + + if ($bucket === null) { + /* + * Use any provided bucket argument as prefix + * and add the mapping from username => bucket + */ + if (!isset($config['arguments']['bucket'])) { + $config['arguments']['bucket'] = ''; + } + $mapper = new Mapper($user, $this->config); + $numBuckets = isset($config['arguments']['num_buckets']) ? $config['arguments']['num_buckets'] : 64; + $bucket = $config['arguments']['bucket'] . $mapper->getBucket($numBuckets); + + $this->config->setUserValue($user->getUID(), 'homeobjectstore', 'bucket', $bucket); + } + + return $bucket; + } +} diff --git a/lib/private/Server.php b/lib/private/Server.php index 07e90843a9803..9e90ac41d6589 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -98,6 +98,7 @@ use OC\Files\Node\HookConnector; use OC\Files\Node\LazyRoot; use OC\Files\Node\Root; +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; use OC\Files\SetupManager; use OC\Files\Storage\StorageFactory; use OC\Files\Template\TemplateManager; @@ -969,10 +970,11 @@ public function __construct($webRoot, \OC\Config $config) { $config = $c->get(\OCP\IConfig::class); $logger = $c->get(LoggerInterface::class); + $objectStoreConfig = new PrimaryObjectStoreConfig($config, $c->get(LoggerInterface::class)); $manager->registerProvider(new CacheMountProvider($config)); $manager->registerHomeProvider(new LocalHomeMountProvider()); - $manager->registerHomeProvider(new ObjectHomeMountProvider($config)); - $manager->registerRootProvider(new RootMountProvider($config, $c->get(LoggerInterface::class))); + $manager->registerHomeProvider(new ObjectHomeMountProvider($objectStoreConfig)); + $manager->registerRootProvider(new RootMountProvider($objectStoreConfig, $config)); $manager->registerRootProvider(new ObjectStorePreviewCacheMountProvider($logger, $config)); return $manager; diff --git a/tests/lib/Files/Mount/ObjectHomeMountProviderTest.php b/tests/lib/Files/Mount/ObjectHomeMountProviderTest.php index 7ce8714012220..2d13cb59b94bc 100644 --- a/tests/lib/Files/Mount/ObjectHomeMountProviderTest.php +++ b/tests/lib/Files/Mount/ObjectHomeMountProviderTest.php @@ -3,9 +3,12 @@ namespace Test\Files\Mount; use OC\Files\Mount\ObjectHomeMountProvider; +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; +use OCP\Files\ObjectStore\IObjectStore; use OCP\Files\Storage\IStorageFactory; use OCP\IConfig; use OCP\IUser; +use Psr\Log\LoggerInterface; class ObjectHomeMountProviderTest extends \Test\TestCase { @@ -28,45 +31,53 @@ protected function setUp(): void { $this->user = $this->createMock(IUser::class); $this->loader = $this->createMock(IStorageFactory::class); - $this->provider = new ObjectHomeMountProvider($this->config); + $objectStoreConfig = new PrimaryObjectStoreConfig($this->config, $this->createMock(LoggerInterface::class)); + $this->provider = new ObjectHomeMountProvider($objectStoreConfig); } public function testSingleBucket() { - $this->config->expects($this->once()) - ->method('getSystemValue') - ->with($this->equalTo('objectstore'), '') - ->willReturn([ - 'class' => 'Test\Files\Mount\FakeObjectStore', - ]); - - $this->user->expects($this->never())->method($this->anything()); - $this->loader->expects($this->never())->method($this->anything()); + $this->config->method('getSystemValue') + ->willReturnCallback(function($key, $default) { + if ($key === 'objectstore') { + return [ + 'class' => 'Test\Files\Mount\FakeObjectStore', + 'arguments' => [ + 'foo' => 'bar' + ], + ]; + } else { + return $default; + } + }); - $config = $this->invokePrivate($this->provider, 'getSingleBucketObjectStoreConfig', [$this->user, $this->loader]); + $mount = $this->provider->getHomeMountForUser($this->user, $this->loader); + $arguments = $this->invokePrivate($mount, 'arguments'); - $this->assertArrayHasKey('class', $config); - $this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore'); - $this->assertArrayHasKey('arguments', $config); - $this->assertArrayHasKey('user', $config['arguments']); - $this->assertSame($this->user, $config['arguments']['user']); - $this->assertArrayHasKey('objectstore', $config['arguments']); - $this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']); + $objectStore = $arguments['objectstore']; + $this->assertInstanceOf(FakeObjectStore::class, $objectStore); + $this->assertEquals(['foo' => 'bar'], $objectStore->getArguments()); } public function testMultiBucket() { - $this->config->expects($this->exactly(2)) - ->method('getSystemValue') - ->with($this->equalTo('objectstore_multibucket'), '') - ->willReturn([ - 'class' => 'Test\Files\Mount\FakeObjectStore', - ]); + $this->config->method('getSystemValue') + ->willReturnCallback(function($key, $default) { + if ($key === 'objectstore_multibucket') { + return [ + 'class' => 'Test\Files\Mount\FakeObjectStore', + 'arguments' => [ + 'foo' => 'bar' + ], + ]; + } else { + return $default; + } + }); $this->user->method('getUID') ->willReturn('uid'); $this->loader->expects($this->never())->method($this->anything()); - $this->config->expects($this->once()) - ->method('getUserValue') + $this->config->method('getUserValue') ->with( $this->equalTo('uid'), $this->equalTo('homeobjectstore'), @@ -84,29 +95,29 @@ public function testMultiBucket() { $this->equalTo(null) ); - $config = $this->invokePrivate($this->provider, 'getMultiBucketObjectStoreConfig', [$this->user, $this->loader]); + $mount = $this->provider->getHomeMountForUser($this->user, $this->loader); + $arguments = $this->invokePrivate($mount, 'arguments'); - $this->assertArrayHasKey('class', $config); - $this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore'); - $this->assertArrayHasKey('arguments', $config); - $this->assertArrayHasKey('user', $config['arguments']); - $this->assertSame($this->user, $config['arguments']['user']); - $this->assertArrayHasKey('objectstore', $config['arguments']); - $this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']); - $this->assertArrayHasKey('bucket', $config['arguments']); - $this->assertEquals('49', $config['arguments']['bucket']); + $objectStore = $arguments['objectstore']; + $this->assertInstanceOf(FakeObjectStore::class, $objectStore); + $this->assertEquals(['foo' => 'bar', 'bucket' => 49], $objectStore->getArguments()); } public function testMultiBucketWithPrefix() { - $this->config->expects($this->exactly(2)) - ->method('getSystemValue') - ->with('objectstore_multibucket') - ->willReturn([ - 'class' => 'Test\Files\Mount\FakeObjectStore', - 'arguments' => [ - 'bucket' => 'myBucketPrefix', - ], - ]); + $this->config->method('getSystemValue') + ->willReturnCallback(function($key, $default) { + if ($key === 'objectstore_multibucket') { + return [ + 'class' => 'Test\Files\Mount\FakeObjectStore', + 'arguments' => [ + 'foo' => 'bar', + 'bucket' => 'myBucketPrefix', + ], + ]; + } else { + return $default; + } + }); $this->user->method('getUID') ->willReturn('uid'); @@ -131,29 +142,29 @@ public function testMultiBucketWithPrefix() { $this->equalTo(null) ); - $config = $this->invokePrivate($this->provider, 'getMultiBucketObjectStoreConfig', [$this->user, $this->loader]); + $mount = $this->provider->getHomeMountForUser($this->user, $this->loader); + $arguments = $this->invokePrivate($mount, 'arguments'); - $this->assertArrayHasKey('class', $config); - $this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore'); - $this->assertArrayHasKey('arguments', $config); - $this->assertArrayHasKey('user', $config['arguments']); - $this->assertSame($this->user, $config['arguments']['user']); - $this->assertArrayHasKey('objectstore', $config['arguments']); - $this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']); - $this->assertArrayHasKey('bucket', $config['arguments']); - $this->assertEquals('myBucketPrefix49', $config['arguments']['bucket']); + $objectStore = $arguments['objectstore']; + $this->assertInstanceOf(FakeObjectStore::class, $objectStore); + $this->assertEquals(['foo' => 'bar', 'bucket' => 'myBucketPrefix49'], $objectStore->getArguments()); } public function testMultiBucketBucketAlreadySet() { - $this->config->expects($this->once()) - ->method('getSystemValue') - ->with('objectstore_multibucket') - ->willReturn([ - 'class' => 'Test\Files\Mount\FakeObjectStore', - 'arguments' => [ - 'bucket' => 'myBucketPrefix', - ], - ]); + $this->config->method('getSystemValue') + ->willReturnCallback(function($key, $default) { + if ($key === 'objectstore_multibucket') { + return [ + 'class' => 'Test\Files\Mount\FakeObjectStore', + 'arguments' => [ + 'foo' => 'bar', + 'bucket' => 'myBucketPrefix', + ], + ]; + } else { + return $default; + } + }); $this->user->method('getUID') ->willReturn('uid'); @@ -171,26 +182,29 @@ public function testMultiBucketBucketAlreadySet() { $this->config->expects($this->never()) ->method('setUserValue'); - $config = $this->invokePrivate($this->provider, 'getMultiBucketObjectStoreConfig', [$this->user, $this->loader]); + $mount = $this->provider->getHomeMountForUser($this->user, $this->loader); + $arguments = $this->invokePrivate($mount, 'arguments'); - $this->assertArrayHasKey('class', $config); - $this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore'); - $this->assertArrayHasKey('arguments', $config); - $this->assertArrayHasKey('user', $config['arguments']); - $this->assertSame($this->user, $config['arguments']['user']); - $this->assertArrayHasKey('objectstore', $config['arguments']); - $this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']); - $this->assertArrayHasKey('bucket', $config['arguments']); - $this->assertEquals('awesomeBucket1', $config['arguments']['bucket']); + $objectStore = $arguments['objectstore']; + $this->assertInstanceOf(FakeObjectStore::class, $objectStore); + $this->assertEquals(['foo' => 'bar', 'bucket' => 'awesomeBucket1'], $objectStore->getArguments()); } public function testMultiBucketConfigFirst() { - $this->config->expects($this->exactly(2)) - ->method('getSystemValue') - ->with('objectstore_multibucket') - ->willReturn([ - 'class' => 'Test\Files\Mount\FakeObjectStore', - ]); + $this->config->method('getSystemValue') + ->willReturnCallback(function($key, $default) { + if ($key === 'objectstore_multibucket') { + return [ + 'class' => 'Test\Files\Mount\FakeObjectStore', + 'arguments' => [ + 'foo' => 'bar', + 'bucket' => 'myBucketPrefix', + ], + ]; + } else { + return $default; + } + }); $this->user->method('getUID') ->willReturn('uid'); @@ -201,17 +215,20 @@ public function testMultiBucketConfigFirst() { } public function testMultiBucketConfigFirstFallBackSingle() { - $this->config->expects($this->exactly(2)) - ->method('getSystemValue') - ->withConsecutive( - [$this->equalTo('objectstore_multibucket')], - [$this->equalTo('objectstore')], - )->willReturnOnConsecutiveCalls( - '', - [ - 'class' => 'Test\Files\Mount\FakeObjectStore', - ], - ); + $this->config->method('getSystemValue') + ->willReturnCallback(function($key, $default) { + if ($key === 'objectstore') { + return [ + 'class' => 'Test\Files\Mount\FakeObjectStore', + 'arguments' => [ + 'foo' => 'bar', + 'bucket' => 'myBucketPrefix', + ], + ]; + } else { + return $default; + } + }); $this->user->method('getUID') ->willReturn('uid'); @@ -222,16 +239,17 @@ public function testMultiBucketConfigFirstFallBackSingle() { } public function testNoObjectStore() { - $this->config->expects($this->exactly(2)) - ->method('getSystemValue') - ->willReturn(''); + $this->config->method('getSystemValue') + ->willReturnCallback(function($key, $default) { + return $default; + }); $mount = $this->provider->getHomeMountForUser($this->user, $this->loader); $this->assertNull($mount); } } -class FakeObjectStore { +class FakeObjectStore implements IObjectStore { private $arguments; public function __construct(array $arguments) { @@ -241,4 +259,22 @@ public function __construct(array $arguments) { public function getArguments() { return $this->arguments; } + + public function getStorageId() { + } + + public function readObject($urn) { + } + + public function writeObject($urn, $stream, string $mimetype = null) { + } + + public function deleteObject($urn) { + } + + public function objectExists($urn) { + } + + public function copyObject($from, $to) { + } } diff --git a/tests/lib/Files/Mount/RootMountProviderTest.php b/tests/lib/Files/Mount/RootMountProviderTest.php index e5eaabf93bee4..f6379461ddbc2 100644 --- a/tests/lib/Files/Mount/RootMountProviderTest.php +++ b/tests/lib/Files/Mount/RootMountProviderTest.php @@ -25,6 +25,7 @@ use OC\Files\Mount\RootMountProvider; use OC\Files\ObjectStore\ObjectStoreStorage; +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; use OC\Files\ObjectStore\S3; use OC\Files\Storage\LocalRootStorage; use OC\Files\Storage\StorageFactory; @@ -55,8 +56,8 @@ private function getConfig(array $systemConfig): IConfig { private function getProvider(array $systemConfig): RootMountProvider { $config = $this->getConfig($systemConfig); - $provider = new RootMountProvider($config, $this->createMock(LoggerInterface::class)); - return $provider; + $objectStoreConfig = new PrimaryObjectStoreConfig($config, $this->createMock(LoggerInterface::class)); + return new RootMountProvider($objectStoreConfig, $config); } public function testLocal() { diff --git a/tests/lib/TestCase.php b/tests/lib/TestCase.php index 256fb95a85be1..b637ab844a3cd 100644 --- a/tests/lib/TestCase.php +++ b/tests/lib/TestCase.php @@ -30,6 +30,7 @@ use OC\Files\Mount\CacheMountProvider; use OC\Files\Mount\LocalHomeMountProvider; use OC\Files\Mount\RootMountProvider; +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; use OC\Files\SetupManager; use OC\Template\Base; use OCP\Command\IBus; @@ -295,7 +296,8 @@ public static function tearDownAfterClass(): void { $config = \OC::$server->get(IConfig::class); $mountProviderCollection->registerProvider(new CacheMountProvider($config)); $mountProviderCollection->registerHomeProvider(new LocalHomeMountProvider()); - $mountProviderCollection->registerRootProvider(new RootMountProvider($config, \OC::$server->get(LoggerInterface::class))); + $objectStoreConfig = new PrimaryObjectStoreConfig($config, \OC::$server->get(LoggerInterface::class)); + $mountProviderCollection->registerRootProvider(new RootMountProvider($objectStoreConfig, $config)); $setupManager->setupRoot();