diff options
author | Robin Appelman <robin@icewind.nl> | 2022-02-10 17:36:46 +0100 |
---|---|---|
committer | Robin Appelman <robin@icewind.nl> | 2022-03-04 16:29:47 +0100 |
commit | 15ff65c12fafbe1c4026fa6f734fb58fdbdcda11 (patch) | |
tree | 34d371700a1271cb6d3371dc229cc052adeaecf3 /lib/private | |
parent | 7630d7a934c8e8036313824d95e5aa9de80dab96 (diff) | |
download | nextcloud-server-15ff65c12fafbe1c4026fa6f734fb58fdbdcda11.tar.gz nextcloud-server-15ff65c12fafbe1c4026fa6f734fb58fdbdcda11.zip |
start moving filesystem setup logic to it's own place
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/Files/Mount/Manager.php | 18 | ||||
-rw-r--r-- | lib/private/Files/SetupManager.php | 194 | ||||
-rw-r--r-- | lib/private/legacy/OC_Util.php | 144 |
3 files changed, 215 insertions, 141 deletions
diff --git a/lib/private/Files/Mount/Manager.php b/lib/private/Files/Mount/Manager.php index cfb008a94d1..91b6ad36c87 100644 --- a/lib/private/Files/Mount/Manager.php +++ b/lib/private/Files/Mount/Manager.php @@ -30,18 +30,28 @@ namespace OC\Files\Mount; use OC\Cache\CappedMemoryCache; use OC\Files\Filesystem; +use OC\Files\SetupManager; +use OCP\Diagnostics\IEventLogger; +use OCP\Files\Config\IMountProviderCollection; use OCP\Files\Mount\IMountManager; use OCP\Files\Mount\IMountPoint; +use OCP\IUserSession; class Manager implements IMountManager { /** @var MountPoint[] */ private array $mounts = []; private CappedMemoryCache $pathCache; private CappedMemoryCache $inPathCache; + private SetupManager $setupManager; - public function __construct() { + public function __construct( + IEventLogger $eventLogger, + IMountProviderCollection $mountProviderCollection, + IUserSession $userSession + ) { $this->pathCache = new CappedMemoryCache(); $this->inPathCache = new CappedMemoryCache(); + $this->setupManager = new SetupManager($eventLogger, $mountProviderCollection, $this, $userSession); } /** @@ -80,12 +90,12 @@ class Manager implements IMountManager { private function setupForFind(string $path) { if (strpos($path, '/appdata_' . \OC_Util::getInstanceId()) === 0) { // for appdata, we only setup the root bits, not the user bits - \OC_Util::setupRootFS(); + $this->setupManager->setupRoot(); } elseif (strpos($path, '/files_external/uploads/') === 0) { // for OC\Security\CertificateManager, we only setup the root bits, not the user bits - \OC_Util::setupRootFS(); + $this->setupManager->setupRoot(); } else { - \OC_Util::setupFS(); + $this->setupManager->setupForCurrentUser(); } } diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php new file mode 100644 index 00000000000..56f321666b3 --- /dev/null +++ b/lib/private/Files/SetupManager.php @@ -0,0 +1,194 @@ +<?php + +declare(strict_types=1); +/** + * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OC\Files; + +use OC\Files\Storage\Common; +use OC\Files\Storage\Storage; +use OC\Files\Storage\Wrapper\Availability; +use OC\Files\Storage\Wrapper\Encoding; +use OC\Files\Storage\Wrapper\PermissionsMask; +use OC\Files\Storage\Wrapper\Quota; +use OC_App; +use OC_Hook; +use OC_Util; +use OCP\Constants; +use OCP\Diagnostics\IEventLogger; +use OCP\Files\Config\IMountProviderCollection; +use OCP\Files\IHomeStorage; +use OCP\Files\Mount\IMountManager; +use OCP\Files\Mount\IMountPoint; +use OCP\Files\Storage\IStorage; +use OCP\IUser; +use OCP\IUserSession; + +class SetupManager { + private bool $rootSetup = false; + private IEventLogger $eventLogger; + private IMountProviderCollection $mountProviderCollection; + private IMountManager $mountManager; + private IUserSession $userSession; + private array $setupUsers = []; + + public function __construct( + IEventLogger $eventLogger, + IMountProviderCollection $mountProviderCollection, + IMountManager $mountManager, + IUserSession $userSession + ) { + $this->eventLogger = $eventLogger; + $this->mountProviderCollection = $mountProviderCollection; + $this->mountManager = $mountManager; + $this->userSession = $userSession; + } + + private function setupBuiltinWrappers() { + Filesystem::addStorageWrapper('mount_options', function ($mountPoint, IStorage $storage, IMountPoint $mount) { + if ($storage->instanceOfStorage(Common::class)) { + $storage->setMountOptions($mount->getOptions()); + } + return $storage; + }); + + Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, IStorage $storage, IMountPoint $mount) { + if (!$mount->getOption('enable_sharing', true)) { + return new PermissionsMask([ + 'storage' => $storage, + 'mask' => Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE, + ]); + } + return $storage; + }); + + // install storage availability wrapper, before most other wrappers + Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, IStorage $storage) { + if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) { + return new Availability(['storage' => $storage]); + } + return $storage; + }); + + Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, IStorage $storage, IMountPoint $mount) { + if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) { + return new Encoding(['storage' => $storage]); + } + return $storage; + }); + + Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) { + // set up quota for home storages, even for other users + // which can happen when using sharing + + /** + * @var Storage $storage + */ + if ($storage->instanceOfStorage(IHomeStorage::class)) { + if (is_object($storage->getUser())) { + $quota = OC_Util::getUserQuota($storage->getUser()); + if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) { + return new Quota(['storage' => $storage, 'quota' => $quota, 'root' => 'files']); + } + } + } + + return $storage; + }); + + Filesystem::addStorageWrapper('readonly', function ($mountPoint, IStorage $storage, IMountPoint $mount) { + /* + * Do not allow any operations that modify the storage + */ + if ($mount->getOption('readonly', false)) { + return new PermissionsMask([ + 'storage' => $storage, + 'mask' => Constants::PERMISSION_ALL & ~( + Constants::PERMISSION_UPDATE | + Constants::PERMISSION_CREATE | + Constants::PERMISSION_DELETE + ), + ]); + } + return $storage; + }); + } + + public function setupForCurrentUser() { + $user = $this->userSession->getUser(); + if ($user) { + $this->setupForUser($user); + } else { + $this->setupRoot(); + } + } + + public function setupForUser(IUser $user) { + $this->setupRoot(); + + if (in_array($user->getUID(), $this->setupUsers, true)) { + return; + } + $this->setupUsers[] = $user->getUID(); + + $this->eventLogger->start('setup_fs', 'Setup filesystem'); + + $prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false); + + OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user->getUID()]); + + Filesystem::logWarningWhenAddingStorageWrapper($prevLogging); + + $userDir = '/' . $user->getUID() . '/files'; + + Filesystem::init($user, $userDir); + + OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user->getUID(), 'user_dir' => $userDir]); + + $this->eventLogger->end('setup_fs'); + } + + public function setupRoot() { + //setting up the filesystem twice can only lead to trouble + if ($this->rootSetup) { + return; + } + + $this->eventLogger->start('setup_root_fs', 'Setup root filesystem'); + + // load all filesystem apps before, so no setup-hook gets lost + OC_App::loadApps(['filesystem']); + + $this->rootSetup = true; + $prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false); + + $this->setupBuiltinWrappers(); + + Filesystem::logWarningWhenAddingStorageWrapper($prevLogging); + + $rootMountProviders = $this->mountProviderCollection->getRootMounts(); + foreach ($rootMountProviders as $rootMountProvider) { + $this->mountManager->addMount($rootMountProvider); + } + + $this->eventLogger->end('setup_root_fs'); + } +} diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php index 40dcbb13b93..1d224ed460d 100644 --- a/lib/private/legacy/OC_Util.php +++ b/lib/private/legacy/OC_Util.php @@ -66,6 +66,7 @@ use bantu\IniGetWrapper\IniGetWrapper; use OC\AppFramework\Http\Request; +use OC\Files\SetupManager; use OCP\Files\Template\ITemplateManager; use OCP\IConfig; use OCP\IGroupManager; @@ -78,8 +79,6 @@ class OC_Util { public static $scripts = []; public static $styles = []; public static $headers = []; - private static $rootFsSetup = false; - private static $fsSetup = false; /** @var array Local cache of version.php */ private static $versionCache = null; @@ -89,122 +88,6 @@ class OC_Util { } /** - * Can be set up - * - * @param string $user - * @return boolean - * @description configure the initial filesystem based on the configuration - * @suppress PhanDeprecatedFunction - * @suppress PhanAccessMethodInternal - */ - public static function setupRootFS(string $user = '') { - //setting up the filesystem twice can only lead to trouble - if (self::$rootFsSetup) { - return false; - } - - \OC::$server->getEventLogger()->start('setup_root_fs', 'Setup root filesystem'); - - // load all filesystem apps before, so no setup-hook gets lost - OC_App::loadApps(['filesystem']); - - self::$rootFsSetup = true; - - \OC\Files\Filesystem::initMountManager(); - - $prevLogging = \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(false); - \OC\Files\Filesystem::addStorageWrapper('mount_options', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) { - if ($storage->instanceOfStorage('\OC\Files\Storage\Common')) { - /** @var \OC\Files\Storage\Common $storage */ - $storage->setMountOptions($mount->getOptions()); - } - return $storage; - }); - - \OC\Files\Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) { - if (!$mount->getOption('enable_sharing', true)) { - return new \OC\Files\Storage\Wrapper\PermissionsMask([ - 'storage' => $storage, - 'mask' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_SHARE - ]); - } - return $storage; - }); - - // install storage availability wrapper, before most other wrappers - \OC\Files\Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, \OCP\Files\Storage\IStorage $storage) { - if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) { - return new \OC\Files\Storage\Wrapper\Availability(['storage' => $storage]); - } - return $storage; - }); - - \OC\Files\Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) { - if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) { - return new \OC\Files\Storage\Wrapper\Encoding(['storage' => $storage]); - } - return $storage; - }); - - \OC\Files\Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) { - // set up quota for home storages, even for other users - // which can happen when using sharing - - /** - * @var \OC\Files\Storage\Storage $storage - */ - if ($storage->instanceOfStorage('\OC\Files\Storage\Home') - || $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage') - ) { - /** @var \OC\Files\Storage\Home $storage */ - if (is_object($storage->getUser())) { - $quota = OC_Util::getUserQuota($storage->getUser()); - if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) { - return new \OC\Files\Storage\Wrapper\Quota(['storage' => $storage, 'quota' => $quota, 'root' => 'files']); - } - } - } - - return $storage; - }); - - \OC\Files\Filesystem::addStorageWrapper('readonly', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) { - /* - * Do not allow any operations that modify the storage - */ - if ($mount->getOption('readonly', false)) { - return new \OC\Files\Storage\Wrapper\PermissionsMask([ - 'storage' => $storage, - 'mask' => \OCP\Constants::PERMISSION_ALL & ~( - \OCP\Constants::PERMISSION_UPDATE | - \OCP\Constants::PERMISSION_CREATE | - \OCP\Constants::PERMISSION_DELETE - ), - ]); - } - return $storage; - }); - - OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user]); - - \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper($prevLogging); - - /** @var \OCP\Files\Config\IMountProviderCollection $mountProviderCollection */ - $mountProviderCollection = \OC::$server->query(\OCP\Files\Config\IMountProviderCollection::class); - $rootMountProviders = $mountProviderCollection->getRootMounts(); - - /** @var \OC\Files\Mount\Manager $mountManager */ - $mountManager = \OC\Files\Filesystem::getMountManager(); - foreach ($rootMountProviders as $rootMountProvider) { - $mountManager->addMount($rootMountProvider); - } - - \OC::$server->getEventLogger()->end('setup_root_fs'); - - return true; - } - - /** * Setup the file system * * @param string|null $user @@ -214,14 +97,6 @@ class OC_Util { * @suppress PhanAccessMethodInternal */ public static function setupFS(?string $user = '') { - self::setupRootFS($user ?? ''); - - if (self::$fsSetup) { - return false; - } - - \OC::$server->getEventLogger()->start('setup_fs', 'Setup filesystem'); - // If we are not forced to load a specific user we load the one that is logged in if ($user === '') { $userObject = \OC::$server->get(\OCP\IUserSession::class)->getUser(); @@ -229,19 +104,14 @@ class OC_Util { $userObject = \OC::$server->get(\OCP\IUserManager::class)->get($user); } - //if we aren't logged in, or the user doesn't exist, there is no use to set up the filesystem - if ($userObject) { - self::$fsSetup = true; + /** @var SetupManager $setupManager */ + $setupManager = \OC::$server->get(SetupManager::class); - $userDir = '/' . $userObject->getUID() . '/files'; - - //jail the user into his "home" directory - \OC\Files\Filesystem::init($userObject, $userDir); - - OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $userObject->getUID(), 'user_dir' => $userDir]); + if ($userObject) { + $setupManager->setupForUser($userObject); + } else { + $setupManager->setupRoot(); } - \OC::$server->getEventLogger()->end('setup_fs'); - return true; } /** |