start moving filesystem setup logic to it's own place

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2022-02-10 17:36:46 +01:00
parent 7630d7a934
commit 15ff65c12f
No known key found for this signature in database
GPG key ID: 42B69D8A64526EFB
3 changed files with 215 additions and 141 deletions

View file

@ -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();
}
}

View file

@ -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');
}
}

View file

@ -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;
@ -88,122 +87,6 @@ class OC_Util {
return \OC::$server->getAppManager();
}
/**
* 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
*
@ -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
/** @var SetupManager $setupManager */
$setupManager = \OC::$server->get(SetupManager::class);
if ($userObject) {
self::$fsSetup = true;
$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]);
$setupManager->setupForUser($userObject);
} else {
$setupManager->setupRoot();
}
\OC::$server->getEventLogger()->end('setup_fs');
return true;
}
/**