diff options
Diffstat (limited to 'apps/files_external/lib')
18 files changed, 213 insertions, 53 deletions
diff --git a/apps/files_external/lib/AppInfo/Application.php b/apps/files_external/lib/AppInfo/Application.php index 761fc97b7aa..5dae81d558c 100644 --- a/apps/files_external/lib/AppInfo/Application.php +++ b/apps/files_external/lib/AppInfo/Application.php @@ -9,6 +9,7 @@ namespace OCA\Files_External\AppInfo; use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCA\Files_External\Config\ConfigAdapter; use OCA\Files_External\Config\UserPlaceholderHandler; +use OCA\Files_External\ConfigLexicon; use OCA\Files_External\Lib\Auth\AmazonS3\AccessKey; use OCA\Files_External\Lib\Auth\Builtin; use OCA\Files_External\Lib\Auth\NullMechanism; @@ -73,6 +74,7 @@ class Application extends App implements IBackendProvider, IAuthMechanismProvide $context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class); $context->registerEventListener(GroupDeletedEvent::class, GroupDeletedListener::class); $context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalListener::class); + $context->registerConfigLexicon(ConfigLexicon::class); } public function boot(IBootContext $context): void { diff --git a/apps/files_external/lib/Command/Backends.php b/apps/files_external/lib/Command/Backends.php index c2d844dc781..399bdadcacf 100644 --- a/apps/files_external/lib/Command/Backends.php +++ b/apps/files_external/lib/Command/Backends.php @@ -94,7 +94,7 @@ class Backends extends Base { */ private function formatConfiguration(array $parameters): array { $configuration = array_filter($parameters, function (DefinitionParameter $parameter) { - return $parameter->getType() !== DefinitionParameter::VALUE_HIDDEN; + return $parameter->isFlagSet(DefinitionParameter::FLAG_HIDDEN); }); return array_map(function (DefinitionParameter $parameter) { return $parameter->getTypeName(); diff --git a/apps/files_external/lib/Command/Dependencies.php b/apps/files_external/lib/Command/Dependencies.php new file mode 100644 index 00000000000..1bb57778129 --- /dev/null +++ b/apps/files_external/lib/Command/Dependencies.php @@ -0,0 +1,56 @@ +<?php +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Command; + +use OC\Core\Command\Base; +use OCA\Files_External\Service\BackendService; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Dependencies extends Base { + public function __construct( + private readonly BackendService $backendService, + ) { + parent::__construct(); + } + + protected function configure(): void { + $this + ->setName('files_external:dependencies') + ->setDescription('Show information about the backend dependencies'); + parent::configure(); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + $storageBackends = $this->backendService->getBackends(); + + $anyMissing = false; + + foreach ($storageBackends as $backend) { + if ($backend->getDeprecateTo() !== null) { + continue; + } + $missingDependencies = $backend->checkDependencies(); + if ($missingDependencies) { + $anyMissing = true; + $output->writeln($backend->getText() . ':'); + foreach ($missingDependencies as $missingDependency) { + if ($missingDependency->getMessage()) { + $output->writeln(" - <comment>{$missingDependency->getDependency()}</comment>: {$missingDependency->getMessage()}"); + } else { + $output->writeln(" - <comment>{$missingDependency->getDependency()}</comment>"); + } + } + } + } + + if (!$anyMissing) { + $output->writeln('<info>All dependencies are met</info>'); + } + + return self::SUCCESS; + } +} diff --git a/apps/files_external/lib/Command/Scan.php b/apps/files_external/lib/Command/Scan.php index bd54415df55..75d98878baa 100644 --- a/apps/files_external/lib/Command/Scan.php +++ b/apps/files_external/lib/Command/Scan.php @@ -11,6 +11,7 @@ namespace OCA\Files_External\Command; use OC\Files\Cache\Scanner; use OCA\Files_External\Service\GlobalStoragesService; use OCP\IUserManager; +use OCP\Lock\LockedException; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -53,6 +54,11 @@ class Scan extends StorageAuthBase { InputOption::VALUE_OPTIONAL, 'The path in the storage to scan', '' + )->addOption( + 'unscanned', + '', + InputOption::VALUE_NONE, + 'only scan files which are marked as not fully scanned' ); parent::configure(); } @@ -82,7 +88,27 @@ class Scan extends StorageAuthBase { $this->abortIfInterrupted(); }); - $scanner->scan($path); + try { + if ($input->getOption('unscanned')) { + if ($path !== '') { + $output->writeln('<error>--unscanned is mutually exclusive with --path</error>'); + return 1; + } + $scanner->backgroundScan(); + } else { + $scanner->scan($path); + } + } catch (LockedException $e) { + if (is_string($e->getReadablePath()) && str_starts_with($e->getReadablePath(), 'scanner::')) { + if ($e->getReadablePath() === 'scanner::') { + $output->writeln('<error>Another process is already scanning this storage</error>'); + } else { + $output->writeln('<error>Another process is already scanning \'' . substr($e->getReadablePath(), strlen('scanner::')) . '\' in this storage</error>'); + } + } else { + throw $e; + } + } $this->presentStats($output); diff --git a/apps/files_external/lib/ConfigLexicon.php b/apps/files_external/lib/ConfigLexicon.php new file mode 100644 index 00000000000..e162efc92cf --- /dev/null +++ b/apps/files_external/lib/ConfigLexicon.php @@ -0,0 +1,41 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\Files_External; + +use NCU\Config\Lexicon\ConfigLexiconEntry; +use NCU\Config\Lexicon\ConfigLexiconStrictness; +use NCU\Config\Lexicon\IConfigLexicon; +use NCU\Config\ValueType; + +/** + * Config Lexicon for files_sharing. + * + * Please Add & Manage your Config Keys in that file and keep the Lexicon up to date! + * + * {@see IConfigLexicon} + */ +class ConfigLexicon implements IConfigLexicon { + public const ALLOW_USER_MOUNTING = 'allow_user_mounting'; + public const USER_MOUNTING_BACKENDS = 'user_mounting_backends'; + + public function getStrictness(): ConfigLexiconStrictness { + return ConfigLexiconStrictness::NOTICE; + } + + public function getAppConfigs(): array { + return [ + new ConfigLexiconEntry(self::ALLOW_USER_MOUNTING, ValueType::BOOL, false, 'allow users to mount their own external filesystems', true), + new ConfigLexiconEntry(self::USER_MOUNTING_BACKENDS, ValueType::STRING, '', 'list of mounting backends available for users', true), + ]; + } + + public function getUserConfigs(): array { + return []; + } +} diff --git a/apps/files_external/lib/Lib/Auth/OAuth1/OAuth1.php b/apps/files_external/lib/Lib/Auth/OAuth1/OAuth1.php index b215201b4f4..688e04c4210 100644 --- a/apps/files_external/lib/Lib/Auth/OAuth1/OAuth1.php +++ b/apps/files_external/lib/Lib/Auth/OAuth1/OAuth1.php @@ -21,14 +21,17 @@ class OAuth1 extends AuthMechanism { ->setText($l->t('OAuth1')) ->addParameters([ (new DefinitionParameter('configured', 'configured')) - ->setType(DefinitionParameter::VALUE_HIDDEN), + ->setType(DefinitionParameter::VALUE_TEXT) + ->setFlag(DefinitionParameter::FLAG_HIDDEN), new DefinitionParameter('app_key', $l->t('App key')), (new DefinitionParameter('app_secret', $l->t('App secret'))) ->setType(DefinitionParameter::VALUE_PASSWORD), (new DefinitionParameter('token', 'token')) - ->setType(DefinitionParameter::VALUE_HIDDEN), + ->setType(DefinitionParameter::VALUE_PASSWORD) + ->setFlag(DefinitionParameter::FLAG_HIDDEN), (new DefinitionParameter('token_secret', 'token_secret')) - ->setType(DefinitionParameter::VALUE_HIDDEN), + ->setType(DefinitionParameter::VALUE_PASSWORD) + ->setFlag(DefinitionParameter::FLAG_HIDDEN), ]) ->addCustomJs('oauth1') ; diff --git a/apps/files_external/lib/Lib/Auth/OAuth2/OAuth2.php b/apps/files_external/lib/Lib/Auth/OAuth2/OAuth2.php index 6b41fef90d5..b6c1e1d9557 100644 --- a/apps/files_external/lib/Lib/Auth/OAuth2/OAuth2.php +++ b/apps/files_external/lib/Lib/Auth/OAuth2/OAuth2.php @@ -21,12 +21,14 @@ class OAuth2 extends AuthMechanism { ->setText($l->t('OAuth2')) ->addParameters([ (new DefinitionParameter('configured', 'configured')) - ->setType(DefinitionParameter::VALUE_HIDDEN), + ->setType(DefinitionParameter::VALUE_TEXT) + ->setFlag(DefinitionParameter::FLAG_HIDDEN), new DefinitionParameter('client_id', $l->t('Client ID')), (new DefinitionParameter('client_secret', $l->t('Client secret'))) ->setType(DefinitionParameter::VALUE_PASSWORD), (new DefinitionParameter('token', 'token')) - ->setType(DefinitionParameter::VALUE_HIDDEN), + ->setType(DefinitionParameter::VALUE_PASSWORD) + ->setFlag(DefinitionParameter::FLAG_HIDDEN), ]) ->addCustomJs('oauth2') ; diff --git a/apps/files_external/lib/Lib/Auth/Password/LoginCredentials.php b/apps/files_external/lib/Lib/Auth/Password/LoginCredentials.php index e3453a477d4..57df6316361 100644 --- a/apps/files_external/lib/Lib/Auth/Password/LoginCredentials.php +++ b/apps/files_external/lib/Lib/Auth/Password/LoginCredentials.php @@ -43,7 +43,9 @@ class LoginCredentials extends AuthMechanism { ->setText($l->t('Log-in credentials, save in database')) ->addParameters([ (new DefinitionParameter('password', $l->t('Password'))) - ->setType(DefinitionParameter::VALUE_PASSWORD), + ->setType(DefinitionParameter::VALUE_PASSWORD) + ->setFlag(DefinitionParameter::FLAG_HIDDEN) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), ]); $eventDispatcher->addServiceListener(UserLoggedInEvent::class, StorePasswordListener::class); diff --git a/apps/files_external/lib/Lib/Auth/Password/SessionCredentials.php b/apps/files_external/lib/Lib/Auth/Password/SessionCredentials.php index 6b7a51a8828..8af82ab228c 100644 --- a/apps/files_external/lib/Lib/Auth/Password/SessionCredentials.php +++ b/apps/files_external/lib/Lib/Auth/Password/SessionCredentials.php @@ -32,7 +32,9 @@ class SessionCredentials extends AuthMechanism { ->setText($l->t('Log-in credentials, save in session')) ->addParameters([ (new DefinitionParameter('password', $l->t('Password'))) - ->setType(DefinitionParameter::VALUE_PASSWORD), + ->setType(DefinitionParameter::VALUE_PASSWORD) + ->setFlag(DefinitionParameter::FLAG_HIDDEN) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), ]); } diff --git a/apps/files_external/lib/Lib/Auth/PublicKey/RSA.php b/apps/files_external/lib/Lib/Auth/PublicKey/RSA.php index 2371ce0a219..87072299d6d 100644 --- a/apps/files_external/lib/Lib/Auth/PublicKey/RSA.php +++ b/apps/files_external/lib/Lib/Auth/PublicKey/RSA.php @@ -31,7 +31,8 @@ class RSA extends AuthMechanism { new DefinitionParameter('user', $l->t('Login')), new DefinitionParameter('public_key', $l->t('Public key')), (new DefinitionParameter('private_key', 'private_key')) - ->setType(DefinitionParameter::VALUE_HIDDEN), + ->setType(DefinitionParameter::VALUE_PASSWORD) + ->setFlag(DefinitionParameter::FLAG_HIDDEN), ]) ->addCustomJs('public_key') ; diff --git a/apps/files_external/lib/Lib/Backend/LegacyBackend.php b/apps/files_external/lib/Lib/Backend/LegacyBackend.php index 11396913fbd..a74412e8373 100644 --- a/apps/files_external/lib/Lib/Backend/LegacyBackend.php +++ b/apps/files_external/lib/Lib/Backend/LegacyBackend.php @@ -52,10 +52,6 @@ class LegacyBackend extends Backend { $type = DefinitionParameter::VALUE_PASSWORD; $placeholder = substr($placeholder, 1); break; - case '#': - $type = DefinitionParameter::VALUE_HIDDEN; - $placeholder = substr($placeholder, 1); - break; } $this->addParameter((new DefinitionParameter($name, $placeholder)) ->setType($type) diff --git a/apps/files_external/lib/Lib/Backend/SMB.php b/apps/files_external/lib/Lib/Backend/SMB.php index c4a68fea6e1..3549f69cbe3 100644 --- a/apps/files_external/lib/Lib/Backend/SMB.php +++ b/apps/files_external/lib/Lib/Backend/SMB.php @@ -10,19 +10,20 @@ namespace OCA\Files_External\Lib\Backend; use Icewind\SMB\BasicAuth; use Icewind\SMB\KerberosApacheAuth; use Icewind\SMB\KerberosAuth; +use Icewind\SMB\Native\NativeServer; +use Icewind\SMB\Wrapped\Server; use OCA\Files_External\Lib\Auth\AuthMechanism; use OCA\Files_External\Lib\Auth\Password\Password; use OCA\Files_External\Lib\Auth\SMB\KerberosApacheAuth as KerberosApacheAuthMechanism; use OCA\Files_External\Lib\DefinitionParameter; use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException; -use OCA\Files_External\Lib\LegacyDependencyCheckPolyfill; +use OCA\Files_External\Lib\MissingDependency; +use OCA\Files_External\Lib\Storage\SystemBridge; use OCA\Files_External\Lib\StorageConfig; use OCP\IL10N; use OCP\IUser; class SMB extends Backend { - use LegacyDependencyCheckPolyfill; - public function __construct(IL10N $l, Password $legacyAuth) { $this ->setIdentifier('smb') @@ -49,8 +50,9 @@ class SMB extends Backend { ->setFlag(DefinitionParameter::FLAG_OPTIONAL) ->setTooltip($l->t("Check the ACL's of each file or folder inside a directory to filter out items where the account has no read permissions, comes with a performance penalty")), (new DefinitionParameter('timeout', $l->t('Timeout'))) - ->setType(DefinitionParameter::VALUE_HIDDEN) - ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + ->setType(DefinitionParameter::VALUE_TEXT) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL) + ->setFlag(DefinitionParameter::FLAG_HIDDEN), ]) ->addAuthScheme(AuthMechanism::SCHEME_PASSWORD) ->addAuthScheme(AuthMechanism::SCHEME_SMB) @@ -121,4 +123,20 @@ class SMB extends Backend { $storage->setBackendOption('auth', $smbAuth); } + + public function checkDependencies() { + $system = \OCP\Server::get(SystemBridge::class); + if (NativeServer::available($system)) { + return []; + } elseif (Server::available($system)) { + $missing = new MissingDependency('php-smbclient'); + $missing->setOptional(true); + $missing->setMessage('The php-smbclient library provides improved compatibility and performance for SMB storages.'); + return [$missing]; + } else { + $missing = new MissingDependency('php-smbclient'); + $missing->setMessage('Either the php-smbclient library (preferred) or the smbclient binary is required for SMB storages.'); + return [$missing, new MissingDependency('smbclient')]; + } + } } diff --git a/apps/files_external/lib/Lib/DefinitionParameter.php b/apps/files_external/lib/Lib/DefinitionParameter.php index 1e611edd1ed..3c668c6b83d 100644 --- a/apps/files_external/lib/Lib/DefinitionParameter.php +++ b/apps/files_external/lib/Lib/DefinitionParameter.php @@ -18,12 +18,12 @@ class DefinitionParameter implements \JsonSerializable { public const VALUE_TEXT = 0; public const VALUE_BOOLEAN = 1; public const VALUE_PASSWORD = 2; - public const VALUE_HIDDEN = 3; /** Flag constants */ public const FLAG_NONE = 0; public const FLAG_OPTIONAL = 1; public const FLAG_USER_PROVIDED = 2; + public const FLAG_HIDDEN = 4; /** @var string human-readable parameter tooltip */ private string $tooltip = ''; diff --git a/apps/files_external/lib/Lib/MissingDependency.php b/apps/files_external/lib/Lib/MissingDependency.php index 5c2c6880f23..da4cbb1de46 100644 --- a/apps/files_external/lib/Lib/MissingDependency.php +++ b/apps/files_external/lib/Lib/MissingDependency.php @@ -12,13 +12,14 @@ namespace OCA\Files_External\Lib; class MissingDependency { /** @var string|null Custom message */ - private $message = null; + private ?string $message = null; + private bool $optional = false; /** * @param string $dependency */ public function __construct( - private $dependency, + private readonly string $dependency, ) { } @@ -38,4 +39,12 @@ class MissingDependency { $this->message = $message; return $this; } + + public function isOptional(): bool { + return $this->optional; + } + + public function setOptional(bool $optional): void { + $this->optional = $optional; + } } diff --git a/apps/files_external/lib/Lib/Storage/SMB.php b/apps/files_external/lib/Lib/Storage/SMB.php index fc1f9b9ecd1..fe5f3adb25e 100644 --- a/apps/files_external/lib/Lib/Storage/SMB.php +++ b/apps/files_external/lib/Lib/Storage/SMB.php @@ -198,7 +198,7 @@ class SMB extends Common implements INotifyStorage { try { $acls = $file->getAcls(); } catch (Exception $e) { - $this->logger->error('Error while getting file acls', ['exception' => $e]); + $this->logger->warning('Error while getting file acls', ['exception' => $e]); return null; } foreach ($acls as $user => $acl) { @@ -426,6 +426,7 @@ class SMB extends Common implements INotifyStorage { case 'r': case 'rb': if (!$this->file_exists($path)) { + $this->logger->warning('Failed to open ' . $path . ' on ' . $this->getId() . ', file doesn\'t exist.'); return false; } return $this->share->read($fullPath); @@ -453,11 +454,13 @@ class SMB extends Common implements INotifyStorage { } if ($this->file_exists($path)) { if (!$this->isUpdatable($path)) { + $this->logger->warning('Failed to open ' . $path . ' on ' . $this->getId() . ', file not updatable.'); return false; } $tmpFile = $this->getCachedFile($path); } else { if (!$this->isCreatable(dirname($path))) { + $this->logger->warning('Failed to open ' . $path . ' on ' . $this->getId() . ', parent directory not writable.'); return false; } $tmpFile = \OCP\Server::get(ITempManager::class)->getTemporaryFile($ext); @@ -472,13 +475,16 @@ class SMB extends Common implements INotifyStorage { } return false; } catch (NotFoundException $e) { + $this->logger->warning('Failed to open ' . $path . ' on ' . $this->getId() . ', not found.', ['exception' => $e]); return false; } catch (ForbiddenException $e) { + $this->logger->warning('Failed to open ' . $path . ' on ' . $this->getId() . ', forbidden.', ['exception' => $e]); return false; } catch (OutOfSpaceException $e) { + $this->logger->warning('Failed to open ' . $path . ' on ' . $this->getId() . ', out of space.', ['exception' => $e]); throw new EntityTooLargeException('not enough available space to create file', 0, $e); } catch (ConnectException $e) { - $this->logger->error('Error while opening file', ['exception' => $e]); + $this->logger->error('Error while opening file ' . $path . ' on ' . $this->getId(), ['exception' => $e]); throw new StorageNotAvailableException($e->getMessage(), (int)$e->getCode(), $e); } } diff --git a/apps/files_external/lib/Lib/Storage/Swift.php b/apps/files_external/lib/Lib/Storage/Swift.php index a71331766d4..e80570f14ba 100644 --- a/apps/files_external/lib/Lib/Storage/Swift.php +++ b/apps/files_external/lib/Lib/Storage/Swift.php @@ -288,7 +288,6 @@ class Swift extends Common { public function stat(string $path): array|false { $path = $this->normalizePath($path); - if ($path === '.') { $path = ''; } elseif ($this->is_dir($path)) { @@ -308,22 +307,23 @@ class Swift extends Common { return false; } - $dateTime = $object->lastModified ? \DateTime::createFromFormat(\DateTime::RFC1123, $object->lastModified) : false; - $mtime = $dateTime ? $dateTime->getTimestamp() : null; - $objectMetadata = $object->getMetadata(); - if (isset($objectMetadata['timestamp'])) { - $mtime = $objectMetadata['timestamp']; + $mtime = null; + if (!empty($object->lastModified)) { + $dateTime = \DateTime::createFromFormat(\DateTime::RFC1123, $object->lastModified); + if ($dateTime !== false) { + $mtime = $dateTime->getTimestamp(); + } } - if (!empty($mtime)) { - $mtime = floor($mtime); + if (is_numeric($object->getMetadata()['timestamp'] ?? null)) { + $mtime = (float)$object->getMetadata()['timestamp']; } - $stat = []; - $stat['size'] = (int)$object->contentLength; - $stat['mtime'] = $mtime; - $stat['atime'] = time(); - return $stat; + return [ + 'size' => (int)$object->contentLength, + 'mtime' => isset($mtime) ? (int)floor($mtime) : null, + 'atime' => time(), + ]; } public function filetype(string $path) { diff --git a/apps/files_external/lib/Listener/LoadAdditionalListener.php b/apps/files_external/lib/Listener/LoadAdditionalListener.php index 66d06675291..6ba917759c3 100644 --- a/apps/files_external/lib/Listener/LoadAdditionalListener.php +++ b/apps/files_external/lib/Listener/LoadAdditionalListener.php @@ -10,10 +10,11 @@ namespace OCA\Files_External\Listener; use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCA\Files_External\AppInfo\Application; +use OCA\Files_External\ConfigLexicon; use OCP\AppFramework\Services\IInitialState; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; -use OCP\IConfig; +use OCP\IAppConfig; use OCP\Util; /** @@ -22,7 +23,7 @@ use OCP\Util; class LoadAdditionalListener implements IEventListener { public function __construct( - private IConfig $config, + private readonly IAppConfig $appConfig, private IInitialState $initialState, ) { } @@ -32,7 +33,7 @@ class LoadAdditionalListener implements IEventListener { return; } - $allowUserMounting = $this->config->getAppValue('files_external', 'allow_user_mounting', 'no') === 'yes'; + $allowUserMounting = $this->appConfig->getValueBool('files_external', ConfigLexicon::ALLOW_USER_MOUNTING); $this->initialState->provideInitialState('allowUserMounting', $allowUserMounting); Util::addInitScript(Application::APP_ID, 'init'); diff --git a/apps/files_external/lib/Service/BackendService.php b/apps/files_external/lib/Service/BackendService.php index b452b27e175..586ce5330ad 100644 --- a/apps/files_external/lib/Service/BackendService.php +++ b/apps/files_external/lib/Service/BackendService.php @@ -7,14 +7,15 @@ namespace OCA\Files_External\Service; use OCA\Files_External\Config\IConfigHandler; +use OCA\Files_External\ConfigLexicon; use OCA\Files_External\Lib\Auth\AuthMechanism; use OCA\Files_External\Lib\Backend\Backend; - use OCA\Files_External\Lib\Config\IAuthMechanismProvider; use OCA\Files_External\Lib\Config\IBackendProvider; +use OCA\Files_External\Lib\MissingDependency; use OCP\EventDispatcher\GenericEvent; use OCP\EventDispatcher\IEventDispatcher; -use OCP\IConfig; +use OCP\IAppConfig; use OCP\Server; /** @@ -56,19 +57,12 @@ class BackendService { private $configHandlers = []; - /** - * @param IConfig $config - */ public function __construct( - protected IConfig $config, + protected IAppConfig $appConfig, ) { // Load config values - if ($this->config->getAppValue('files_external', 'allow_user_mounting', 'yes') !== 'yes') { - $this->userMountingAllowed = false; - } - $this->userMountingBackends = explode(',', - $this->config->getAppValue('files_external', 'user_mounting_backends', '') - ); + $this->userMountingAllowed = $appConfig->getValueBool('files_external', ConfigLexicon::ALLOW_USER_MOUNTING); + $this->userMountingBackends = explode(',', $appConfig->getValueString('files_external', ConfigLexicon::USER_MOUNTING_BACKENDS)); // if no backend is in the list an empty string is in the array and user mounting is disabled if ($this->userMountingBackends === ['']) { @@ -194,7 +188,8 @@ class BackendService { */ public function getAvailableBackends() { return array_filter($this->getBackends(), function ($backend) { - return !$backend->checkDependencies(); + $missing = array_filter($backend->checkDependencies(), fn (MissingDependency $dependency) => !$dependency->isOptional()); + return count($missing) === 0; }); } |