-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
[stable29] [stable30] feat: move primary object store configuration to a single place #56540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
| /** | ||
| * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors | ||
| * SPDX-License-Identifier: AGPL-3.0-only | ||
| */ | ||
|
|
||
| namespace OC\Files\ObjectStore; | ||
|
|
||
| use OCP\App\IAppManager; | ||
| use OCP\Files\ObjectStore\IObjectStore; | ||
| use OCP\IConfig; | ||
| use OCP\IUser; | ||
|
|
||
| /** | ||
| * @psalm-type ObjectStoreConfig array{class: class-string<IObjectStore>, arguments: array{multibucket: bool, ...}} | ||
| */ | ||
| class PrimaryObjectStoreConfig { | ||
| public function __construct( | ||
| private readonly IConfig $config, | ||
|
Check failure on line 21 in lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php
|
||
Check failureCode scanning / Psalm ParseError Error
Syntax error, unexpected T_STRING, expecting T_VARIABLE on line 21
|
||
| private readonly IAppManager $appManager, | ||
| ) { | ||
| } | ||
|
|
||
| /** | ||
| * @param ObjectStoreConfig $config | ||
| */ | ||
| public function buildObjectStore(array $config): IObjectStore { | ||
| return new $config['class']($config['arguments']); | ||
| } | ||
|
|
||
| /** | ||
| * @return ?ObjectStoreConfig | ||
| */ | ||
| public function getObjectStoreConfigForRoot(): ?array { | ||
| $config = $this->getObjectStoreConfig(); | ||
|
|
||
| if ($config && $config['arguments']['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 $config; | ||
| } | ||
|
|
||
| /** | ||
| * @return ?ObjectStoreConfig | ||
| */ | ||
| public function getObjectStoreConfigForUser(IUser $user): ?array { | ||
| $config = $this->getObjectStoreConfig(); | ||
|
|
||
| if ($config && $config['arguments']['multibucket']) { | ||
| $config['arguments']['bucket'] = $this->getBucketForUser($user, $config); | ||
| } | ||
| return $config; | ||
| } | ||
|
|
||
| /** | ||
| * @return ?ObjectStoreConfig | ||
| */ | ||
| private function getObjectStoreConfig(): ?array { | ||
| $objectStore = $this->config->getSystemValue('objectstore', null); | ||
|
Check failure on line 66 in lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php
|
||
Check failureCode scanning / Psalm UndefinedThisPropertyFetch Error
Instance property OC\Files\ObjectStore\PrimaryObjectStoreConfig::$config is not defined
|
||
| $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['arguments']['multibucket'] = true; | ||
| return $this->validateObjectStoreConfig($objectStoreMultiBucket); | ||
| } elseif ($objectStore) { | ||
| return $this->validateObjectStoreConfig($objectStore); | ||
| } else { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @return ObjectStoreConfig | ||
| */ | ||
| private function validateObjectStoreConfig(array $config) { | ||
| if (!isset($config['class'])) { | ||
| throw new \Exception('No class configured for object store'); | ||
| } | ||
| if (!isset($config['arguments'])) { | ||
| $config['arguments'] = []; | ||
| } | ||
| $class = $config['class']; | ||
| $arguments = $config['arguments']; | ||
| if (!is_array($arguments)) { | ||
| throw new \Exception('Configured object store arguments are not an array'); | ||
| } | ||
| if (!isset($arguments['multibucket'])) { | ||
| $arguments['multibucket'] = false; | ||
| } | ||
| if (!is_bool($arguments['multibucket'])) { | ||
| throw new \Exception('arguments.multibucket must be a boolean in object store configuration'); | ||
| } | ||
|
|
||
| if (!is_string($class)) { | ||
| throw new \Exception('Configured class for object store is not a string'); | ||
| } | ||
|
|
||
| if (str_starts_with($class, 'OCA\\') && substr_count($class, '\\') >= 2) { | ||
| [$appId] = explode('\\', $class); | ||
| $this->appManager->loadApp(strtolower($appId)); | ||
|
Check failure on line 108 in lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php
|
||
Check failureCode scanning / Psalm UndefinedThisPropertyFetch Error
Instance property OC\Files\ObjectStore\PrimaryObjectStoreConfig::$appManager is not defined
|
||
| } | ||
|
|
||
| if (!is_a($class, IObjectStore::class, true)) { | ||
| throw new \Exception('Configured class for object store is not an object store'); | ||
| } | ||
| return [ | ||
| 'class' => $class, | ||
| 'arguments' => $arguments, | ||
| ]; | ||
| } | ||
|
|
||
| private function getBucketForUser(IUser $user, array $config): string { | ||
| $bucket = $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'bucket', null); | ||
|
Check failure on line 121 in lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php
|
||
Check failureCode scanning / Psalm UndefinedThisPropertyFetch Error
Instance property OC\Files\ObjectStore\PrimaryObjectStoreConfig::$config is not defined
|
||
|
|
||
| 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; | ||
| } | ||
| } | ||
Check failure
Code scanning / Psalm
InvalidDocblock Error