Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Petry <vincent@nextcloud.com>2022-03-24 23:08:15 +0300
committerGitHub <noreply@github.com>2022-03-24 23:08:15 +0300
commita7e778b57fb81c8e62d093ece7f0689d34db4c45 (patch)
treef50492f0380bb21d0cce095231c2560f77b00d36
parent00076c07098dbff236d133998de03bee8d4fec33 (diff)
parent91ab4e1df4f3e234c5e4941d89cf0d9f19166c18 (diff)
Merge pull request #31265 from nextcloud/fs-limited-setup
Fine grained filesystem setup
-rw-r--r--apps/dav/lib/Connector/Sabre/Auth.php1
-rw-r--r--apps/dav/lib/Connector/Sabre/ServerFactory.php2
-rw-r--r--apps/files_external/lib/Service/StoragesService.php16
-rw-r--r--apps/files_external/lib/Service/UserGlobalStoragesService.php7
-rw-r--r--apps/files_external/lib/Service/UserStoragesService.php7
-rw-r--r--apps/files_external/tests/Service/GlobalStoragesServiceTest.php2
-rw-r--r--apps/files_external/tests/Service/StoragesServiceTest.php7
-rw-r--r--apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php3
-rw-r--r--apps/files_external/tests/Service/UserStoragesServiceTest.php4
-rw-r--r--apps/files_sharing/lib/MountProvider.php4
-rw-r--r--apps/files_sharing/lib/SharedMount.php42
-rw-r--r--lib/composer/composer/autoload_classmap.php2
-rw-r--r--lib/composer/composer/autoload_static.php2
-rw-r--r--lib/private/Files/Config/MountProviderCollection.php34
-rw-r--r--lib/private/Files/Config/UserMountCache.php42
-rw-r--r--lib/private/Files/Filesystem.php27
-rw-r--r--lib/private/Files/Mount/Manager.php2
-rw-r--r--lib/private/Files/Node/LazyFolder.php25
-rw-r--r--lib/private/Files/Node/LazyUserFolder.php56
-rw-r--r--lib/private/Files/Node/Root.php21
-rw-r--r--lib/private/Files/SetupManager.php221
-rw-r--r--lib/private/Files/SetupManagerFactory.php17
-rw-r--r--lib/public/Files/Config/IMountProviderCollection.php10
-rw-r--r--lib/public/Files/Config/IUserMountCache.php26
-rw-r--r--lib/public/Files/Events/InvalidateMountCacheEvent.php55
25 files changed, 561 insertions, 74 deletions
diff --git a/apps/dav/lib/Connector/Sabre/Auth.php b/apps/dav/lib/Connector/Sabre/Auth.php
index 71e833809ac..df4e3c65ce0 100644
--- a/apps/dav/lib/Connector/Sabre/Auth.php
+++ b/apps/dav/lib/Connector/Sabre/Auth.php
@@ -235,7 +235,6 @@ class Auth extends AbstractBasic {
\OC_User::handleApacheAuth()
) {
$user = $this->userSession->getUser()->getUID();
- \OC_Util::setupFS($user);
$this->currentUser = $user;
$this->session->close();
return [true, $this->principalPrefix . $user];
diff --git a/apps/dav/lib/Connector/Sabre/ServerFactory.php b/apps/dav/lib/Connector/Sabre/ServerFactory.php
index ff96b7a19c5..095fb631c2b 100644
--- a/apps/dav/lib/Connector/Sabre/ServerFactory.php
+++ b/apps/dav/lib/Connector/Sabre/ServerFactory.php
@@ -31,7 +31,7 @@
*/
namespace OCA\DAV\Connector\Sabre;
-use OC\Files\Node\Folder;
+use OCP\Files\Folder;
use OCA\DAV\AppInfo\PluginManager;
use OCA\DAV\Files\BrowserErrorPagePlugin;
use OCP\Files\Mount\IMountManager;
diff --git a/apps/files_external/lib/Service/StoragesService.php b/apps/files_external/lib/Service/StoragesService.php
index b8eabd65e1e..489192dbdc2 100644
--- a/apps/files_external/lib/Service/StoragesService.php
+++ b/apps/files_external/lib/Service/StoragesService.php
@@ -40,7 +40,9 @@ 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 OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IUserMountCache;
+use OCP\Files\Events\InvalidateMountCacheEvent;
use OCP\Files\StorageNotAvailableException;
use OCP\ILogger;
@@ -62,15 +64,24 @@ abstract class StoragesService {
*/
protected $userMountCache;
+ protected IEventDispatcher $eventDispatcher;
+
/**
* @param BackendService $backendService
* @param DBConfigService $dbConfigService
* @param IUserMountCache $userMountCache
+ * @param IEventDispatcher $eventDispatcher
*/
- public function __construct(BackendService $backendService, DBConfigService $dbConfigService, IUserMountCache $userMountCache) {
+ public function __construct(
+ BackendService $backendService,
+ DBConfigService $dbConfigService,
+ IUserMountCache $userMountCache,
+ IEventDispatcher $eventDispatcher
+ ) {
$this->backendService = $backendService;
$this->dbConfig = $dbConfigService;
$this->userMountCache = $userMountCache;
+ $this->eventDispatcher = $eventDispatcher;
}
protected function readDBConfig() {
@@ -338,7 +349,8 @@ abstract class StoragesService {
* @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(
Filesystem::CLASSNAME,
diff --git a/apps/files_external/lib/Service/UserGlobalStoragesService.php b/apps/files_external/lib/Service/UserGlobalStoragesService.php
index ba894d8f210..2eda36e9242 100644
--- a/apps/files_external/lib/Service/UserGlobalStoragesService.php
+++ b/apps/files_external/lib/Service/UserGlobalStoragesService.php
@@ -24,6 +24,7 @@
namespace OCA\Files_External\Service;
use OCA\Files_External\Lib\StorageConfig;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IUserMountCache;
use OCP\IGroupManager;
use OCP\IUser;
@@ -45,15 +46,17 @@ class UserGlobalStoragesService extends GlobalStoragesService {
* @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
+ IUserMountCache $userMountCache,
+ IEventDispatcher $eventDispatcher
) {
- parent::__construct($backendService, $dbConfig, $userMountCache);
+ parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher);
$this->userSession = $userSession;
$this->groupManager = $groupManager;
}
diff --git a/apps/files_external/lib/Service/UserStoragesService.php b/apps/files_external/lib/Service/UserStoragesService.php
index 8af6bdb3a77..b09b37b40cc 100644
--- a/apps/files_external/lib/Service/UserStoragesService.php
+++ b/apps/files_external/lib/Service/UserStoragesService.php
@@ -32,6 +32,7 @@ use OC\Files\Filesystem;
use OCA\Files_External\Lib\StorageConfig;
use OCA\Files_External\NotFoundException;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IUserMountCache;
use OCP\IUserSession;
@@ -49,15 +50,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() {
diff --git a/apps/files_external/tests/Service/GlobalStoragesServiceTest.php b/apps/files_external/tests/Service/GlobalStoragesServiceTest.php
index b23c4b8f2bf..7d77ea971f3 100644
--- a/apps/files_external/tests/Service/GlobalStoragesServiceTest.php
+++ b/apps/files_external/tests/Service/GlobalStoragesServiceTest.php
@@ -37,7 +37,7 @@ use OCA\Files_External\Service\GlobalStoragesService;
class GlobalStoragesServiceTest extends StoragesServiceTest {
protected function setUp(): void {
parent::setUp();
- $this->service = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache);
+ $this->service = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher);
}
protected function tearDown(): void {
diff --git a/apps/files_external/tests/Service/StoragesServiceTest.php b/apps/files_external/tests/Service/StoragesServiceTest.php
index 3829a9ea0ce..4eaf70a8e84 100644
--- a/apps/files_external/tests/Service/StoragesServiceTest.php
+++ b/apps/files_external/tests/Service/StoragesServiceTest.php
@@ -39,6 +39,7 @@ use OCA\Files_External\Service\BackendService;
use OCA\Files_External\Service\DBConfigService;
use OCA\Files_External\Service\StoragesService;
use OCP\AppFramework\IAppContainer;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Cache\ICache;
use OCP\Files\Config\IUserMountCache;
use OCP\Files\Mount\IMountPoint;
@@ -96,6 +97,11 @@ abstract class StoragesServiceTest extends \Test\TestCase {
*/
protected $mountCache;
+ /**
+ * @var \PHPUnit\Framework\MockObject\MockObject|IEventDispatcher
+ */
+ protected IEventDispatcher $eventDispatcher;
+
protected function setUp(): void {
parent::setUp();
$this->dbConfig = new CleaningDBConfig(\OC::$server->getDatabaseConnection(), \OC::$server->getCrypto());
@@ -108,6 +114,7 @@ abstract class StoragesServiceTest extends \Test\TestCase {
\OCA\Files_External\MountConfig::$skipTest = true;
$this->mountCache = $this->createMock(IUserMountCache::class);
+ $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
// prepare BackendService mock
$this->backendService =
diff --git a/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php b/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php
index ea77148c8f2..aa5aa1df431 100644
--- a/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php
+++ b/apps/files_external/tests/Service/UserGlobalStoragesServiceTest.php
@@ -100,7 +100,8 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
$this->dbConfig,
$userSession,
$this->groupManager,
- $this->mountCache
+ $this->mountCache,
+ $this->eventDispatcher,
);
}
diff --git a/apps/files_external/tests/Service/UserStoragesServiceTest.php b/apps/files_external/tests/Service/UserStoragesServiceTest.php
index ff39ea9ddbc..cda1dd0a27f 100644
--- a/apps/files_external/tests/Service/UserStoragesServiceTest.php
+++ b/apps/files_external/tests/Service/UserStoragesServiceTest.php
@@ -54,7 +54,7 @@ class UserStoragesServiceTest extends StoragesServiceTest {
protected function setUp(): void {
parent::setUp();
- $this->globalStoragesService = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache);
+ $this->globalStoragesService = new GlobalStoragesService($this->backendService, $this->dbConfig, $this->mountCache, $this->eventDispatcher);
$this->userId = $this->getUniqueID('user_');
$this->createUser($this->userId, $this->userId);
@@ -67,7 +67,7 @@ class UserStoragesServiceTest extends StoragesServiceTest {
->method('getUser')
->willReturn($this->user);
- $this->service = new UserStoragesService($this->backendService, $this->dbConfig, $userSession, $this->mountCache);
+ $this->service = new UserStoragesService($this->backendService, $this->dbConfig, $userSession, $this->mountCache, $this->eventDispatcher);
}
private function makeTestStorageData() {
diff --git a/apps/files_sharing/lib/MountProvider.php b/apps/files_sharing/lib/MountProvider.php
index 102e5d96559..27edf5074e1 100644
--- a/apps/files_sharing/lib/MountProvider.php
+++ b/apps/files_sharing/lib/MountProvider.php
@@ -134,7 +134,9 @@ class MountProvider implements IMountProvider {
],
$loader,
$view,
- $foldersExistCache
+ $foldersExistCache,
+ $this->eventDispatcher,
+ $user
);
$event = new ShareMountedEvent($mount);
diff --git a/apps/files_sharing/lib/SharedMount.php b/apps/files_sharing/lib/SharedMount.php
index c8f5d0f64ae..60361e25fd0 100644
--- a/apps/files_sharing/lib/SharedMount.php
+++ b/apps/files_sharing/lib/SharedMount.php
@@ -34,7 +34,9 @@ use OC\Files\Mount\MountPoint;
use OC\Files\Mount\MoveableMount;
use OC\Files\View;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Events\InvalidateMountCacheEvent;
use OCP\Files\Storage\IStorageFactory;
+use OCP\IUser;
use OCP\Share\Events\VerifyMountPointEvent;
/**
@@ -51,10 +53,7 @@ class SharedMount extends MountPoint implements MoveableMount {
*/
private $recipientView;
- /**
- * @var string
- */
- private $user;
+ private IUser $user;
/** @var \OCP\Share\IShare */
private $superShare;
@@ -62,22 +61,27 @@ class SharedMount extends MountPoint implements MoveableMount {
/** @var \OCP\Share\IShare[] */
private $groupedShares;
- /**
- * @param string $storage
- * @param SharedMount[] $mountpoints
- * @param array $arguments
- * @param IStorageFactory $loader
- * @param View $recipientView
- */
- public function __construct($storage, array $mountpoints, $arguments, IStorageFactory $loader, View $recipientView, CappedMemoryCache $folderExistCache) {
- $this->user = $arguments['user'];
+ private IEventDispatcher $eventDispatcher;
+
+ public function __construct(
+ $storage,
+ array $mountpoints,
+ $arguments,
+ IStorageFactory $loader,
+ View $recipientView,
+ CappedMemoryCache $folderExistCache,
+ IEventDispatcher $eventDispatcher,
+ IUser $user
+ ) {
+ $this->user = $user;
$this->recipientView = $recipientView;
+ $this->eventDispatcher = $eventDispatcher;
$this->superShare = $arguments['superShare'];
$this->groupedShares = $arguments['groupedShares'];
$newMountPoint = $this->verifyMountPoint($this->superShare, $mountpoints, $folderExistCache);
- $absMountPoint = '/' . $this->user . '/files' . $newMountPoint;
+ $absMountPoint = '/' . $user->getUID() . '/files' . $newMountPoint;
parent::__construct($storage, $absMountPoint, $arguments, $loader, null, null, MountProvider::class);
}
@@ -93,9 +97,7 @@ class SharedMount extends MountPoint implements MoveableMount {
$parent = dirname($share->getTarget());
$event = new VerifyMountPointEvent($share, $this->recipientView, $parent);
- /** @var IEventDispatcher $dispatcher */
- $dispatcher = \OC::$server->query(IEventDispatcher::class);
- $dispatcher->dispatchTyped($event);
+ $this->eventDispatcher->dispatchTyped($event);
$parent = $event->getParent();
if ($folderExistCache->hasKey($parent)) {
@@ -105,7 +107,7 @@ class SharedMount extends MountPoint implements MoveableMount {
$folderExistCache->set($parent, $parentExists);
}
if (!$parentExists) {
- $parent = Helper::getShareFolder($this->recipientView, $this->user);
+ $parent = Helper::getShareFolder($this->recipientView, $this->user->getUID());
}
$newMountPoint = $this->generateUniqueTarget(
@@ -133,8 +135,10 @@ class SharedMount extends MountPoint implements MoveableMount {
foreach ($this->groupedShares as $tmpShare) {
$tmpShare->setTarget($newPath);
- \OC::$server->getShareManager()->moveShare($tmpShare, $this->user);
+ \OC::$server->getShareManager()->moveShare($tmpShare, $this->user->getUID());
}
+
+ $this->eventDispatcher->dispatchTyped(new InvalidateMountCacheEvent($this->user));
}
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index feaa60a4ca6..79035f2e42a 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -260,6 +260,7 @@ return array(
'OCP\\Files\\Events\\FileCacheUpdated' => $baseDir . '/lib/public/Files/Events/FileCacheUpdated.php',
'OCP\\Files\\Events\\FileScannedEvent' => $baseDir . '/lib/public/Files/Events/FileScannedEvent.php',
'OCP\\Files\\Events\\FolderScannedEvent' => $baseDir . '/lib/public/Files/Events/FolderScannedEvent.php',
+ 'OCP\\Files\\Events\\InvalidateMountCacheEvent' => $baseDir . '/lib/public/Files/Events/InvalidateMountCacheEvent.php',
'OCP\\Files\\Events\\NodeAddedToCache' => $baseDir . '/lib/public/Files/Events/NodeAddedToCache.php',
'OCP\\Files\\Events\\NodeRemovedFromCache' => $baseDir . '/lib/public/Files/Events/NodeRemovedFromCache.php',
'OCP\\Files\\Events\\Node\\AbstractNodeEvent' => $baseDir . '/lib/public/Files/Events/Node/AbstractNodeEvent.php',
@@ -1141,6 +1142,7 @@ return array(
'OC\\Files\\Node\\HookConnector' => $baseDir . '/lib/private/Files/Node/HookConnector.php',
'OC\\Files\\Node\\LazyFolder' => $baseDir . '/lib/private/Files/Node/LazyFolder.php',
'OC\\Files\\Node\\LazyRoot' => $baseDir . '/lib/private/Files/Node/LazyRoot.php',
+ 'OC\\Files\\Node\\LazyUserFolder' => $baseDir . '/lib/private/Files/Node/LazyUserFolder.php',
'OC\\Files\\Node\\Node' => $baseDir . '/lib/private/Files/Node/Node.php',
'OC\\Files\\Node\\NonExistingFile' => $baseDir . '/lib/private/Files/Node/NonExistingFile.php',
'OC\\Files\\Node\\NonExistingFolder' => $baseDir . '/lib/private/Files/Node/NonExistingFolder.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 795742f87f8..4a4c886a082 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -289,6 +289,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Files\\Events\\FileCacheUpdated' => __DIR__ . '/../../..' . '/lib/public/Files/Events/FileCacheUpdated.php',
'OCP\\Files\\Events\\FileScannedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/FileScannedEvent.php',
'OCP\\Files\\Events\\FolderScannedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/FolderScannedEvent.php',
+ 'OCP\\Files\\Events\\InvalidateMountCacheEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/InvalidateMountCacheEvent.php',
'OCP\\Files\\Events\\NodeAddedToCache' => __DIR__ . '/../../..' . '/lib/public/Files/Events/NodeAddedToCache.php',
'OCP\\Files\\Events\\NodeRemovedFromCache' => __DIR__ . '/../../..' . '/lib/public/Files/Events/NodeRemovedFromCache.php',
'OCP\\Files\\Events\\Node\\AbstractNodeEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/AbstractNodeEvent.php',
@@ -1170,6 +1171,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Files\\Node\\HookConnector' => __DIR__ . '/../../..' . '/lib/private/Files/Node/HookConnector.php',
'OC\\Files\\Node\\LazyFolder' => __DIR__ . '/../../..' . '/lib/private/Files/Node/LazyFolder.php',
'OC\\Files\\Node\\LazyRoot' => __DIR__ . '/../../..' . '/lib/private/Files/Node/LazyRoot.php',
+ 'OC\\Files\\Node\\LazyUserFolder' => __DIR__ . '/../../..' . '/lib/private/Files/Node/LazyUserFolder.php',
'OC\\Files\\Node\\Node' => __DIR__ . '/../../..' . '/lib/private/Files/Node/Node.php',
'OC\\Files\\Node\\NonExistingFile' => __DIR__ . '/../../..' . '/lib/private/Files/Node/NonExistingFile.php',
'OC\\Files\\Node\\NonExistingFolder' => __DIR__ . '/../../..' . '/lib/private/Files/Node/NonExistingFolder.php',
diff --git a/lib/private/Files/Config/MountProviderCollection.php b/lib/private/Files/Config/MountProviderCollection.php
index cd8a2a2e29f..2b0acf7d69d 100644
--- a/lib/private/Files/Config/MountProviderCollection.php
+++ b/lib/private/Files/Config/MountProviderCollection.php
@@ -75,16 +75,15 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
}
/**
- * Get all configured mount points for the user
- *
- * @param \OCP\IUser $user
- * @return \OCP\Files\Mount\IMountPoint[]
+ * @param IUser $user
+ * @param IMountProvider[] $providers
+ * @return IMountPoint[]
*/
- public function getMountsForUser(IUser $user) {
+ private function getUserMountsForProviders(IUser $user, array $providers): array {
$loader = $this->loader;
$mounts = array_map(function (IMountProvider $provider) use ($user, $loader) {
return $provider->getMountsForUser($user, $loader);
- }, $this->providers);
+ }, $providers);
$mounts = array_filter($mounts, function ($result) {
return is_array($result);
});
@@ -94,14 +93,31 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
return $this->filterMounts($user, $mounts);
}
- public function addMountForUser(IUser $user, IMountManager $mountManager) {
+ public function getMountsForUser(IUser $user): array {
+ return $this->getUserMountsForProviders($user, $this->providers);
+ }
+
+ public function getUserMountsForProviderClass(IUser $user, string $mountProviderClass): array {
+ $providers = array_filter(
+ $this->providers,
+ fn (IMountProvider $mountProvider) => (get_class($mountProvider) === $mountProviderClass)
+ );
+ return $this->getUserMountsForProviders($user, $providers);
+ }
+
+ public function addMountForUser(IUser $user, IMountManager $mountManager, callable $providerFilter = null) {
// shared mount provider gets to go last since it needs to know existing files
// to check for name collisions
$firstMounts = [];
- $firstProviders = array_filter($this->providers, function (IMountProvider $provider) {
+ if ($providerFilter) {
+ $providers = array_filter($this->providers, $providerFilter);
+ } else {
+ $providers = $this->providers;
+ }
+ $firstProviders = array_filter($providers, function (IMountProvider $provider) {
return (get_class($provider) !== 'OCA\Files_Sharing\MountProvider');
});
- $lastProviders = array_filter($this->providers, function (IMountProvider $provider) {
+ $lastProviders = array_filter($providers, function (IMountProvider $provider) {
return (get_class($provider) === 'OCA\Files_Sharing\MountProvider');
});
foreach ($firstProviders as $provider) {
diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php
index dc2640361e7..9a5eddc4878 100644
--- a/lib/private/Files/Config/UserMountCache.php
+++ b/lib/private/Files/Config/UserMountCache.php
@@ -89,7 +89,7 @@ class UserMountCache implements IUserMountCache {
$this->mountsForUsers = new CappedMemoryCache();
}
- public function registerMounts(IUser $user, array $mounts) {
+ public function registerMounts(IUser $user, array $mounts, array $mountProviderClasses = null) {
// filter out non-proper storages coming from unit tests
$mounts = array_filter($mounts, function (IMountPoint $mount) {
return $mount instanceof SharedMount || $mount->getStorage() && $mount->getStorage()->getCache();
@@ -110,6 +110,11 @@ class UserMountCache implements IUserMountCache {
$newMounts = array_combine($newMountRootIds, $newMounts);
$cachedMounts = $this->getMountsForUser($user);
+ if (is_array($mountProviderClasses)) {
+ $cachedMounts = array_filter($cachedMounts, function (ICachedMountInfo $mountInfo) use ($mountProviderClasses) {
+ return in_array($mountInfo->getMountProvider(), $mountProviderClasses);
+ });
+ }
$cachedMountRootIds = array_map(function (ICachedMountInfo $mount) {
return $mount->getRootId();
}, $cachedMounts);
@@ -446,4 +451,39 @@ class UserMountCache implements IUserMountCache {
$this->cacheInfoCache = new CappedMemoryCache();
$this->mountsForUsers = new CappedMemoryCache();
}
+
+ public function getMountForPath(IUser $user, string $path): ICachedMountInfo {
+ $mounts = $this->getMountsForUser($user);
+ $mountPoints = array_map(function (ICachedMountInfo $mount) {
+ return $mount->getMountPoint();
+ }, $mounts);
+ $mounts = array_combine($mountPoints, $mounts);
+
+ $current = $path;
+ // walk up the directory tree until we find a path that has a mountpoint set
+ // the loop will return if a mountpoint is found or break if none are found
+ while (true) {
+ $mountPoint = $current . '/';
+ if (isset($mounts[$mountPoint])) {
+ return $mounts[$mountPoint];
+ } elseif ($current === '') {
+ break;
+ }
+
+ $current = dirname($current);
+ if ($current === '.' || $current === '/') {
+ $current = '';
+ }
+ }
+
+ throw new NotFoundException("No cached mount for path " . $path);
+ }
+
+ public function getMountsInPath(IUser $user, string $path): array {
+ $path = rtrim($path, '/') . '/';
+ $mounts = $this->getMountsForUser($user);
+ return array_filter($mounts, function (ICachedMountInfo $mount) use ($path) {
+ return $mount->getMountPoint() !== $path && strpos($mount->getMountPoint(), $path) === 0;
+ });
+ }
}
diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php
index 9db9252037f..20b44e2736a 100644
--- a/lib/private/Files/Filesystem.php
+++ b/lib/private/Files/Filesystem.php
@@ -46,6 +46,7 @@ use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorageFactory;
use OCP\IUser;
use OCP\IUserManager;
+use OCP\IUserSession;
class Filesystem {
@@ -324,6 +325,18 @@ class Filesystem {
if (self::$defaultInstance) {
return false;
}
+ self::initInternal($root);
+
+ //load custom mount config
+ self::initMountPoints($user);
+
+ return true;
+ }
+
+ public static function initInternal($root) {
+ if (self::$defaultInstance) {
+ return false;
+ }
self::getLoader();
self::$defaultInstance = new View($root);
/** @var IEventDispatcher $eventDispatcher */
@@ -338,9 +351,6 @@ class Filesystem {
self::$mounts = \OC::$server->getMountManager();
}
- //load custom mount config
- self::initMountPoints($user);
-
self::$loaded = true;
return true;
@@ -378,6 +388,15 @@ class Filesystem {
* @return View
*/
public static function getView() {
+ if (!self::$defaultInstance) {
+ /** @var IUserSession $session */
+ $session = \OC::$server->get(IUserSession::class);
+ $user = $session->getUser();
+ if ($user) {
+ $userDir = '/' . $user->getUID() . '/files';
+ self::initInternal($userDir);
+ }
+ }
return self::$defaultInstance;
}
@@ -736,7 +755,7 @@ class Filesystem {
* @return \OC\Files\FileInfo|false False if file does not exist
*/
public static function getFileInfo($path, $includeMountPoints = true) {
- return self::$defaultInstance->getFileInfo($path, $includeMountPoints);
+ return self::getView()->getFileInfo($path, $includeMountPoints);
}
/**
diff --git a/lib/private/Files/Mount/Manager.php b/lib/private/Files/Mount/Manager.php
index 66832690363..ecd97760f17 100644
--- a/lib/private/Files/Mount/Manager.php
+++ b/lib/private/Files/Mount/Manager.php
@@ -125,7 +125,7 @@ class Manager implements IMountManager {
* @return IMountPoint[]
*/
public function findIn(string $path): array {
- $this->setupManager->setupForPath($path);
+ $this->setupManager->setupForPath($path, true);
$path = $this->formatPath($path);
if (isset($this->inPathCache[$path])) {
diff --git a/lib/private/Files/Node/LazyFolder.php b/lib/private/Files/Node/LazyFolder.php
index bfdaeeccff7..45451e5c53c 100644
--- a/lib/private/Files/Node/LazyFolder.php
+++ b/lib/private/Files/Node/LazyFolder.php
@@ -25,6 +25,8 @@ declare(strict_types=1);
*/
namespace OC\Files\Node;
+use OCP\Constants;
+
/**
* Class LazyFolder
*
@@ -40,13 +42,16 @@ class LazyFolder implements \OCP\Files\Folder {
/** @var LazyFolder | null */
protected $folder = null;
+ protected array $data;
+
/**
* LazyFolder constructor.
*
* @param \Closure $folderClosure
*/
- public function __construct(\Closure $folderClosure) {
+ public function __construct(\Closure $folderClosure, array $data = []) {
$this->folderClosure = $folderClosure;
+ $this->data = $data;
}
/**
@@ -181,6 +186,9 @@ class LazyFolder implements \OCP\Files\Folder {
* @inheritDoc
*/
public function getPath() {
+ if (isset($this->data['path'])) {
+ return $this->data['path'];
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -230,6 +238,9 @@ class LazyFolder implements \OCP\Files\Folder {
* @inheritDoc
*/
public function getPermissions() {
+ if (isset($this->data['permissions'])) {
+ return $this->data['permissions'];
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -237,6 +248,9 @@ class LazyFolder implements \OCP\Files\Folder {
* @inheritDoc
*/
public function isReadable() {
+ if (isset($this->data['permissions'])) {
+ return ($this->data['permissions'] & Constants::PERMISSION_READ) == Constants::PERMISSION_READ;
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -244,6 +258,9 @@ class LazyFolder implements \OCP\Files\Folder {
* @inheritDoc
*/
public function isUpdateable() {
+ if (isset($this->data['permissions'])) {
+ return ($this->data['permissions'] & Constants::PERMISSION_UPDATE) == Constants::PERMISSION_UPDATE;
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -251,6 +268,9 @@ class LazyFolder implements \OCP\Files\Folder {
* @inheritDoc
*/
public function isDeletable() {
+ if (isset($this->data['permissions'])) {
+ return ($this->data['permissions'] & Constants::PERMISSION_DELETE) == Constants::PERMISSION_DELETE;
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
@@ -258,6 +278,9 @@ class LazyFolder implements \OCP\Files\Folder {
* @inheritDoc
*/
public function isShareable() {
+ if (isset($this->data['permissions'])) {
+ return ($this->data['permissions'] & Constants::PERMISSION_SHARE) == Constants::PERMISSION_SHARE;
+ }
return $this->__call(__FUNCTION__, func_get_args());
}
diff --git a/lib/private/Files/Node/LazyUserFolder.php b/lib/private/Files/Node/LazyUserFolder.php
new file mode 100644
index 00000000000..4c9e89ce233
--- /dev/null
+++ b/lib/private/Files/Node/LazyUserFolder.php
@@ -0,0 +1,56 @@
+<?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\Node;
+
+use OCP\Constants;
+use OCP\Files\IRootFolder;
+use OCP\Files\NotFoundException;
+use OCP\IUser;
+
+class LazyUserFolder extends LazyFolder {
+ private IRootFolder $rootFolder;
+ private IUser $user;
+
+ public function __construct(IRootFolder $rootFolder, IUser $user) {
+ $this->rootFolder = $rootFolder;
+ $this->user = $user;
+ parent::__construct(function () use ($user) {
+ try {
+ return $this->rootFolder->get('/' . $user->getUID() . '/files');
+ } catch (NotFoundException $e) {
+ if (!$this->rootFolder->nodeExists('/' . $user->getUID())) {
+ $this->rootFolder->newFolder('/' . $user->getUID());
+ }
+ return $this->rootFolder->newFolder('/' . $user->getUID() . '/files');
+ }
+ }, [
+ 'path' => '/' . $user->getUID() . '/files',
+ 'permissions' => Constants::PERMISSION_ALL,
+ ]);
+ }
+
+ public function get($path) {
+ return $this->rootFolder->get('/' . $this->user->getUID() . '/files/' . rtrim($path, '/'));
+ }
+}
diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php
index 88ac4a31d34..53162737b6f 100644
--- a/lib/private/Files/Node/Root.php
+++ b/lib/private/Files/Node/Root.php
@@ -380,15 +380,20 @@ class Root extends Folder implements IRootFolder {
$userId = $userObject->getUID();
if (!$this->userFolderCache->hasKey($userId)) {
- \OC\Files\Filesystem::initMountPoints($userId);
-
- try {
- $folder = $this->get('/' . $userId . '/files');
- } catch (NotFoundException $e) {
- if (!$this->nodeExists('/' . $userId)) {
- $this->newFolder('/' . $userId);
+ if ($this->mountManager->getSetupManager()->isSetupComplete($userObject)) {
+ try {
+ $folder = $this->get('/' . $userId . '/files');
+ if (!$folder instanceof \OCP\Files\Folder) {
+ throw new \Exception("User folder for $userId exists as a file");
+ }
+ } catch (NotFoundException $e) {
+ if (!$this->nodeExists('/' . $userId)) {
+ $this->newFolder('/' . $userId);
+ }
+ $folder = $this->newFolder('/' . $userId . '/files');
}
- $folder = $this->newFolder('/' . $userId . '/files');
+ } else {
+ $folder = new LazyUserFolder($this, $userObject);
}
$this->userFolderCache->set($userId, $folder);
diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php
index 9726fbef428..da50983da32 100644
--- a/lib/private/Files/SetupManager.php
+++ b/lib/private/Files/SetupManager.php
@@ -42,14 +42,23 @@ use OCP\Diagnostics\IEventLogger;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IMountProvider;
use OCP\Files\Config\IUserMountCache;
+use OCP\Files\Events\InvalidateMountCacheEvent;
use OCP\Files\Events\Node\FilesystemTornDownEvent;
use OCP\Files\Mount\IMountManager;
use OCP\Files\Mount\IMountPoint;
+use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorage;
+use OCP\Group\Events\UserAddedEvent;
+use OCP\Group\Events\UserRemovedEvent;
+use OCP\ICache;
+use OCP\ICacheFactory;
+use OCP\IConfig;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Lockdown\ILockdownManager;
+use OCP\Share\Events\ShareCreatedEvent;
+use Psr\Log\LoggerInterface;
class SetupManager {
private bool $rootSetup = false;
@@ -57,11 +66,19 @@ class SetupManager {
private MountProviderCollection $mountProviderCollection;
private IMountManager $mountManager;
private IUserManager $userManager;
+ // List of users for which at least one mount is setup
private array $setupUsers = [];
+ // List of users for which all mounts are setup
+ private array $setupUsersComplete = [];
+ /** @var array<string, string[]> */
+ private array $setupUserMountProviders = [];
private IEventDispatcher $eventDispatcher;
private IUserMountCache $userMountCache;
private ILockdownManager $lockdownManager;
private IUserSession $userSession;
+ private ICache $cache;
+ private LoggerInterface $logger;
+ private IConfig $config;
private bool $listeningForProviders;
public function __construct(
@@ -72,7 +89,10 @@ class SetupManager {
IEventDispatcher $eventDispatcher,
IUserMountCache $userMountCache,
ILockdownManager $lockdownManager,
- IUserSession $userSession
+ IUserSession $userSession,
+ ICacheFactory $cacheFactory,
+ LoggerInterface $logger,
+ IConfig $config
) {
$this->eventLogger = $eventLogger;
$this->mountProviderCollection = $mountProviderCollection;
@@ -81,8 +101,21 @@ class SetupManager {
$this->eventDispatcher = $eventDispatcher;
$this->userMountCache = $userMountCache;
$this->lockdownManager = $lockdownManager;
+ $this->logger = $logger;
$this->userSession = $userSession;
+ $this->cache = $cacheFactory->createDistributed('setupmanager::');
$this->listeningForProviders = false;
+ $this->config = $config;
+
+ $this->setupListeners();
+ }
+
+ private function isSetupStarted(IUser $user): bool {
+ return in_array($user->getUID(), $this->setupUsers, true);
+ }
+
+ public function isSetupComplete(IUser $user): bool {
+ return in_array($user->getUID(), $this->setupUsersComplete, true);
}
private function setupBuiltinWrappers() {
@@ -159,15 +192,33 @@ class SetupManager {
* Setup the full filesystem for the specified user
*/
public function setupForUser(IUser $user): void {
- $this->setupRoot();
+ if ($this->isSetupComplete($user)) {
+ return;
+ }
+ $this->setupUsersComplete[] = $user->getUID();
+
+ if (!isset($this->setupUserMountProviders[$user->getUID()])) {
+ $this->setupUserMountProviders[$user->getUID()] = [];
+ }
+ $this->setupForUserWith($user, function () use ($user) {
+ $this->mountProviderCollection->addMountForUser($user, $this->mountManager, function (
+ IMountProvider $provider
+ ) use ($user) {
+ return !in_array(get_class($provider), $this->setupUserMountProviders[$user->getUID()]);
+ });
+ });
+ $this->afterUserFullySetup($user);
+ }
+
+ /**
+ * part of the user setup that is run only once per user
+ */
+ private function oneTimeUserSetup(IUser $user) {
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()]);
@@ -176,7 +227,7 @@ class SetupManager {
$userDir = '/' . $user->getUID() . '/files';
- Filesystem::init($user, $userDir);
+ Filesystem::initInternal($userDir);
if ($this->lockdownManager->canAccessFilesystem()) {
// home mounts are handled separate since we need to ensure this is mounted before we call the other mount providers
@@ -187,13 +238,6 @@ class SetupManager {
$homeMount->getStorage()->mkdir('');
$homeMount->getStorage()->getScanner()->scan('');
}
-
- // Chance to mount for other storages
- $mounts = $this->mountProviderCollection->addMountForUser($user, $this->mountManager);
- $mounts[] = $homeMount;
- $this->userMountCache->registerMounts($user, $mounts);
-
- $this->listenForNewMountProviders();
} else {
$this->mountManager->addMount(new MountPoint(
new NullStorage([]),
@@ -203,9 +247,46 @@ class SetupManager {
new NullStorage([]),
'/' . $user->getUID() . '/files'
));
+ $this->setupUsersComplete[] = $user->getUID();
+ }
+
+ $this->listenForNewMountProviders();
+ }
+
+ /**
+ * Final housekeeping after a user has been fully setup
+ */
+ private function afterUserFullySetup(IUser $user): void {
+ $userRoot = '/' . $user->getUID() . '/';
+ $mounts = $this->mountManager->getAll();
+ $mounts = array_filter($mounts, function (IMountPoint $mount) use ($userRoot) {
+ return strpos($mount->getMountPoint(), $userRoot) === 0;
+ });
+ $this->userMountCache->registerMounts($user, $mounts);
+ }
+
+ /**
+ * @param IUser $user
+ * @param IMountPoint $mounts
+ * @return void
+ * @throws \OCP\HintException
+ * @throws \OC\ServerNotAvailableException
+ */
+ private function setupForUserWith(IUser $user, callable $mountCallback): void {
+ $this->setupRoot();
+
+ if (!$this->isSetupStarted($user)) {
+ $this->oneTimeUserSetup($user);
+ }
+
+ $this->eventLogger->start('setup_fs', 'Setup filesystem');
+
+ if ($this->lockdownManager->canAccessFilesystem()) {
+ $mountCallback();
}
\OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user->getUID()]);
+ $userDir = '/' . $user->getUID() . '/files';
OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user->getUID(), 'user_dir' => $userDir]);
$this->eventLogger->end('setup_fs');
@@ -242,7 +323,7 @@ class SetupManager {
/**
* Set up the filesystem for the specified path
*/
- public function setupForPath(string $path): void {
+ public function setupForPath(string $path, bool $includeChildren = false): void {
if (substr_count($path, '/') < 2) {
if ($user = $this->userSession->getUser()) {
$this->setupForUser($user);
@@ -264,11 +345,81 @@ class SetupManager {
return;
}
- $this->setupForUser($user);
+ if ($this->isSetupComplete($user)) {
+ return;
+ }
+
+ // we perform a "cached" setup only after having done the full setup recently
+ // this is also used to trigger a full setup after handling events that are likely
+ // to change the available mounts
+ $cachedSetup = $this->cache->get($user->getUID());
+ if (!$cachedSetup) {
+ $this->setupForUser($user);
+
+ $cacheDuration = $this->config->getSystemValueInt('fs_mount_cache_duration', 5 * 60);
+ if ($cacheDuration > 0) {
+ $this->cache->set($user->getUID(), true, $cacheDuration);
+ }
+ return;
+ }
+
+ if (!isset($this->setupUserMountProviders[$user->getUID()])) {
+ $this->setupUserMountProviders[$user->getUID()] = [];
+ }
+ $setupProviders = &$this->setupUserMountProviders[$user->getUID()];
+ $currentProviders = [];
+
+ try {
+ $cachedMount = $this->userMountCache->getMountForPath($user, $path);
+ } catch (NotFoundException $e) {
+ $this->setupForUser($user);
+ return;
+ }
+
+ $mounts = [];
+ if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
+ $setupProviders[] = $cachedMount->getMountProvider();
+ $currentProviders[] = $cachedMount->getMountProvider();
+ if ($cachedMount->getMountProvider()) {
+ $mounts = $this->mountProviderCollection->getUserMountsForProviderClass($user, $cachedMount->getMountProvider());
+ } else {
+ $this->logger->debug("mount at " . $cachedMount->getMountPoint() . " has no provider set, performing full setup");
+ $this->setupForUser($user);
+ return;
+ }
+ }
+
+ if ($includeChildren) {
+ $subCachedMounts = $this->userMountCache->getMountsInPath($user, $path);
+ foreach ($subCachedMounts as $cachedMount) {
+ if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
+ $setupProviders[] = $cachedMount->getMountProvider();
+ $currentProviders[] = $cachedMount->getMountProvider();
+ if ($cachedMount->getMountProvider()) {
+ $mounts = array_merge($mounts, $this->mountProviderCollection->getUserMountsForProviderClass($user, $cachedMount->getMountProvider()));
+ } else {
+ $this->logger->debug("mount at " . $cachedMount->getMountPoint() . " has no provider set, performing full setup");
+ $this->setupForUser($user);
+ return;
+ }
+ }
+ }
+ }
+
+ if (count($mounts)) {
+ $this->userMountCache->registerMounts($user, $mounts, $currentProviders);
+ $this->setupForUserWith($user, function () use ($mounts) {
+ array_walk($mounts, [$this->mountManager, 'addMount']);
+ });
+ } elseif (!$this->isSetupStarted($user)) {
+ $this->oneTimeUserSetup($user);
+ }
}
public function tearDown() {
$this->setupUsers = [];
+ $this->setupUsersComplete = [];
+ $this->setupUserMountProviders = [];
$this->rootSetup = false;
$this->mountManager->clear();
$this->eventDispatcher->dispatchTyped(new FilesystemTornDownEvent());
@@ -280,7 +431,9 @@ class SetupManager {
private function listenForNewMountProviders() {
if (!$this->listeningForProviders) {
$this->listeningForProviders = true;
- $this->mountProviderCollection->listen('\OC\Files\Config', 'registerMountProvider', function (IMountProvider $provider) {
+ $this->mountProviderCollection->listen('\OC\Files\Config', 'registerMountProvider', function (
+ IMountProvider $provider
+ ) {
foreach ($this->setupUsers as $userId) {
$user = $this->userManager->get($userId);
if ($user) {
@@ -291,4 +444,40 @@ class SetupManager {
});
}
}
+
+ private function setupListeners() {
+ // note that this event handling is intentionally pessimistic
+ // clearing the cache to often is better than not enough
+
+ $this->eventDispatcher->addListener(UserAddedEvent::class, function (UserAddedEvent $event) {
+ $this->cache->remove($event->getUser()->getUID());
+ });
+ $this->eventDispatcher->addListener(UserRemovedEvent::class, function (UserRemovedEvent $event) {
+ $this->cache->remove($event->getUser()->getUID());
+ });
+ $this->eventDispatcher->addListener(ShareCreatedEvent::class, function (ShareCreatedEvent $event) {
+ $this->cache->remove($event->getShare()->getSharedWith());
+ });
+ $this->eventDispatcher->addListener(InvalidateMountCacheEvent::class, function (InvalidateMountCacheEvent $event
+ ) {
+ if ($user = $event->getUser()) {
+ $this->cache->remove($user->getUID());
+ } else {
+ $this->cache->clear();
+ }
+ });
+
+ $genericEvents = [
+ '\OCA\Circles::onCircleCreation',
+ '\OCA\Circles::onCircleDestruction',
+ '\OCA\Circles::onMemberNew',
+ '\OCA\Circles::onMemberLeaving',
+ ];
+
+ foreach ($genericEvents as $genericEvent) {
+ $this->eventDispatcher->addListener($genericEvent, function ($event) {
+ $this->cache->clear();
+ });
+ }
+ }
}
diff --git a/lib/private/Files/SetupManagerFactory.php b/lib/private/Files/SetupManagerFactory.php
index 56e70d09961..1d9efbd411f 100644
--- a/lib/private/Files/SetupManagerFactory.php
+++ b/lib/private/Files/SetupManagerFactory.php
@@ -28,9 +28,12 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IMountProviderCollection;
use OCP\Files\Config\IUserMountCache;
use OCP\Files\Mount\IMountManager;
+use OCP\ICacheFactory;
+use OCP\IConfig;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Lockdown\ILockdownManager;
+use Psr\Log\LoggerInterface;
class SetupManagerFactory {
private IEventLogger $eventLogger;
@@ -41,6 +44,9 @@ class SetupManagerFactory {
private ILockdownManager $lockdownManager;
private IUserSession $userSession;
private ?SetupManager $setupManager;
+ private ICacheFactory $cacheFactory;
+ private LoggerInterface $logger;
+ private IConfig $config;
public function __construct(
IEventLogger $eventLogger,
@@ -49,7 +55,10 @@ class SetupManagerFactory {
IEventDispatcher $eventDispatcher,
IUserMountCache $userMountCache,
ILockdownManager $lockdownManager,
- IUserSession $userSession
+ IUserSession $userSession,
+ ICacheFactory $cacheFactory,
+ LoggerInterface $logger,
+ IConfig $config
) {
$this->eventLogger = $eventLogger;
$this->mountProviderCollection = $mountProviderCollection;
@@ -58,6 +67,9 @@ class SetupManagerFactory {
$this->userMountCache = $userMountCache;
$this->lockdownManager = $lockdownManager;
$this->userSession = $userSession;
+ $this->cacheFactory = $cacheFactory;
+ $this->logger = $logger;
+ $this->config = $config;
$this->setupManager = null;
}
@@ -72,6 +84,9 @@ class SetupManagerFactory {
$this->userMountCache,
$this->lockdownManager,
$this->userSession,
+ $this->cacheFactory,
+ $this->logger,
+ $this->config
);
}
return $this->setupManager;
diff --git a/lib/public/Files/Config/IMountProviderCollection.php b/lib/public/Files/Config/IMountProviderCollection.php
index f845d72cee6..5894d06a388 100644
--- a/lib/public/Files/Config/IMountProviderCollection.php
+++ b/lib/public/Files/Config/IMountProviderCollection.php
@@ -39,6 +39,16 @@ interface IMountProviderCollection {
public function getMountsForUser(IUser $user);
/**
+ * Get the configured mount points for the user from a specific mount provider
+ *
+ * @param \OCP\IUser $user
+ * @param class-string<IMountProvider> $mountProviderClass
+ * @return \OCP\Files\Mount\IMountPoint[]
+ * @since 24.0.0
+ */
+ public function getUserMountsForProviderClass(IUser $user, string $mountProviderClass);
+
+ /**
* Get the configured home mount for this user
*
* @param \OCP\IUser $user
diff --git a/lib/public/Files/Config/IUserMountCache.php b/lib/public/Files/Config/IUserMountCache.php
index 08f95990d3c..4411200c7ae 100644
--- a/lib/public/Files/Config/IUserMountCache.php
+++ b/lib/public/Files/Config/IUserMountCache.php
@@ -25,6 +25,7 @@
namespace OCP\Files\Config;
use OCP\Files\Mount\IMountPoint;
+use OCP\Files\NotFoundException;
use OCP\IUser;
/**
@@ -38,9 +39,10 @@ interface IUserMountCache {
*
* @param IUser $user
* @param IMountPoint[] $mounts
+ * @param array|null $mountProviderClasses
* @since 9.0.0
*/
- public function registerMounts(IUser $user, array $mounts);
+ public function registerMounts(IUser $user, array $mounts, array $mountProviderClasses = null);
/**
* Get all cached mounts for a user
@@ -125,4 +127,26 @@ interface IUserMountCache {
* @since 20.0.0
*/
public function clear(): void;
+
+ /**
+ * Get all cached mounts for a user
+ *
+ * @param IUser $user
+ * @param string $path
+ * @return ICachedMountInfo
+ * @throws NotFoundException
+ * @since 24.0.0
+ */
+ public function getMountForPath(IUser $user, string $path): ICachedMountInfo;
+
+ /**
+ * Get all cached mounts for a user inside a path
+ *
+ * @param IUser $user
+ * @param string $path
+ * @return ICachedMountInfo[]
+ * @throws NotFoundException
+ * @since 24.0.0
+ */
+ public function getMountsInPath(IUser $user, string $path): array;
}
diff --git a/lib/public/Files/Events/InvalidateMountCacheEvent.php b/lib/public/Files/Events/InvalidateMountCacheEvent.php
new file mode 100644
index 00000000000..6508e168d4c
--- /dev/null
+++ b/lib/public/Files/Events/InvalidateMountCacheEvent.php
@@ -0,0 +1,55 @@
+<?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 OCP\Files\Events;
+
+use OCP\EventDispatcher\Event;
+use OCP\IUser;
+
+/**
+ * Used to notify the filesystem setup manager that the available mounts for a user have changed
+ *
+ * @since 24.0.0
+ */
+class InvalidateMountCacheEvent extends Event {
+ private ?IUser $user;
+
+ /**
+ * @param IUser|null $user user
+ *
+ * @since 24.0.0
+ */
+ public function __construct(?IUser $user) {
+ parent::__construct();
+ $this->user = $user;
+ }
+
+ /**
+ * @return IUser|null user
+ *
+ * @since 24.0.0
+ */
+ public function getUser(): ?IUser {
+ return $this->user;
+ }
+}