diff options
Diffstat (limited to 'apps/files_external/lib/Service')
10 files changed, 352 insertions, 495 deletions
diff --git a/apps/files_external/lib/Service/BackendService.php b/apps/files_external/lib/Service/BackendService.php index 49af01f5bf9..3a688ee66e6 100644 --- a/apps/files_external/lib/Service/BackendService.php +++ b/apps/files_external/lib/Service/BackendService.php @@ -1,34 +1,23 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin McCorkell <robin@mccorkell.me.uk> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * 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\Service; -use \OCP\IConfig; - -use \OCA\Files_External\Lib\Backend\Backend; -use \OCA\Files_External\Lib\Auth\AuthMechanism; -use \OCA\Files_External\Lib\Config\IBackendProvider; -use \OCA\Files_External\Lib\Config\IAuthMechanismProvider; +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\IAppConfig; +use OCP\Server; /** * Service class to manage backend definitions @@ -36,18 +25,15 @@ use \OCA\Files_External\Lib\Config\IAuthMechanismProvider; class BackendService { /** Visibility constants for VisibilityTrait */ - const VISIBILITY_NONE = 0; - const VISIBILITY_PERSONAL = 1; - const VISIBILITY_ADMIN = 2; + public const VISIBILITY_NONE = 0; + public const VISIBILITY_PERSONAL = 1; + public const VISIBILITY_ADMIN = 2; //const VISIBILITY_ALIENS = 4; - const VISIBILITY_DEFAULT = 3; // PERSONAL | ADMIN + public const VISIBILITY_DEFAULT = 3; // PERSONAL | ADMIN /** Priority constants for PriorityTrait */ - const PRIORITY_DEFAULT = 100; - - /** @var IConfig */ - protected $config; + public const PRIORITY_DEFAULT = 100; /** @var bool */ private $userMountingAllowed = true; @@ -67,21 +53,17 @@ class BackendService { /** @var IAuthMechanismProvider[] */ private $authMechanismProviders = []; - /** - * @param IConfig $config - */ + /** @var callable[] */ + private $configHandlerLoaders = []; + + private $configHandlers = []; + public function __construct( - IConfig $config + protected IAppConfig $appConfig, ) { - $this->config = $config; - // 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 === ['']) { @@ -99,7 +81,19 @@ class BackendService { $this->backendProviders[] = $provider; } + private function callForRegistrations() { + static $eventSent = false; + if (!$eventSent) { + Server::get(IEventDispatcher::class)->dispatch( + 'OCA\\Files_External::loadAdditionalBackends', + new GenericEvent() + ); + $eventSent = true; + } + } + private function loadBackendProviders() { + $this->callForRegistrations(); foreach ($this->backendProviders as $provider) { $this->registerBackends($provider->getBackends()); } @@ -117,6 +111,7 @@ class BackendService { } private function loadAuthMechanismProviders() { + $this->callForRegistrations(); foreach ($this->authMechanismProviders as $provider) { $this->registerAuthMechanisms($provider->getAuthMechanisms()); } @@ -193,8 +188,9 @@ class BackendService { * @return Backend[] */ public function getAvailableBackends() { - return array_filter($this->getBackends(), function($backend) { - return !($backend->checkDependencies()); + return array_filter($this->getBackends(), function ($backend) { + $missing = array_filter($backend->checkDependencies(), fn (MissingDependency $dependency) => !$dependency->isOptional()); + return count($missing) === 0; }); } @@ -232,7 +228,7 @@ class BackendService { * @return AuthMechanism[] */ public function getAuthMechanismsByScheme(array $schemes) { - return array_filter($this->getAuthMechanisms(), function($authMech) use ($schemes) { + return array_filter($this->getAuthMechanisms(), function ($authMech) use ($schemes) { return in_array($authMech->getScheme(), $schemes, true); }); } @@ -263,8 +259,8 @@ class BackendService { * @return bool */ protected function isAllowedUserBackend(Backend $backend) { - if ($this->userMountingAllowed && - array_intersect($backend->getIdentifierAliases(), $this->userMountingBackends) + if ($this->userMountingAllowed + && array_intersect($backend->getIdentifierAliases(), $this->userMountingBackends) ) { return true; } @@ -280,4 +276,67 @@ class BackendService { protected function isAllowedAuthMechanism(AuthMechanism $authMechanism) { return true; // not implemented } + + /** + * registers a configuration handler + * + * The function of the provided $placeholder is mostly to act a sorting + * criteria, so longer placeholders are replaced first. This avoids + * "$user" overwriting parts of "$userMail" and "$userLang", for example. + * The provided value should not contain the $ prefix, only a-z0-9 are + * allowed. Upper case letters are lower cased, the replacement is case- + * insensitive. + * + * The configHandlerLoader should just instantiate the handler on demand. + * For now all handlers are instantiated when a mount is loaded, independent + * of whether the placeholder is present or not. This may change in future. + * + * @since 16.0.0 + */ + public function registerConfigHandler(string $placeholder, callable $configHandlerLoader) { + $placeholder = trim(strtolower($placeholder)); + if (!(bool)\preg_match('/^[a-z0-9]*$/', $placeholder)) { + throw new \RuntimeException(sprintf( + 'Invalid placeholder %s, only [a-z0-9] are allowed', $placeholder + )); + } + if ($placeholder === '') { + throw new \RuntimeException('Invalid empty placeholder'); + } + if (isset($this->configHandlerLoaders[$placeholder]) || isset($this->configHandlers[$placeholder])) { + throw new \RuntimeException(sprintf('A handler is already registered for %s', $placeholder)); + } + $this->configHandlerLoaders[$placeholder] = $configHandlerLoader; + } + + protected function loadConfigHandlers():void { + $this->callForRegistrations(); + $newLoaded = false; + foreach ($this->configHandlerLoaders as $placeholder => $loader) { + $handler = $loader(); + if (!$handler instanceof IConfigHandler) { + throw new \RuntimeException(sprintf( + 'Handler for %s is not an instance of IConfigHandler', $placeholder + )); + } + $this->configHandlers[$placeholder] = $handler; + $newLoaded = true; + } + $this->configHandlerLoaders = []; + if ($newLoaded) { + // ensure those with longest placeholders come first, + // to avoid substring matches + uksort($this->configHandlers, function ($phA, $phB) { + return strlen($phB) <=> strlen($phA); + }); + } + } + + /** + * @since 16.0.0 + */ + public function getConfigHandlers() { + $this->loadConfigHandlers(); + return $this->configHandlers; + } } diff --git a/apps/files_external/lib/Service/DBConfigService.php b/apps/files_external/lib/Service/DBConfigService.php index c986acbaa5d..41ec4512d70 100644 --- a/apps/files_external/lib/Service/DBConfigService.php +++ b/apps/files_external/lib/Service/DBConfigService.php @@ -1,30 +1,13 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Robin Appelman <robin@icewind.nl> - * @author Robin McCorkell <robin@mccorkell.me.uk> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * 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\Service; +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; use OCP\Security\ICrypto; @@ -33,39 +16,22 @@ use OCP\Security\ICrypto; * Stores the mount config in the database */ class DBConfigService { - const MOUNT_TYPE_ADMIN = 1; - const MOUNT_TYPE_PERSONAl = 2; - - const APPLICABLE_TYPE_GLOBAL = 1; - const APPLICABLE_TYPE_GROUP = 2; - const APPLICABLE_TYPE_USER = 3; - - /** - * @var IDBConnection - */ - private $connection; - - /** - * @var ICrypto - */ - private $crypto; - - /** - * DBConfigService constructor. - * - * @param IDBConnection $connection - * @param ICrypto $crypto - */ - public function __construct(IDBConnection $connection, ICrypto $crypto) { - $this->connection = $connection; - $this->crypto = $crypto; + public const MOUNT_TYPE_ADMIN = 1; + public const MOUNT_TYPE_PERSONAL = 2; + /** @deprecated use MOUNT_TYPE_PERSONAL (full uppercase) instead */ + public const MOUNT_TYPE_PERSONAl = 2; + + public const APPLICABLE_TYPE_GLOBAL = 1; + public const APPLICABLE_TYPE_GROUP = 2; + public const APPLICABLE_TYPE_USER = 3; + + public function __construct( + private IDBConnection $connection, + private ICrypto $crypto, + ) { } - /** - * @param int $mountId - * @return array - */ - public function getMountById($mountId) { + public function getMountById(int $mountId): ?array { $builder = $this->connection->getQueryBuilder(); $query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type']) ->from('external_mounts', 'm') @@ -113,11 +79,42 @@ class DBConfigService { return $this->getMountsFromQuery($query); } + public function modifyMountsOnUserDelete(string $uid): void { + $this->modifyMountsOnDelete($uid, self::APPLICABLE_TYPE_USER); + } + + public function modifyMountsOnGroupDelete(string $gid): void { + $this->modifyMountsOnDelete($gid, self::APPLICABLE_TYPE_GROUP); + } + + protected function modifyMountsOnDelete(string $applicableId, int $applicableType): void { + $builder = $this->connection->getQueryBuilder(); + $query = $builder->select(['a.mount_id', $builder->func()->count('a.mount_id', 'count')]) + ->from('external_applicable', 'a') + ->leftJoin('a', 'external_applicable', 'b', $builder->expr()->eq('a.mount_id', 'b.mount_id')) + ->where($builder->expr()->andX( + $builder->expr()->eq('b.type', $builder->createNamedParameter($applicableType, IQueryBuilder::PARAM_INT)), + $builder->expr()->eq('b.value', $builder->createNamedParameter($applicableId)) + ) + ) + ->groupBy(['a.mount_id']); + $stmt = $query->executeQuery(); + $result = $stmt->fetchAll(); + $stmt->closeCursor(); + + foreach ($result as $row) { + if ((int)$row['count'] > 1) { + $this->removeApplicable($row['mount_id'], $applicableType, $applicableId); + } else { + $this->removeMount($row['mount_id']); + } + } + } + /** * Get admin defined mounts * * @return array - * @suppress SqlInjectionChecker */ public function getAdminMounts() { $builder = $this->connection->getQueryBuilder(); @@ -162,7 +159,6 @@ class DBConfigService { * @param int $type any of the self::APPLICABLE_TYPE_ constants * @param string|null $value user_id, group_id or null for global mounts * @return array - * @suppress SqlInjectionChecker */ public function getAdminMountsFor($type, $value) { $builder = $this->connection->getQueryBuilder(); @@ -178,7 +174,6 @@ class DBConfigService { * @param int $type any of the self::APPLICABLE_TYPE_ constants * @param string[] $values user_ids or group_ids * @return array - * @suppress SqlInjectionChecker */ public function getAdminMountsForMultiple($type, array $values) { $builder = $this->connection->getQueryBuilder(); @@ -202,12 +197,11 @@ class DBConfigService { * @param int $type any of the self::APPLICABLE_TYPE_ constants * @param string|null $value user_id, group_id or null for global mounts * @return array - * @suppress SqlInjectionChecker */ public function getUserMountsFor($type, $value) { $builder = $this->connection->getQueryBuilder(); $query = $this->getForQuery($builder, $type, $value); - $query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_PERSONAl, IQueryBuilder::PARAM_INT))); + $query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_PERSONAL, IQueryBuilder::PARAM_INT))); return $this->getMountsFromQuery($query); } @@ -235,8 +229,8 @@ class DBConfigService { 'priority' => $builder->createNamedParameter($priority, IQueryBuilder::PARAM_INT), 'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT) ]); - $query->execute(); - return (int)$this->connection->lastInsertId('*PREFIX*external_mounts'); + $query->executeStatement(); + return $query->getLastInsertId(); } /** @@ -248,19 +242,22 @@ class DBConfigService { $builder = $this->connection->getQueryBuilder(); $query = $builder->delete('external_mounts') ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))); - $query->execute(); + $query->executeStatement(); + $builder = $this->connection->getQueryBuilder(); $query = $builder->delete('external_applicable') ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))); - $query->execute(); + $query->executeStatement(); + $builder = $this->connection->getQueryBuilder(); $query = $builder->delete('external_config') ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))); - $query->execute(); + $query->executeStatement(); + $builder = $this->connection->getQueryBuilder(); $query = $builder->delete('external_options') ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))); - $query->execute(); + $query->executeStatement(); } /** @@ -274,7 +271,7 @@ class DBConfigService { ->set('mount_point', $builder->createNamedParameter($newMountPoint)) ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))); - $query->execute(); + $query->executeStatement(); } /** @@ -288,7 +285,7 @@ class DBConfigService { ->set('auth_backend', $builder->createNamedParameter($newAuthBackend)) ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))); - $query->execute(); + $query->executeStatement(); } /** @@ -300,18 +297,21 @@ class DBConfigService { if ($key === 'password') { $value = $this->encryptValue($value); } - $count = $this->connection->insertIfNotExist('*PREFIX*external_config', [ - 'mount_id' => $mountId, - 'key' => $key, - 'value' => $value - ], ['mount_id', 'key']); - if ($count === 0) { + + try { + $builder = $this->connection->getQueryBuilder(); + $builder->insert('external_config') + ->setValue('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)) + ->setValue('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR)) + ->setValue('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR)) + ->execute(); + } catch (UniqueConstraintViolationException $e) { $builder = $this->connection->getQueryBuilder(); $query = $builder->update('external_config') ->set('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR)) ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))) ->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR))); - $query->execute(); + $query->executeStatement(); } } @@ -321,28 +321,34 @@ class DBConfigService { * @param string $value */ public function setOption($mountId, $key, $value) { - - $count = $this->connection->insertIfNotExist('*PREFIX*external_options', [ - 'mount_id' => $mountId, - 'key' => $key, - 'value' => json_encode($value) - ], ['mount_id', 'key']); - if ($count === 0) { + try { + $builder = $this->connection->getQueryBuilder(); + $builder->insert('external_options') + ->setValue('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)) + ->setValue('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR)) + ->setValue('value', $builder->createNamedParameter(json_encode($value), IQueryBuilder::PARAM_STR)) + ->execute(); + } catch (UniqueConstraintViolationException $e) { $builder = $this->connection->getQueryBuilder(); $query = $builder->update('external_options') ->set('value', $builder->createNamedParameter(json_encode($value), IQueryBuilder::PARAM_STR)) ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))) ->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR))); - $query->execute(); + $query->executeStatement(); } } public function addApplicable($mountId, $type, $value) { - $this->connection->insertIfNotExist('*PREFIX*external_applicable', [ - 'mount_id' => $mountId, - 'type' => $type, - 'value' => $value - ], ['mount_id', 'type', 'value']); + try { + $builder = $this->connection->getQueryBuilder(); + $builder->insert('external_applicable') + ->setValue('mount_id', $builder->createNamedParameter($mountId)) + ->setValue('type', $builder->createNamedParameter($type)) + ->setValue('value', $builder->createNamedParameter($value)) + ->execute(); + } catch (UniqueConstraintViolationException $e) { + // applicable exists already + } } public function removeApplicable($mountId, $type, $value) { @@ -357,11 +363,11 @@ class DBConfigService { $query = $query->andWhere($builder->expr()->eq('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR))); } - $query->execute(); + $query->executeStatement(); } private function getMountsFromQuery(IQueryBuilder $query) { - $result = $query->execute(); + $result = $query->executeQuery(); $mounts = $result->fetchAll(); $uniqueMounts = []; foreach ($mounts as $mount) { @@ -411,7 +417,10 @@ class DBConfigService { $query = $builder->select($fields) ->from($table) ->where($builder->expr()->in('mount_id', $placeHolders)); - $rows = $query->execute()->fetchAll(); + + $result = $query->executeQuery(); + $rows = $result->fetchAll(); + $result->closeCursor(); $result = []; foreach ($mountIds as $mountId) { diff --git a/apps/files_external/lib/Service/GlobalStoragesService.php b/apps/files_external/lib/Service/GlobalStoragesService.php index d0431ed11a6..5b1a9f41e48 100644 --- a/apps/files_external/lib/Service/GlobalStoragesService.php +++ b/apps/files_external/lib/Service/GlobalStoragesService.php @@ -1,38 +1,18 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Robin Appelman <robin@icewind.nl> - * @author Robin McCorkell <robin@mccorkell.me.uk> - * @author Stefan Weil <sw@weilnetz.de> - * @author Vincent Petry <pvince81@owncloud.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Files_External\Service; - -use \OC\Files\Filesystem; +use OC\Files\Filesystem; use OCA\Files_External\Lib\StorageConfig; +use OCA\Files_External\MountConfig; /** - * Service class to manage global external storages + * Service class to manage global external storage */ class GlobalStoragesService extends StoragesService { /** @@ -51,7 +31,7 @@ class GlobalStoragesService extends StoragesService { $this->triggerApplicableHooks( $signal, $storage->getMountPoint(), - \OC_Mount_Config::MOUNT_TYPE_USER, + MountConfig::MOUNT_TYPE_USER, ['all'] ); return; @@ -60,13 +40,13 @@ class GlobalStoragesService extends StoragesService { $this->triggerApplicableHooks( $signal, $storage->getMountPoint(), - \OC_Mount_Config::MOUNT_TYPE_USER, + MountConfig::MOUNT_TYPE_USER, $applicableUsers ); $this->triggerApplicableHooks( $signal, $storage->getMountPoint(), - \OC_Mount_Config::MOUNT_TYPE_GROUP, + MountConfig::MOUNT_TYPE_GROUP, $applicableGroups ); } @@ -100,7 +80,7 @@ class GlobalStoragesService extends StoragesService { $this->triggerApplicableHooks( Filesystem::signal_delete_mount, $oldStorage->getMountPoint(), - \OC_Mount_Config::MOUNT_TYPE_USER, + MountConfig::MOUNT_TYPE_USER, ['all'] ); } @@ -109,7 +89,7 @@ class GlobalStoragesService extends StoragesService { $this->triggerApplicableHooks( Filesystem::signal_delete_mount, $oldStorage->getMountPoint(), - \OC_Mount_Config::MOUNT_TYPE_USER, + MountConfig::MOUNT_TYPE_USER, $userDeletions ); @@ -117,7 +97,7 @@ class GlobalStoragesService extends StoragesService { $this->triggerApplicableHooks( Filesystem::signal_delete_mount, $oldStorage->getMountPoint(), - \OC_Mount_Config::MOUNT_TYPE_GROUP, + MountConfig::MOUNT_TYPE_GROUP, $groupDeletions ); @@ -125,7 +105,7 @@ class GlobalStoragesService extends StoragesService { $this->triggerApplicableHooks( Filesystem::signal_create_mount, $newStorage->getMountPoint(), - \OC_Mount_Config::MOUNT_TYPE_USER, + MountConfig::MOUNT_TYPE_USER, $userAdditions ); @@ -133,7 +113,7 @@ class GlobalStoragesService extends StoragesService { $this->triggerApplicableHooks( Filesystem::signal_create_mount, $newStorage->getMountPoint(), - \OC_Mount_Config::MOUNT_TYPE_GROUP, + MountConfig::MOUNT_TYPE_GROUP, $groupAdditions ); @@ -145,7 +125,7 @@ class GlobalStoragesService extends StoragesService { $this->triggerApplicableHooks( Filesystem::signal_create_mount, $newStorage->getMountPoint(), - \OC_Mount_Config::MOUNT_TYPE_USER, + MountConfig::MOUNT_TYPE_USER, ['all'] ); } @@ -154,7 +134,7 @@ class GlobalStoragesService extends StoragesService { /** * Get the visibility type for this controller, used in validation * - * @return string BackendService::VISIBILITY_* constants + * @return int BackendService::VISIBILITY_* constants */ public function getVisibilityType() { return BackendService::VISIBILITY_ADMIN; @@ -167,7 +147,7 @@ class GlobalStoragesService extends StoragesService { /** * Get all configured admin and personal mounts * - * @return array map of storage id to storage config + * @return StorageConfig[] map of storage id to storage config */ public function getStorageForAllUsers() { $mounts = $this->dbConfig->getAllMounts(); diff --git a/apps/files_external/lib/Service/ImportLegacyStoragesService.php b/apps/files_external/lib/Service/ImportLegacyStoragesService.php index 9b3dc5336be..7d9840e9f5e 100644 --- a/apps/files_external/lib/Service/ImportLegacyStoragesService.php +++ b/apps/files_external/lib/Service/ImportLegacyStoragesService.php @@ -1,26 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Robin Appelman <robin@icewind.nl> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Files_External\Service; class ImportLegacyStoragesService extends LegacyStoragesService { diff --git a/apps/files_external/lib/Service/LegacyStoragesService.php b/apps/files_external/lib/Service/LegacyStoragesService.php index 68faf0f2854..9f199a89b3f 100644 --- a/apps/files_external/lib/Service/LegacyStoragesService.php +++ b/apps/files_external/lib/Service/LegacyStoragesService.php @@ -1,30 +1,16 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Stefan Weil <sw@weilnetz.de> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * 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\Service; use OCA\Files_External\Lib\StorageConfig; +use OCA\Files_External\MountConfig; +use OCP\Server; +use Psr\Log\LoggerInterface; /** * Read mount config from legacy mount.json @@ -54,7 +40,7 @@ abstract class LegacyStoragesService { &$storageConfig, $mountType, $applicable, - $storageOptions + $storageOptions, ) { $backend = $this->backendService->getBackend($storageOptions['backend']); if (!$backend) { @@ -79,13 +65,13 @@ abstract class LegacyStoragesService { $storageOptions['priority'] = $backend->getPriority(); } $storageConfig->setPriority($storageOptions['priority']); - if ($mountType === \OC_Mount_Config::MOUNT_TYPE_USER) { + if ($mountType === MountConfig::MOUNT_TYPE_USER) { $applicableUsers = $storageConfig->getApplicableUsers(); if ($applicable !== 'all') { $applicableUsers[] = $applicable; $storageConfig->setApplicableUsers($applicableUsers); } - } else if ($mountType === \OC_Mount_Config::MOUNT_TYPE_GROUP) { + } elseif ($mountType === MountConfig::MOUNT_TYPE_GROUP) { $applicableGroups = $storageConfig->getApplicableGroups(); $applicableGroups[] = $applicable; $storageConfig->setApplicableGroups($applicableGroups); @@ -94,7 +80,7 @@ abstract class LegacyStoragesService { } /** - * Read the external storages config + * Read the external storage config * * @return StorageConfig[] map of storage id to storage config */ @@ -140,17 +126,13 @@ abstract class LegacyStoragesService { $parts = explode('/', ltrim($rootMountPath, '/'), 3); if (count($parts) < 3) { // something went wrong, skip - \OCP\Util::writeLog( - 'files_external', - 'Could not parse mount point "' . $rootMountPath . '"', - \OCP\Util::ERROR - ); + Server::get(LoggerInterface::class)->error('Could not parse mount point "' . $rootMountPath . '"', ['app' => 'files_external']); continue; } $relativeMountPath = rtrim($parts[2], '/'); // note: we cannot do this after the loop because the decrypted config // options might be needed for the config hash - $storageOptions['options'] = \OC_Mount_Config::decryptPasswords($storageOptions['options']); + $storageOptions['options'] = MountConfig::decryptPasswords($storageOptions['options']); if (!isset($storageOptions['backend'])) { $storageOptions['backend'] = $storageOptions['class']; // legacy compat } @@ -168,7 +150,7 @@ abstract class LegacyStoragesService { // but at this point we don't know the max-id, so use // first group it by config hash $storageOptions['mountpoint'] = $rootMountPath; - $configId = \OC_Mount_Config::makeConfigHash($storageOptions); + $configId = MountConfig::makeConfigHash($storageOptions); if (isset($storagesWithConfigHash[$configId])) { $currentStorage = $storagesWithConfigHash[$configId]; } @@ -192,11 +174,10 @@ abstract class LegacyStoragesService { } } catch (\UnexpectedValueException $e) { // don't die if a storage backend doesn't exist - \OCP\Util::writeLog( - 'files_external', - 'Could not load storage: "' . $e->getMessage() . '"', - \OCP\Util::ERROR - ); + Server::get(LoggerInterface::class)->error('Could not load storage.', [ + 'app' => 'files_external', + 'exception' => $e, + ]); } } } diff --git a/apps/files_external/lib/Service/StoragesService.php b/apps/files_external/lib/Service/StoragesService.php index d52bf410461..a12a8fc245a 100644 --- a/apps/files_external/lib/Service/StoragesService.php +++ b/apps/files_external/lib/Service/StoragesService.php @@ -1,70 +1,46 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Jesús Macias <jmacias@solidgear.es> - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Robin Appelman <robin@icewind.nl> - * @author Robin McCorkell <robin@mccorkell.me.uk> - * @author Stefan Weil <sw@weilnetz.de> - * @author Vincent Petry <pvince81@owncloud.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * 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\Service; -use \OC\Files\Filesystem; +use OC\Files\Cache\Storage; +use OC\Files\Filesystem; +use OCA\Files_External\Lib\Auth\AuthMechanism; use OCA\Files_External\Lib\Auth\InvalidAuth; +use OCA\Files_External\Lib\Backend\Backend; use OCA\Files_External\Lib\Backend\InvalidBackend; +use OCA\Files_External\Lib\DefinitionParameter; use OCA\Files_External\Lib\StorageConfig; use OCA\Files_External\NotFoundException; -use \OCA\Files_External\Lib\Backend\Backend; -use \OCA\Files_External\Lib\Auth\AuthMechanism; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Config\IUserMountCache; -use \OCP\Files\StorageNotAvailableException; +use OCP\Files\Events\InvalidateMountCacheEvent; +use OCP\Files\StorageNotAvailableException; +use OCP\Server; +use OCP\Util; +use Psr\Log\LoggerInterface; /** - * Service class to manage external storages + * Service class to manage external storage */ abstract class StoragesService { - /** @var BackendService */ - protected $backendService; - - /** - * @var DBConfigService - */ - protected $dbConfig; - - /** - * @var IUserMountCache - */ - protected $userMountCache; - /** * @param BackendService $backendService - * @param DBConfigService $dbConfigService + * @param DBConfigService $dbConfig * @param IUserMountCache $userMountCache + * @param IEventDispatcher $eventDispatcher */ - public function __construct(BackendService $backendService, DBConfigService $dbConfigService, IUserMountCache $userMountCache) { - $this->backendService = $backendService; - $this->dbConfig = $dbConfigService; - $this->userMountCache = $userMountCache; + public function __construct( + protected BackendService $backendService, + protected DBConfigService $dbConfig, + protected IUserMountCache $userMountCache, + protected IEventDispatcher $eventDispatcher, + ) { } protected function readDBConfig() { @@ -102,24 +78,22 @@ abstract class StoragesService { return $config; } catch (\UnexpectedValueException $e) { // don't die if a storage backend doesn't exist - \OCP\Util::writeLog( - 'files_external', - 'Could not load storage: "' . $e->getMessage() . '"', - \OCP\Util::ERROR - ); + Server::get(LoggerInterface::class)->error('Could not load storage.', [ + 'app' => 'files_external', + 'exception' => $e, + ]); return null; } catch (\InvalidArgumentException $e) { - \OCP\Util::writeLog( - 'files_external', - 'Could not load storage: "' . $e->getMessage() . '"', - \OCP\Util::ERROR - ); + Server::get(LoggerInterface::class)->error('Could not load storage.', [ + 'app' => 'files_external', + 'exception' => $e, + ]); return null; } } /** - * Read the external storages config + * Read the external storage config * * @return array map of storage id to storage config */ @@ -145,7 +119,7 @@ abstract class StoragesService { * @return StorageConfig * @throws NotFoundException if the storage with the given id was not found */ - public function getStorage($id) { + public function getStorage(int $id) { $mount = $this->dbConfig->getMountById($id); if (!is_array($mount)) { @@ -214,7 +188,7 @@ abstract class StoragesService { /** * Get the visibility type for this controller, used in validation * - * @return string BackendService::VISIBILITY_* constants + * @return int BackendService::VISIBILITY_* constants */ abstract public function getVisibilityType(); @@ -293,7 +267,7 @@ abstract class StoragesService { $mountOptions = null, $applicableUsers = null, $applicableGroups = null, - $priority = null + $priority = null, ) { $backend = $this->backendService->getBackend($backendIdentifier); if (!$backend) { @@ -328,13 +302,14 @@ abstract class StoragesService { * Triggers the given hook signal for all the applicables given * * @param string $signal signal - * @param string $mountPoint hook mount pount param + * @param string $mountPoint hook mount point param * @param string $mountType hook mount type param * @param array $applicableArray array of applicable users/groups for which to trigger the hook */ - protected function triggerApplicableHooks($signal, $mountPoint, $mountType, $applicableArray) { + protected function triggerApplicableHooks($signal, $mountPoint, $mountType, $applicableArray): void { + $this->eventDispatcher->dispatchTyped(new InvalidateMountCacheEvent(null)); foreach ($applicableArray as $applicable) { - \OCP\Util::emitHook( + Util::emitHook( Filesystem::CLASSNAME, $signal, [ @@ -415,7 +390,7 @@ abstract class StoragesService { if ($wasGlobal && !$isGlobal) { $this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_GLOBAL, null); - } else if (!$wasGlobal && $isGlobal) { + } elseif (!$wasGlobal && $isGlobal) { $this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_GLOBAL, null); } @@ -423,7 +398,9 @@ abstract class StoragesService { $changedOptions = array_diff_assoc($updatedStorage->getMountOptions(), $oldStorage->getMountOptions()); foreach ($changedConfig as $key => $value) { - $this->dbConfig->setConfig($id, $key, $value); + if ($value !== DefinitionParameter::UNMODIFIED_PLACEHOLDER) { + $this->dbConfig->setConfig($id, $key, $value); + } } foreach ($changedOptions as $key => $value) { $this->dbConfig->setOption($id, $key, $value); @@ -458,7 +435,7 @@ abstract class StoragesService { * * @throws NotFoundException if no storage was found with the given id */ - public function removeStorage($id) { + public function removeStorage(int $id) { $existingMount = $this->dbConfig->getMountById($id); if (!is_array($existingMount)) { @@ -471,45 +448,7 @@ abstract class StoragesService { $this->triggerHooks($deletedStorage, Filesystem::signal_delete_mount); // delete oc_storages entries and oc_filecache - try { - $rustyStorageId = $this->getRustyStorageIdFromConfig($deletedStorage); - \OC\Files\Cache\Storage::remove($rustyStorageId); - } catch (\Exception $e) { - // can happen either for invalid configs where the storage could not - // be instantiated or whenever $user vars where used, in which case - // the storage id could not be computed - \OCP\Util::writeLog( - 'files_external', - 'Exception: "' . $e->getMessage() . '"', - \OCP\Util::ERROR - ); - } - } - - /** - * Returns the rusty storage id from oc_storages from the given storage config. - * - * @param StorageConfig $storageConfig - * @return string rusty storage id - */ - private function getRustyStorageIdFromConfig(StorageConfig $storageConfig) { - // if any of the storage options contains $user, it is not possible - // to compute the possible storage id as we don't know which users - // mounted it already (and we certainly don't want to iterate over ALL users) - foreach ($storageConfig->getBackendOptions() as $value) { - if (strpos($value, '$user') !== false) { - throw new \Exception('Cannot compute storage id for deletion due to $user vars in the configuration'); - } - } - - // note: similar to ConfigAdapter->prepateStorageConfig() - $storageConfig->getAuthMechanism()->manipulateStorageConfig($storageConfig); - $storageConfig->getBackend()->manipulateStorageConfig($storageConfig); - - $class = $storageConfig->getBackend()->getStorageClass(); - $storageImpl = new $class($storageConfig->getBackendOptions()); - - return $storageImpl->getId(); + Storage::cleanByMountId($id); } /** @@ -528,6 +467,7 @@ abstract class StoragesService { $storage = $storageConfig->getBackend()->wrapStorage($storage); $storage = $storageConfig->getAuthMechanism()->wrapStorage($storage); + /** @var \OC\Files\Storage\Storage $storage */ return $storage->getStorageCache()->getNumericId(); } catch (\Exception $e) { return -1; diff --git a/apps/files_external/lib/Service/UserGlobalStoragesService.php b/apps/files_external/lib/Service/UserGlobalStoragesService.php index 355401bb84f..aaa59c85d62 100644 --- a/apps/files_external/lib/Service/UserGlobalStoragesService.php +++ b/apps/files_external/lib/Service/UserGlobalStoragesService.php @@ -1,61 +1,44 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Robin Appelman <robin@icewind.nl> - * @author Robin McCorkell <robin@mccorkell.me.uk> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Files_External\Service; +use OCA\Files_External\Lib\StorageConfig; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Config\IUserMountCache; -use \OCP\IUserSession; -use \OCP\IGroupManager; -use \OCA\Files_External\Lib\StorageConfig; +use OCP\IGroupManager; +use OCP\IUser; +use OCP\IUserSession; /** * Service class to read global storages applicable to the user * Read-only access available, attempting to write will throw DomainException */ class UserGlobalStoragesService extends GlobalStoragesService { - use UserTrait; - /** @var IGroupManager */ - protected $groupManager; - /** * @param BackendService $backendService * @param DBConfigService $dbConfig * @param IUserSession $userSession * @param IGroupManager $groupManager * @param IUserMountCache $userMountCache + * @param IEventDispatcher $eventDispatcher */ public function __construct( BackendService $backendService, DBConfigService $dbConfig, IUserSession $userSession, - IGroupManager $groupManager, - IUserMountCache $userMountCache + protected IGroupManager $groupManager, + IUserMountCache $userMountCache, + IEventDispatcher $eventDispatcher, ) { - parent::__construct($backendService, $dbConfig, $userMountCache); + parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher); $this->userSession = $userSession; - $this->groupManager = $groupManager; } /** @@ -75,7 +58,7 @@ class UserGlobalStoragesService extends GlobalStoragesService { $userMounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_USER, $this->getUser()->getUID()); $globalMounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_GLOBAL, null); $groups = $this->groupManager->getUserGroupIds($this->getUser()); - if (is_array($groups) && count($groups) !== 0) { + if (count($groups) !== 0) { $groupMounts = $this->dbConfig->getAdminMountsForMultiple(DBConfigService::APPLICABLE_TYPE_GROUP, $groups); } else { $groupMounts = []; @@ -177,14 +160,18 @@ class UserGlobalStoragesService extends GlobalStoragesService { /** * Gets all storages for the user, admin, personal, global, etc * + * @param IUser|null $user user to get the storages for, if not set the currently logged in user will be used * @return StorageConfig[] array of storage configs */ - public function getAllStoragesForUser() { - if (is_null($this->getUser())) { + public function getAllStoragesForUser(?IUser $user = null) { + if (is_null($user)) { + $user = $this->getUser(); + } + if (is_null($user)) { return []; } - $groupIds = $this->groupManager->getUserGroupIds($this->getUser()); - $mounts = $this->dbConfig->getMountsForUser($this->getUser()->getUID(), $groupIds); + $groupIds = $this->groupManager->getUserGroupIds($user); + $mounts = $this->dbConfig->getMountsForUser($user->getUID(), $groupIds); $configs = array_map([$this, 'getStorageConfigFromDBMount'], $mounts); $configs = array_filter($configs, function ($config) { return $config instanceof StorageConfig; diff --git a/apps/files_external/lib/Service/UserLegacyStoragesService.php b/apps/files_external/lib/Service/UserLegacyStoragesService.php deleted file mode 100644 index dec673b6f72..00000000000 --- a/apps/files_external/lib/Service/UserLegacyStoragesService.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Robin Appelman <robin@icewind.nl> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OCA\Files_External\Service; - -use OCP\IUserSession; - -/** - * Read user defined mounts from the legacy mount.json - */ -class UserLegacyStoragesService extends LegacyStoragesService { - /** - * @var IUserSession - */ - private $userSession; - - /** - * @param BackendService $backendService - * @param IUserSession $userSession - */ - public function __construct(BackendService $backendService, IUserSession $userSession) { - $this->backendService = $backendService; - $this->userSession = $userSession; - } - - /** - * Read legacy config data - * - * @return array list of storage configs - */ - protected function readLegacyConfig() { - // read user config - $user = $this->userSession->getUser()->getUID(); - return \OC_Mount_Config::readData($user); - } -} diff --git a/apps/files_external/lib/Service/UserStoragesService.php b/apps/files_external/lib/Service/UserStoragesService.php index b225f1eec8c..9d4192734b6 100644 --- a/apps/files_external/lib/Service/UserStoragesService.php +++ b/apps/files_external/lib/Service/UserStoragesService.php @@ -1,42 +1,22 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Robin McCorkell <robin@mccorkell.me.uk> - * @author Stefan Weil <sw@weilnetz.de> - * @author Vincent Petry <pvince81@owncloud.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * 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\Service; -use OCP\Files\Config\IUserMountCache; -use \OCP\IUserSession; -use \OC\Files\Filesystem; - +use OC\Files\Filesystem; use OCA\Files_External\Lib\StorageConfig; +use OCA\Files_External\MountConfig; use OCA\Files_External\NotFoundException; -use \OCA\Files_External\Service\BackendService; -use \OCA\Files_External\Service\UserTrait; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Config\IUserMountCache; +use OCP\IUserSession; /** - * Service class to manage user external storages + * Service class to manage user external storage * (aka personal storages) */ class UserStoragesService extends StoragesService { @@ -49,15 +29,17 @@ class UserStoragesService extends StoragesService { * @param DBConfigService $dbConfig * @param IUserSession $userSession user session * @param IUserMountCache $userMountCache + * @param IEventDispatcher $eventDispatcher */ public function __construct( BackendService $backendService, DBConfigService $dbConfig, IUserSession $userSession, - IUserMountCache $userMountCache + IUserMountCache $userMountCache, + IEventDispatcher $eventDispatcher, ) { $this->userSession = $userSession; - parent::__construct($backendService, $dbConfig, $userMountCache); + parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher); } protected function readDBConfig() { @@ -78,7 +60,7 @@ class UserStoragesService extends StoragesService { $this->triggerApplicableHooks( $signal, $storage->getMountPoint(), - \OC_Mount_Config::MOUNT_TYPE_USER, + MountConfig::MOUNT_TYPE_USER, [$user] ); } @@ -100,7 +82,7 @@ class UserStoragesService extends StoragesService { } protected function getType() { - return DBConfigService::MOUNT_TYPE_PERSONAl; + return DBConfigService::MOUNT_TYPE_PERSONAL; } /** @@ -112,8 +94,7 @@ class UserStoragesService extends StoragesService { */ public function addStorage(StorageConfig $newStorage) { $newStorage->setApplicableUsers([$this->getUser()->getUID()]); - $config = parent::addStorage($newStorage); - return $config; + return parent::addStorage($newStorage); } /** @@ -125,6 +106,9 @@ class UserStoragesService extends StoragesService { * @throws NotFoundException if the given storage does not exist in the config */ public function updateStorage(StorageConfig $updatedStorage) { + // verify ownership through $this->isApplicable() and otherwise throws an exception + $this->getStorage($updatedStorage->getId()); + $updatedStorage->setApplicableUsers([$this->getUser()->getUID()]); return parent::updateStorage($updatedStorage); } @@ -132,13 +116,19 @@ class UserStoragesService extends StoragesService { /** * Get the visibility type for this controller, used in validation * - * @return string BackendService::VISIBILITY_* constants + * @return int BackendService::VISIBILITY_* constants */ public function getVisibilityType() { return BackendService::VISIBILITY_PERSONAL; } protected function isApplicable(StorageConfig $config) { - return ($config->getApplicableUsers() === [$this->getUser()->getUID()]) && $config->getType() === StorageConfig::MOUNT_TYPE_PERSONAl; + return ($config->getApplicableUsers() === [$this->getUser()->getUID()]) && $config->getType() === StorageConfig::MOUNT_TYPE_PERSONAL; + } + + public function removeStorage($id) { + // verify ownership through $this->isApplicable() and otherwise throws an exception + $this->getStorage($id); + parent::removeStorage($id); } } diff --git a/apps/files_external/lib/Service/UserTrait.php b/apps/files_external/lib/Service/UserTrait.php index 5c6464cf719..679066283a5 100644 --- a/apps/files_external/lib/Service/UserTrait.php +++ b/apps/files_external/lib/Service/UserTrait.php @@ -1,29 +1,14 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Robin McCorkell <robin@mccorkell.me.uk> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Files_External\Service; -use \OCP\IUserSession; -use \OCP\IUser; +use OCP\IUser; +use OCP\IUserSession; /** * Trait for getting user information in a service @@ -54,7 +39,7 @@ trait UserTrait { * Override the user from the session * Unset with ->resetUser() when finished! * - * @param IUser + * @param IUser $user * @return self */ public function setUser(IUser $user) { @@ -72,4 +57,3 @@ trait UserTrait { return $this; } } - |