mirror of
https://github.com/nextcloud/server.git
synced 2026-06-08 16:26:59 -04:00
Merge pull request #52784 from nextcloud/backport/52681/stable30
[stable30] feat: add command to check files_external dependencies
This commit is contained in:
commit
cc56c3b603
10 changed files with 134 additions and 20 deletions
|
|
@ -53,6 +53,7 @@ External storage can be configured using the GUI or at the command line. This se
|
|||
<command>OCA\Files_External\Command\Verify</command>
|
||||
<command>OCA\Files_External\Command\Notify</command>
|
||||
<command>OCA\Files_External\Command\Scan</command>
|
||||
<command>OCA\Files_External\Command\Dependencies</command>
|
||||
</commands>
|
||||
|
||||
<settings>
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ return array(
|
|||
'OCA\\Files_External\\Command\\Config' => $baseDir . '/../lib/Command/Config.php',
|
||||
'OCA\\Files_External\\Command\\Create' => $baseDir . '/../lib/Command/Create.php',
|
||||
'OCA\\Files_External\\Command\\Delete' => $baseDir . '/../lib/Command/Delete.php',
|
||||
'OCA\\Files_External\\Command\\Dependencies' => $baseDir . '/../lib/Command/Dependencies.php',
|
||||
'OCA\\Files_External\\Command\\Export' => $baseDir . '/../lib/Command/Export.php',
|
||||
'OCA\\Files_External\\Command\\Import' => $baseDir . '/../lib/Command/Import.php',
|
||||
'OCA\\Files_External\\Command\\ListCommand' => $baseDir . '/../lib/Command/ListCommand.php',
|
||||
|
|
@ -96,6 +97,7 @@ return array(
|
|||
'OCA\\Files_External\\Lib\\Storage\\SMB' => $baseDir . '/../lib/Lib/Storage/SMB.php',
|
||||
'OCA\\Files_External\\Lib\\Storage\\StreamWrapper' => $baseDir . '/../lib/Lib/Storage/StreamWrapper.php',
|
||||
'OCA\\Files_External\\Lib\\Storage\\Swift' => $baseDir . '/../lib/Lib/Storage/Swift.php',
|
||||
'OCA\\Files_External\\Lib\\Storage\\SystemBridge' => $baseDir . '/../lib/Lib/Storage/SystemBridge.php',
|
||||
'OCA\\Files_External\\Lib\\VisibilityTrait' => $baseDir . '/../lib/Lib/VisibilityTrait.php',
|
||||
'OCA\\Files_External\\Listener\\GroupDeletedListener' => $baseDir . '/../lib/Listener/GroupDeletedListener.php',
|
||||
'OCA\\Files_External\\Listener\\LoadAdditionalListener' => $baseDir . '/../lib/Listener/LoadAdditionalListener.php',
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class ComposerStaticInitFiles_External
|
|||
'OCA\\Files_External\\Command\\Config' => __DIR__ . '/..' . '/../lib/Command/Config.php',
|
||||
'OCA\\Files_External\\Command\\Create' => __DIR__ . '/..' . '/../lib/Command/Create.php',
|
||||
'OCA\\Files_External\\Command\\Delete' => __DIR__ . '/..' . '/../lib/Command/Delete.php',
|
||||
'OCA\\Files_External\\Command\\Dependencies' => __DIR__ . '/..' . '/../lib/Command/Dependencies.php',
|
||||
'OCA\\Files_External\\Command\\Export' => __DIR__ . '/..' . '/../lib/Command/Export.php',
|
||||
'OCA\\Files_External\\Command\\Import' => __DIR__ . '/..' . '/../lib/Command/Import.php',
|
||||
'OCA\\Files_External\\Command\\ListCommand' => __DIR__ . '/..' . '/../lib/Command/ListCommand.php',
|
||||
|
|
@ -111,6 +112,7 @@ class ComposerStaticInitFiles_External
|
|||
'OCA\\Files_External\\Lib\\Storage\\SMB' => __DIR__ . '/..' . '/../lib/Lib/Storage/SMB.php',
|
||||
'OCA\\Files_External\\Lib\\Storage\\StreamWrapper' => __DIR__ . '/..' . '/../lib/Lib/Storage/StreamWrapper.php',
|
||||
'OCA\\Files_External\\Lib\\Storage\\Swift' => __DIR__ . '/..' . '/../lib/Lib/Storage/Swift.php',
|
||||
'OCA\\Files_External\\Lib\\Storage\\SystemBridge' => __DIR__ . '/..' . '/../lib/Lib/Storage/SystemBridge.php',
|
||||
'OCA\\Files_External\\Lib\\VisibilityTrait' => __DIR__ . '/..' . '/../lib/Lib/VisibilityTrait.php',
|
||||
'OCA\\Files_External\\Listener\\GroupDeletedListener' => __DIR__ . '/..' . '/../lib/Listener/GroupDeletedListener.php',
|
||||
'OCA\\Files_External\\Listener\\LoadAdditionalListener' => __DIR__ . '/..' . '/../lib/Listener/LoadAdditionalListener.php',
|
||||
|
|
|
|||
57
apps/files_external/lib/Command/Dependencies.php
Normal file
57
apps/files_external/lib/Command/Dependencies.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?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;
|
||||
}
|
||||
}
|
||||
|
|
@ -11,19 +11,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')
|
||||
|
|
@ -123,4 +124,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')];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,18 +11,16 @@ namespace OCA\Files_External\Lib;
|
|||
* External storage backend dependency
|
||||
*/
|
||||
class MissingDependency {
|
||||
|
||||
/** @var string */
|
||||
private $dependency;
|
||||
|
||||
/** @var string|null Custom message */
|
||||
private $message = null;
|
||||
private ?string $message = null;
|
||||
private bool $optional = false;
|
||||
|
||||
/**
|
||||
* @param string $dependency
|
||||
*/
|
||||
public function __construct($dependency) {
|
||||
$this->dependency = $dependency;
|
||||
public function __construct(
|
||||
private string $dependency,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getDependency(): string {
|
||||
|
|
@ -41,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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
namespace OCA\Files_External\Lib\Storage;
|
||||
|
||||
use Icewind\SMB\ACL;
|
||||
|
|
@ -22,7 +23,7 @@ use Icewind\SMB\IFileInfo;
|
|||
use Icewind\SMB\Native\NativeServer;
|
||||
use Icewind\SMB\Options;
|
||||
use Icewind\SMB\ServerFactory;
|
||||
use Icewind\SMB\System;
|
||||
use Icewind\SMB\Wrapped\Server;
|
||||
use Icewind\Streams\CallbackWrapper;
|
||||
use Icewind\Streams\IteratorDirectory;
|
||||
use OC\Files\Filesystem;
|
||||
|
|
@ -93,7 +94,7 @@ class SMB extends Common implements INotifyStorage {
|
|||
}
|
||||
$this->logger = $params['logger'];
|
||||
} else {
|
||||
$this->logger = \OC::$server->get(LoggerInterface::class);
|
||||
$this->logger = \OCP\Server::get(LoggerInterface::class);
|
||||
}
|
||||
|
||||
$options = new Options();
|
||||
|
|
@ -103,7 +104,8 @@ class SMB extends Common implements INotifyStorage {
|
|||
$options->setTimeout($timeout);
|
||||
}
|
||||
}
|
||||
$serverFactory = new ServerFactory($options);
|
||||
$system = \OCP\Server::get(SystemBridge::class);
|
||||
$serverFactory = new ServerFactory($options, $system);
|
||||
$this->server = $serverFactory->createServer($params['host'], $auth);
|
||||
$this->share = $this->server->getShare(trim($params['share'], '/'));
|
||||
|
||||
|
|
@ -721,11 +723,9 @@ class SMB extends Common implements INotifyStorage {
|
|||
/**
|
||||
* check if smbclient is installed
|
||||
*/
|
||||
public static function checkDependencies() {
|
||||
return (
|
||||
(bool) \OC_Helper::findBinaryPath('smbclient')
|
||||
|| NativeServer::available(new System())
|
||||
) ? true : ['smbclient'];
|
||||
public static function checkDependencies(): array|bool {
|
||||
$system = \OCP\Server::get(SystemBridge::class);
|
||||
return Server::available($system) || NativeServer::available($system) ?: ['smbclient'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
27
apps/files_external/lib/Lib/Storage/SystemBridge.php
Normal file
27
apps/files_external/lib/Lib/Storage/SystemBridge.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Robin Appelman <robin@icewind.nl>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Files_External\Lib\Storage;
|
||||
|
||||
use Icewind\SMB\System;
|
||||
use OCP\IBinaryFinder;
|
||||
|
||||
/**
|
||||
* Bridge the NC and SMB binary finding logic
|
||||
*/
|
||||
class SystemBridge extends System {
|
||||
public function __construct(
|
||||
private IBinaryFinder $binaryFinder,
|
||||
) {
|
||||
}
|
||||
|
||||
protected function getBinaryPath(string $binary): ?string {
|
||||
$path = $this->binaryFinder->findBinaryPath($binary);
|
||||
return $path !== false ? $path : null;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ 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;
|
||||
|
|
@ -199,7 +200,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;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace OCP;
|
|||
/**
|
||||
* Service that find the binary path for a program.
|
||||
*
|
||||
* This interface should be injected via depency injection and must
|
||||
* This interface should be injected via dependency injection and must
|
||||
* not be implemented in applications.
|
||||
*
|
||||
* @since 25.0.0
|
||||
|
|
|
|||
Loading…
Reference in a new issue