diff options
Diffstat (limited to 'apps/files_external/lib/Lib/Backend')
-rw-r--r-- | apps/files_external/lib/Lib/Backend/AmazonS3.php | 54 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/Backend.php | 145 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/DAV.php | 37 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/FTP.php | 39 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/InvalidBackend.php | 50 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/LegacyBackend.php | 83 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/Local.php | 38 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/OwnCloud.php | 34 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/SFTP.php | 34 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/SFTP_Key.php | 31 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/SMB.php | 140 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/SMB_OC.php | 57 | ||||
-rw-r--r-- | apps/files_external/lib/Lib/Backend/Swift.php | 43 |
13 files changed, 785 insertions, 0 deletions
diff --git a/apps/files_external/lib/Lib/Backend/AmazonS3.php b/apps/files_external/lib/Lib/Backend/AmazonS3.php new file mode 100644 index 00000000000..464b03b55e0 --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/AmazonS3.php @@ -0,0 +1,54 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\Auth\AmazonS3\AccessKey; +use OCA\Files_External\Lib\Auth\AuthMechanism; +use OCA\Files_External\Lib\DefinitionParameter; +use OCA\Files_External\Lib\LegacyDependencyCheckPolyfill; +use OCP\IL10N; + +class AmazonS3 extends Backend { + use LegacyDependencyCheckPolyfill; + + public function __construct(IL10N $l, AccessKey $legacyAuth) { + $this + ->setIdentifier('amazons3') + ->addIdentifierAlias('\OC\Files\Storage\AmazonS3') // legacy compat + ->setStorageClass('\OCA\Files_External\Lib\Storage\AmazonS3') + ->setText($l->t('Amazon S3')) + ->addParameters([ + new DefinitionParameter('bucket', $l->t('Bucket')), + (new DefinitionParameter('hostname', $l->t('Hostname'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('port', $l->t('Port'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('region', $l->t('Region'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('storageClass', $l->t('Storage Class'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('use_ssl', $l->t('Enable SSL'))) + ->setType(DefinitionParameter::VALUE_BOOLEAN) + ->setDefaultValue(true), + (new DefinitionParameter('use_path_style', $l->t('Enable Path Style'))) + ->setType(DefinitionParameter::VALUE_BOOLEAN), + (new DefinitionParameter('legacy_auth', $l->t('Legacy (v2) authentication'))) + ->setType(DefinitionParameter::VALUE_BOOLEAN), + (new DefinitionParameter('useMultipartCopy', $l->t('Enable multipart copy'))) + ->setType(DefinitionParameter::VALUE_BOOLEAN) + ->setDefaultValue(true), + (new DefinitionParameter('sse_c_key', $l->t('SSE-C encryption key'))) + ->setType(DefinitionParameter::VALUE_PASSWORD) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + ]) + ->addAuthScheme(AccessKey::SCHEME_AMAZONS3_ACCESSKEY) + ->addAuthScheme(AuthMechanism::SCHEME_NULL) + ->setLegacyAuthMechanism($legacyAuth) + ; + } +} diff --git a/apps/files_external/lib/Lib/Backend/Backend.php b/apps/files_external/lib/Lib/Backend/Backend.php new file mode 100644 index 00000000000..f7500ee24a4 --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/Backend.php @@ -0,0 +1,145 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\Auth\AuthMechanism; +use OCA\Files_External\Lib\DependencyTrait; +use OCA\Files_External\Lib\FrontendDefinitionTrait; +use OCA\Files_External\Lib\IdentifierTrait; +use OCA\Files_External\Lib\IFrontendDefinition; +use OCA\Files_External\Lib\IIdentifier; +use OCA\Files_External\Lib\PriorityTrait; +use OCA\Files_External\Lib\StorageConfig; +use OCA\Files_External\Lib\StorageModifierTrait; +use OCA\Files_External\Lib\VisibilityTrait; +use OCP\Files\Storage\IStorage; + +/** + * Storage backend + * + * A backend can have services injected during construction, + * such as \OCP\IDB for database operations. This allows a backend + * to perform advanced operations based on provided information. + * + * An authentication scheme defines the parameter interface, common to the + * storage implementation, the backend and the authentication mechanism. + * A storage implementation expects parameters according to the authentication + * scheme, which are provided from the authentication mechanism. + * + * This class uses the following traits: + * - VisibilityTrait + * Restrict usage to admin-only/none + * - FrontendDefinitionTrait + * Specify configuration parameters and other definitions + * - PriorityTrait + * Allow objects to prioritize over others with the same mountpoint + * - DependencyTrait + * The object requires certain dependencies to be met + * - StorageModifierTrait + * Object can affect storage mounting + */ +class Backend implements \JsonSerializable, IIdentifier, IFrontendDefinition { + use VisibilityTrait; + use FrontendDefinitionTrait; + use PriorityTrait; + use DependencyTrait; + use StorageModifierTrait; + use IdentifierTrait; + + /** @var string storage class */ + private $storageClass; + + /** @var array 'scheme' => true, supported authentication schemes */ + private $authSchemes = []; + + /** @var AuthMechanism|callable authentication mechanism fallback */ + private $legacyAuthMechanism; + + /** + * @return class-string<IStorage> + */ + public function getStorageClass() { + return $this->storageClass; + } + + /** + * @param string $class + * @return $this + */ + public function setStorageClass($class) { + $this->storageClass = $class; + return $this; + } + + /** + * @return array + */ + public function getAuthSchemes() { + if (empty($this->authSchemes)) { + return [AuthMechanism::SCHEME_NULL => true]; + } + return $this->authSchemes; + } + + /** + * @param string $scheme + * @return self + */ + public function addAuthScheme($scheme) { + $this->authSchemes[$scheme] = true; + return $this; + } + + /** + * @param array $parameters storage parameters, for dynamic mechanism selection + * @return AuthMechanism + */ + public function getLegacyAuthMechanism(array $parameters = []) { + if (is_callable($this->legacyAuthMechanism)) { + return call_user_func($this->legacyAuthMechanism, $parameters); + } + return $this->legacyAuthMechanism; + } + + public function setLegacyAuthMechanism(AuthMechanism $authMechanism): self { + $this->legacyAuthMechanism = $authMechanism; + return $this; + } + + /** + * @param callable $callback dynamic auth mechanism selection + */ + public function setLegacyAuthMechanismCallback(callable $callback): self { + $this->legacyAuthMechanism = $callback; + return $this; + } + + /** + * Serialize into JSON for client-side JS + */ + public function jsonSerialize(): array { + $data = $this->jsonSerializeDefinition(); + $data += $this->jsonSerializeIdentifier(); + + $data['backend'] = $data['name']; // legacy compat + $data['priority'] = $this->getPriority(); + $data['authSchemes'] = $this->getAuthSchemes(); + + return $data; + } + + /** + * Check if parameters are satisfied in a StorageConfig + * + * @param StorageConfig $storage + * @return bool + */ + public function validateStorage(StorageConfig $storage) { + return $this->validateStorageDefinition($storage); + } +} diff --git a/apps/files_external/lib/Lib/Backend/DAV.php b/apps/files_external/lib/Lib/Backend/DAV.php new file mode 100644 index 00000000000..dea9e7c5e77 --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/DAV.php @@ -0,0 +1,37 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\Auth\AuthMechanism; +use OCA\Files_External\Lib\Auth\Password\Password; +use OCA\Files_External\Lib\DefinitionParameter; +use OCA\Files_External\Lib\LegacyDependencyCheckPolyfill; +use OCP\IL10N; + +class DAV extends Backend { + use LegacyDependencyCheckPolyfill; + + public function __construct(IL10N $l, Password $legacyAuth) { + $this + ->setIdentifier('dav') + ->addIdentifierAlias('\OC\Files\Storage\DAV') // legacy compat + ->setStorageClass('\OC\Files\Storage\DAV') + ->setText($l->t('WebDAV')) + ->addParameters([ + new DefinitionParameter('host', $l->t('URL')), + (new DefinitionParameter('root', $l->t('Remote subfolder'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('secure', $l->t('Secure https://'))) + ->setType(DefinitionParameter::VALUE_BOOLEAN) + ->setDefaultValue(true), + ]) + ->addAuthScheme(AuthMechanism::SCHEME_PASSWORD) + ->setLegacyAuthMechanism($legacyAuth) + ; + } +} diff --git a/apps/files_external/lib/Lib/Backend/FTP.php b/apps/files_external/lib/Lib/Backend/FTP.php new file mode 100644 index 00000000000..72a8184c9b9 --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/FTP.php @@ -0,0 +1,39 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\Auth\AuthMechanism; +use OCA\Files_External\Lib\Auth\Password\Password; +use OCA\Files_External\Lib\DefinitionParameter; +use OCA\Files_External\Lib\LegacyDependencyCheckPolyfill; +use OCP\IL10N; + +class FTP extends Backend { + use LegacyDependencyCheckPolyfill; + + public function __construct(IL10N $l, Password $legacyAuth) { + $this + ->setIdentifier('ftp') + ->addIdentifierAlias('\OC\Files\Storage\FTP') // legacy compat + ->setStorageClass('\OCA\Files_External\Lib\Storage\FTP') + ->setText($l->t('FTP')) + ->addParameters([ + new DefinitionParameter('host', $l->t('Host')), + (new DefinitionParameter('port', $l->t('Port'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('root', $l->t('Remote subfolder'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('secure', $l->t('Secure ftps://'))) + ->setType(DefinitionParameter::VALUE_BOOLEAN) + ->setDefaultValue(true), + ]) + ->addAuthScheme(AuthMechanism::SCHEME_PASSWORD) + ->setLegacyAuthMechanism($legacyAuth) + ; + } +} diff --git a/apps/files_external/lib/Lib/Backend/InvalidBackend.php b/apps/files_external/lib/Lib/Backend/InvalidBackend.php new file mode 100644 index 00000000000..48912c0e49e --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/InvalidBackend.php @@ -0,0 +1,50 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud GmbH. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\StorageConfig; +use OCP\Files\StorageNotAvailableException; +use OCP\IUser; + +/** + * Invalid storage backend representing a backend + * that could not be resolved + */ +class InvalidBackend extends Backend { + + /** + * Constructs a new InvalidBackend with the id of the invalid backend + * for display purposes + * + * @param string $invalidId id of the backend that did not exist + */ + public function __construct( + private $invalidId, + ) { + $this + ->setIdentifier($this->invalidId) + ->setStorageClass('\OC\Files\Storage\FailedStorage') + ->setText('Unknown storage backend ' . $this->invalidId); + } + + /** + * Returns the invalid backend id + * + * @return string invalid backend id + */ + public function getInvalidId() { + return $this->invalidId; + } + + /** + * @return void + */ + public function manipulateStorageConfig(StorageConfig &$storage, ?IUser $user = null) { + $storage->setBackendOption('exception', new \Exception('Unknown storage backend "' . $this->invalidId . '"', StorageNotAvailableException::STATUS_ERROR)); + } +} diff --git a/apps/files_external/lib/Lib/Backend/LegacyBackend.php b/apps/files_external/lib/Lib/Backend/LegacyBackend.php new file mode 100644 index 00000000000..9c7e5b01bc3 --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/LegacyBackend.php @@ -0,0 +1,83 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\Auth\Builtin; +use OCA\Files_External\Lib\DefinitionParameter; +use OCA\Files_External\Lib\LegacyDependencyCheckPolyfill; +use OCA\Files_External\Lib\MissingDependency; + +/** + * Legacy compatibility for OCA\Files_External\MountConfig::registerBackend() + */ +class LegacyBackend extends Backend { + use LegacyDependencyCheckPolyfill { + LegacyDependencyCheckPolyfill::checkDependencies as doCheckDependencies; + } + + /** @var bool */ + protected $hasDependencies = false; + + /** + * @param string $class + * @param array $definition + * @param Builtin $authMechanism + */ + public function __construct($class, array $definition, Builtin $authMechanism) { + $this + ->setIdentifier($class) + ->setStorageClass($class) + ->setText($definition['backend']) + ->addAuthScheme(Builtin::SCHEME_BUILTIN) + ->setLegacyAuthMechanism($authMechanism) + ; + + foreach ($definition['configuration'] as $name => $placeholder) { + $flags = DefinitionParameter::FLAG_NONE; + $type = DefinitionParameter::VALUE_TEXT; + if ($placeholder[0] === '&') { + $flags = DefinitionParameter::FLAG_OPTIONAL; + $placeholder = substr($placeholder, 1); + } + switch ($placeholder[0]) { + case '!': + $type = DefinitionParameter::VALUE_BOOLEAN; + $placeholder = substr($placeholder, 1); + break; + case '*': + $type = DefinitionParameter::VALUE_PASSWORD; + $placeholder = substr($placeholder, 1); + break; + } + $this->addParameter((new DefinitionParameter($name, $placeholder)) + ->setType($type) + ->setFlags($flags) + ); + } + + if (isset($definition['priority'])) { + $this->setPriority($definition['priority']); + } + if (isset($definition['custom'])) { + $this->addCustomJs($definition['custom']); + } + if (isset($definition['has_dependencies']) && $definition['has_dependencies']) { + $this->hasDependencies = true; + } + } + + /** + * @return MissingDependency[] + */ + public function checkDependencies() { + if ($this->hasDependencies) { + return $this->doCheckDependencies(); + } + return []; + } +} diff --git a/apps/files_external/lib/Lib/Backend/Local.php b/apps/files_external/lib/Lib/Backend/Local.php new file mode 100644 index 00000000000..56940b8e83b --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/Local.php @@ -0,0 +1,38 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\Auth\AuthMechanism; +use OCA\Files_External\Lib\Auth\NullMechanism; +use OCA\Files_External\Lib\DefinitionParameter; +use OCA\Files_External\Lib\StorageConfig; +use OCA\Files_External\Service\BackendService; +use OCP\IL10N; +use OCP\IUser; + +class Local extends Backend { + public function __construct(IL10N $l, NullMechanism $legacyAuth) { + $this + ->setIdentifier('local') + ->addIdentifierAlias('\OC\Files\Storage\Local') // legacy compat + ->setStorageClass('\OC\Files\Storage\Local') + ->setText($l->t('Local')) + ->addParameters([ + new DefinitionParameter('datadir', $l->t('Location')), + ]) + ->setAllowedVisibility(BackendService::VISIBILITY_ADMIN) + ->setPriority(BackendService::PRIORITY_DEFAULT + 50) + ->addAuthScheme(AuthMechanism::SCHEME_NULL) + ->setLegacyAuthMechanism($legacyAuth) + ; + } + + public function manipulateStorageConfig(StorageConfig &$storage, ?IUser $user = null): void { + $storage->setBackendOption('isExternal', true); + } +} diff --git a/apps/files_external/lib/Lib/Backend/OwnCloud.php b/apps/files_external/lib/Lib/Backend/OwnCloud.php new file mode 100644 index 00000000000..0c0e2c6d300 --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/OwnCloud.php @@ -0,0 +1,34 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\Auth\AuthMechanism; +use OCA\Files_External\Lib\Auth\Password\Password; +use OCA\Files_External\Lib\DefinitionParameter; +use OCP\IL10N; + +class OwnCloud extends Backend { + public function __construct(IL10N $l, Password $legacyAuth) { + $this + ->setIdentifier('owncloud') + ->addIdentifierAlias('\OC\Files\Storage\OwnCloud') // legacy compat + ->setStorageClass('\OCA\Files_External\Lib\Storage\OwnCloud') + ->setText($l->t('Nextcloud')) + ->addParameters([ + new DefinitionParameter('host', $l->t('URL')), + (new DefinitionParameter('root', $l->t('Remote subfolder'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('secure', $l->t('Secure https://'))) + ->setType(DefinitionParameter::VALUE_BOOLEAN) + ->setDefaultValue(true), + ]) + ->addAuthScheme(AuthMechanism::SCHEME_PASSWORD) + ->setLegacyAuthMechanism($legacyAuth) + ; + } +} diff --git a/apps/files_external/lib/Lib/Backend/SFTP.php b/apps/files_external/lib/Lib/Backend/SFTP.php new file mode 100644 index 00000000000..0926cf7fd93 --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/SFTP.php @@ -0,0 +1,34 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\Auth\AuthMechanism; +use OCA\Files_External\Lib\Auth\Password\Password; +use OCA\Files_External\Lib\DefinitionParameter; +use OCP\IL10N; + +class SFTP extends Backend { + public function __construct(IL10N $l, Password $legacyAuth) { + $this + ->setIdentifier('sftp') + ->addIdentifierAlias('\OC\Files\Storage\SFTP') // legacy compat + ->setStorageClass('\OCA\Files_External\Lib\Storage\SFTP') + ->setText($l->t('SFTP')) + ->addParameters([ + new DefinitionParameter('host', $l->t('Host')), + (new DefinitionParameter('port', $l->t('Port'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('root', $l->t('Root'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + ]) + ->addAuthScheme(AuthMechanism::SCHEME_PASSWORD) + ->addAuthScheme(AuthMechanism::SCHEME_PUBLICKEY) + ->setLegacyAuthMechanism($legacyAuth) + ; + } +} diff --git a/apps/files_external/lib/Lib/Backend/SFTP_Key.php b/apps/files_external/lib/Lib/Backend/SFTP_Key.php new file mode 100644 index 00000000000..278fae3fba7 --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/SFTP_Key.php @@ -0,0 +1,31 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\Auth\AuthMechanism; +use OCA\Files_External\Lib\Auth\PublicKey\RSA; +use OCA\Files_External\Lib\DefinitionParameter; +use OCP\IL10N; + +class SFTP_Key extends Backend { + public function __construct(IL10N $l, RSA $legacyAuth, SFTP $sftpBackend) { + $this + ->setIdentifier('\OC\Files\Storage\SFTP_Key') + ->setStorageClass('\OCA\Files_External\Lib\Storage\SFTP') + ->setText($l->t('SFTP with secret key login')) + ->addParameters([ + new DefinitionParameter('host', $l->t('Host')), + (new DefinitionParameter('root', $l->t('Remote subfolder'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + ]) + ->addAuthScheme(AuthMechanism::SCHEME_PUBLICKEY) + ->setLegacyAuthMechanism($legacyAuth) + ->deprecateTo($sftpBackend) + ; + } +} diff --git a/apps/files_external/lib/Lib/Backend/SMB.php b/apps/files_external/lib/Lib/Backend/SMB.php new file mode 100644 index 00000000000..e86ad98880c --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/SMB.php @@ -0,0 +1,140 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ + +namespace OCA\Files_External\Lib\Backend; + +use Icewind\SMB\BasicAuth; +use Icewind\SMB\KerberosAuth; +use Icewind\SMB\KerberosTicket; +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\MissingDependency; +use OCA\Files_External\Lib\Storage\SystemBridge; +use OCA\Files_External\Lib\StorageConfig; +use OCP\IL10N; +use OCP\IUser; + +class SMB extends Backend { + public function __construct(IL10N $l, Password $legacyAuth) { + $this + ->setIdentifier('smb') + ->addIdentifierAlias('\OC\Files\Storage\SMB')// legacy compat + ->setStorageClass('\OCA\Files_External\Lib\Storage\SMB') + ->setText($l->t('SMB/CIFS')) + ->addParameters([ + new DefinitionParameter('host', $l->t('Host')), + new DefinitionParameter('share', $l->t('Share')), + (new DefinitionParameter('root', $l->t('Remote subfolder'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('domain', $l->t('Domain'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('show_hidden', $l->t('Show hidden files'))) + ->setType(DefinitionParameter::VALUE_BOOLEAN) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('case_sensitive', $l->t('Case sensitive file system'))) + ->setType(DefinitionParameter::VALUE_BOOLEAN) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL) + ->setDefaultValue(true) + ->setTooltip($l->t('Disabling it will allow to use a case insensitive file system, but comes with a performance penalty')), + (new DefinitionParameter('check_acl', $l->t('Verify ACL access when listing files'))) + ->setType(DefinitionParameter::VALUE_BOOLEAN) + ->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_TEXT) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL) + ->setFlag(DefinitionParameter::FLAG_HIDDEN), + ]) + ->addAuthScheme(AuthMechanism::SCHEME_PASSWORD) + ->addAuthScheme(AuthMechanism::SCHEME_SMB) + ->setLegacyAuthMechanism($legacyAuth); + } + + public function manipulateStorageConfig(StorageConfig &$storage, ?IUser $user = null): void { + $auth = $storage->getAuthMechanism(); + if ($auth->getScheme() === AuthMechanism::SCHEME_PASSWORD) { + if (!is_string($storage->getBackendOption('user')) || !is_string($storage->getBackendOption('password'))) { + throw new \InvalidArgumentException('user or password is not set'); + } + + $smbAuth = new BasicAuth( + $storage->getBackendOption('user'), + $storage->getBackendOption('domain'), + $storage->getBackendOption('password') + ); + } else { + switch ($auth->getIdentifier()) { + case 'smb::kerberos': + $smbAuth = new KerberosAuth(); + break; + case 'smb::kerberosapache': + if (!$auth instanceof KerberosApacheAuthMechanism) { + throw new \InvalidArgumentException('invalid authentication backend'); + } + $credentialsStore = $auth->getCredentialsStore(); + $kerbAuth = new KerberosAuth(); + $kerbAuth->setTicket(KerberosTicket::fromEnv()); + // check if a kerberos ticket is available, else fallback to session credentials + if ($kerbAuth->getTicket()?->isValid()) { + $smbAuth = $kerbAuth; + } else { + try { + $credentials = $credentialsStore->getLoginCredentials(); + $loginName = $credentials->getLoginName(); + $pass = $credentials->getPassword(); + preg_match('/(.*)@(.*)/', $loginName, $matches); + $realm = $storage->getBackendOption('default_realm'); + if (empty($realm)) { + $realm = 'WORKGROUP'; + } + if (count($matches) === 0) { + $username = $loginName; + $workgroup = $realm; + } else { + [, $username, $workgroup] = $matches; + } + $smbAuth = new BasicAuth( + $username, + $workgroup, + $pass + ); + } catch (\Exception) { + throw new InsufficientDataForMeaningfulAnswerException('No session credentials saved'); + } + } + + break; + default: + throw new \InvalidArgumentException('unknown authentication backend'); + } + } + + $storage->setBackendOption('auth', $smbAuth); + } + + public function checkDependencies(): array { + $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/Backend/SMB_OC.php b/apps/files_external/lib/Lib/Backend/SMB_OC.php new file mode 100644 index 00000000000..bcb8d0fbf16 --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/SMB_OC.php @@ -0,0 +1,57 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\Auth\AuthMechanism; +use OCA\Files_External\Lib\Auth\Password\SessionCredentials; +use OCA\Files_External\Lib\DefinitionParameter; +use OCA\Files_External\Lib\LegacyDependencyCheckPolyfill; +use OCA\Files_External\Lib\StorageConfig; +use OCA\Files_External\Service\BackendService; +use OCP\IL10N; +use OCP\IUser; + +/** + * Deprecated SMB_OC class - use SMB with the password::sessioncredentials auth mechanism + */ +class SMB_OC extends Backend { + use LegacyDependencyCheckPolyfill; + + public function __construct(IL10N $l, SessionCredentials $legacyAuth, SMB $smbBackend) { + $this + ->setIdentifier('\OC\Files\Storage\SMB_OC') + ->setStorageClass('\OCA\Files_External\Lib\Storage\SMB') + ->setText($l->t('SMB/CIFS using OC login')) + ->addParameters([ + new DefinitionParameter('host', $l->t('Host')), + (new DefinitionParameter('username_as_share', $l->t('Login as share'))) + ->setType(DefinitionParameter::VALUE_BOOLEAN), + (new DefinitionParameter('share', $l->t('Share'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + (new DefinitionParameter('root', $l->t('Remote subfolder'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + ]) + ->setPriority(BackendService::PRIORITY_DEFAULT - 10) + ->addAuthScheme(AuthMechanism::SCHEME_PASSWORD) + ->setLegacyAuthMechanism($legacyAuth) + ->deprecateTo($smbBackend) + ; + } + + /** + * @return void + */ + public function manipulateStorageConfig(StorageConfig &$storage, ?IUser $user = null) { + $username_as_share = ($storage->getBackendOption('username_as_share') === true); + + if ($username_as_share) { + $share = '/' . $storage->getBackendOption('user'); + $storage->setBackendOption('share', $share); + } + } +} diff --git a/apps/files_external/lib/Lib/Backend/Swift.php b/apps/files_external/lib/Lib/Backend/Swift.php new file mode 100644 index 00000000000..37527ba3dbb --- /dev/null +++ b/apps/files_external/lib/Lib/Backend/Swift.php @@ -0,0 +1,43 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCA\Files_External\Lib\Backend; + +use OCA\Files_External\Lib\Auth\AuthMechanism; +use OCA\Files_External\Lib\Auth\OpenStack\OpenStackV2; +use OCA\Files_External\Lib\Auth\OpenStack\Rackspace; +use OCA\Files_External\Lib\DefinitionParameter; +use OCA\Files_External\Lib\LegacyDependencyCheckPolyfill; +use OCP\IL10N; + +class Swift extends Backend { + use LegacyDependencyCheckPolyfill; + + public function __construct(IL10N $l, OpenStackV2 $openstackAuth, Rackspace $rackspaceAuth) { + $this + ->setIdentifier('swift') + ->addIdentifierAlias('\OC\Files\Storage\Swift') // legacy compat + ->setStorageClass('\OCA\Files_External\Lib\Storage\Swift') + ->setText($l->t('OpenStack Object Storage')) + ->addParameters([ + (new DefinitionParameter('service_name', $l->t('Service name'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + new DefinitionParameter('region', $l->t('Region')), + new DefinitionParameter('bucket', $l->t('Bucket')), + (new DefinitionParameter('timeout', $l->t('Request timeout (seconds)'))) + ->setFlag(DefinitionParameter::FLAG_OPTIONAL), + ]) + ->addAuthScheme(AuthMechanism::SCHEME_OPENSTACK) + ->setLegacyAuthMechanismCallback(function (array $params) use ($openstackAuth, $rackspaceAuth) { + if (isset($params['options']['key']) && $params['options']['key']) { + return $rackspaceAuth; + } + return $openstackAuth; + }) + ; + } +} |