aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/files/lib/Service/OwnershipTransferService.php40
-rw-r--r--build/integration/features/bootstrap/CommandLineContext.php8
-rw-r--r--build/integration/features/bootstrap/Provisioning.php22
-rw-r--r--build/integration/features/transfer-ownership.feature314
-rw-r--r--lib/private/Files/Config/UserMountCache.php5
-rw-r--r--lib/public/Files/Config/IUserMountCache.php7
6 files changed, 391 insertions, 5 deletions
diff --git a/apps/files/lib/Service/OwnershipTransferService.php b/apps/files/lib/Service/OwnershipTransferService.php
index f47128a8d9f..8eb031df554 100644
--- a/apps/files/lib/Service/OwnershipTransferService.php
+++ b/apps/files/lib/Service/OwnershipTransferService.php
@@ -32,12 +32,14 @@ use OC\Files\Filesystem;
use OC\Files\View;
use OCA\Files\Exception\TransferOwnershipException;
use OCP\Encryption\IManager as IEncryptionManager;
+use OCP\Files\Config\IUserMountCache;
use OCP\Files\FileInfo;
use OCP\Files\IHomeStorage;
use OCP\Files\InvalidPathException;
use OCP\Files\Mount\IMountManager;
use OCP\IUser;
use OCP\Share\IManager as IShareManager;
+use OCP\Share\IShare;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;
@@ -59,12 +61,17 @@ class OwnershipTransferService {
/** @var IMountManager */
private $mountManager;
+ /** @var IUserMountCache */
+ private $userMountCache;
+
public function __construct(IEncryptionManager $manager,
IShareManager $shareManager,
- IMountManager $mountManager) {
+ IMountManager $mountManager,
+ IUserMountCache $userMountCache) {
$this->encryptionManager = $manager;
$this->shareManager = $shareManager;
$this->mountManager = $mountManager;
+ $this->userMountCache = $userMountCache;
}
/**
@@ -145,7 +152,9 @@ class OwnershipTransferService {
// collect all the shares
$shares = $this->collectUsersShares(
$sourceUid,
- $output
+ $output,
+ $view,
+ $sourcePath
);
// transfer the files
@@ -230,7 +239,9 @@ class OwnershipTransferService {
}
private function collectUsersShares(string $sourceUid,
- OutputInterface $output): array {
+ OutputInterface $output,
+ View $view,
+ string $path): array {
$output->writeln("Collecting all share information for files and folders of $sourceUid ...");
$shares = [];
@@ -243,6 +254,23 @@ class OwnershipTransferService {
if (empty($sharePage)) {
break;
}
+ if ($path !== "$sourceUid/files") {
+ $sharePage = array_filter($sharePage, function (IShare $share) use ($view, $path) {
+ try {
+ $relativePath = $view->getPath($share->getNodeId());
+ $singleFileTranfer = $view->is_file($path);
+ if ($singleFileTranfer) {
+ return Filesystem::normalizePath($relativePath) === Filesystem::normalizePath($path);
+ }
+
+ return mb_strpos(
+ Filesystem::normalizePath($relativePath . '/', false),
+ Filesystem::normalizePath($path . '/', false)) === 0;
+ } catch (\Exception $e) {
+ return false;
+ }
+ });
+ }
$shares = array_merge($shares, $sharePage);
$offset += 50;
}
@@ -303,6 +331,12 @@ class OwnershipTransferService {
$share->setSharedBy($destinationUid);
}
+
+ // trigger refetching of the node so that the new owner and mountpoint are taken into account
+ // otherwise the checks on the share update will fail due to the original node not being available in the new user scope
+ $this->userMountCache->clear();
+ $share->setNodeId($share->getNode()->getId());
+
$this->shareManager->updateShare($share);
}
} catch (\OCP\Files\NotFoundException $e) {
diff --git a/build/integration/features/bootstrap/CommandLineContext.php b/build/integration/features/bootstrap/CommandLineContext.php
index 5bb87c04a94..83d767f53bc 100644
--- a/build/integration/features/bootstrap/CommandLineContext.php
+++ b/build/integration/features/bootstrap/CommandLineContext.php
@@ -25,6 +25,7 @@
require __DIR__ . '/../../vendor/autoload.php';
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
+use PHPUnit\Framework\Assert;
class CommandLineContext implements \Behat\Behat\Context\Context {
use CommandLine;
@@ -127,4 +128,11 @@ class CommandLineContext implements \Behat\Behat\Context\Context {
$davPath = rtrim($davPath, '/') . $this->lastTransferPath;
$this->featureContext->usingDavPath($davPath);
}
+
+ /**
+ * @Then /^transfer folder name contains "([^"]+)"$/
+ */
+ public function transferFolderNameContains($text) {
+ Assert::assertContains($text, $this->lastTransferPath);
+ }
}
diff --git a/build/integration/features/bootstrap/Provisioning.php b/build/integration/features/bootstrap/Provisioning.php
index 4339c9a01af..c3fc21bbc8d 100644
--- a/build/integration/features/bootstrap/Provisioning.php
+++ b/build/integration/features/bootstrap/Provisioning.php
@@ -69,6 +69,23 @@ trait Provisioning {
}
/**
+ * @Given /^user "([^"]*)" with displayname "((?:[^"]|\\")*)" exists$/
+ * @param string $user
+ */
+ public function assureUserWithDisplaynameExists($user, $displayname) {
+ try {
+ $this->userExists($user);
+ } catch (\GuzzleHttp\Exception\ClientException $ex) {
+ $previous_user = $this->currentUser;
+ $this->currentUser = "admin";
+ $this->creatingTheUser($user, $displayname);
+ $this->currentUser = $previous_user;
+ }
+ $this->userExists($user);
+ Assert::assertEquals(200, $this->response->getStatusCode());
+ }
+
+ /**
* @Given /^user "([^"]*)" does not exist$/
* @param string $user
*/
@@ -92,7 +109,7 @@ trait Provisioning {
}
}
- public function creatingTheUser($user) {
+ public function creatingTheUser($user, $displayname = '') {
$fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users";
$client = new Client();
$options = [];
@@ -104,6 +121,9 @@ trait Provisioning {
'userid' => $user,
'password' => '123456'
];
+ if ($displayname !== '') {
+ $options['form_params']['displayName'] = $displayname;
+ }
$options['headers'] = [
'OCS-APIREQUEST' => 'true',
];
diff --git a/build/integration/features/transfer-ownership.feature b/build/integration/features/transfer-ownership.feature
index a0959db6c17..b091d00dae8 100644
--- a/build/integration/features/transfer-ownership.feature
+++ b/build/integration/features/transfer-ownership.feature
@@ -9,6 +9,10 @@ Feature: transfer-ownership
And As an "user1"
And using received transfer folder of "user1" as dav path
Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the file "/somefile.txt" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the file "/somefile.txt" exists
Scenario: transfering ownership of a folder
Given user "user0" exists
@@ -20,6 +24,26 @@ Feature: transfer-ownership
And As an "user1"
And using received transfer folder of "user1" as dav path
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+
+ Scenario: transfering ownership from user with risky display name
+ Given user "user0" with displayname "user0 \"risky\"? ヂspḷay 'na|\/|e':.#" exists
+ And user "user1" exists
+ And User "user0" created a folder "/test"
+ And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt"
+ When transfering ownership from "user0" to "user1"
+ And the command was successful
+ And As an "user1"
+ And using received transfer folder of "user1" as dav path
+ Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And transfer folder name contains "transferred from user0 -risky- ヂspḷay -na|-|e- on"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
Scenario: transfering ownership of file shares
Given user "user0" exists
@@ -32,6 +56,17 @@ Feature: transfer-ownership
And the command was successful
And As an "user2"
Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the file "/somefile.txt" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the file "/somefile.txt" exists
+ And As an "user1"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | user1 |
+ | uid_file_owner | user1 |
+ | share_with | user2 |
Scenario: transfering ownership of folder shared with third user
Given user "user0" exists
@@ -45,6 +80,17 @@ Feature: transfer-ownership
And the command was successful
And As an "user2"
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+ And As an "user1"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | user1 |
+ | uid_file_owner | user1 |
+ | share_with | user2 |
Scenario: transfering ownership of folder shared with transfer recipient
Given user "user0" exists
@@ -59,6 +105,12 @@ Feature: transfer-ownership
Then as "user1" the folder "/test" does not exist
And using received transfer folder of "user1" as dav path
And Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+ And Getting info of last share
+ And the OCS status code should be "404"
Scenario: transfering ownership of folder doubly shared with third user
Given group "group1" exists
@@ -76,6 +128,17 @@ Feature: transfer-ownership
And the command was successful
And As an "user2"
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+ And As an "user1"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | user1 |
+ | uid_file_owner | user1 |
+ | share_with | user2 |
Scenario: transfering ownership of file shares to user with the same id as the group
Given user "user0" exists
@@ -90,6 +153,102 @@ Feature: transfer-ownership
And the command was successful
And As an "user2"
Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the file "/somefile.txt" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "test" the file "/somefile.txt" exists
+ And As an "test"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | test |
+ | uid_file_owner | test |
+ | share_with | test |
+
+ Scenario: transfering ownership of folder reshared with another user
+ Given user "user0" exists
+ And user "user1" exists
+ And user "user2" exists
+ And user "user3" exists
+ And User "user3" created a folder "/test"
+ And User "user3" uploads file "data/textfile.txt" to "/test/somefile.txt"
+ And folder "/test" of user "user3" is shared with user "user0" with permissions 31
+ And user "user0" accepts last share
+ And folder "/test" of user "user0" is shared with user "user2" with permissions 31
+ And user "user2" accepts last share
+ When transfering ownership from "user0" to "user1"
+ And the command was successful
+ And As an "user2"
+ Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" exists
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" does not exist
+ And As an "user0"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | user0 |
+ | uid_file_owner | user3 |
+ | share_with | user2 |
+
+ Scenario: transfering ownership of folder reshared with group to a user in the group
+ Given user "user0" exists
+ And user "user1" exists
+ And user "user2" exists
+ And user "user3" exists
+ And group "group1" exists
+ And user "user1" belongs to group "group1"
+ And User "user3" created a folder "/test"
+ And User "user3" uploads file "data/textfile.txt" to "/test/somefile.txt"
+ And folder "/test" of user "user3" is shared with user "user0" with permissions 31
+ And user "user0" accepts last share
+ And folder "/test" of user "user0" is shared with group "group1" with permissions 31
+ And user "user1" accepts last share
+ When transfering ownership from "user0" to "user1"
+ And the command was successful
+ And As an "user1"
+ Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" exists
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" does not exist
+ And As an "user1"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | user1 |
+ | uid_file_owner | user3 |
+ | share_with | group1 |
+
+ Scenario: transfering ownership of folder reshared with group to a user not in the group
+ Given user "user0" exists
+ And user "user1" exists
+ And user "user2" exists
+ And user "user3" exists
+ And group "group1" exists
+ And user "user2" belongs to group "group1"
+ And User "user3" created a folder "/test"
+ And User "user3" uploads file "data/textfile.txt" to "/test/somefile.txt"
+ And folder "/test" of user "user3" is shared with user "user0" with permissions 31
+ And user "user0" accepts last share
+ And folder "/test" of user "user0" is shared with group "group1" with permissions 31
+ And user "user2" accepts last share
+ When transfering ownership from "user0" to "user1"
+ And the command was successful
+ And As an "user2"
+ Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" exists
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" does not exist
+ And As an "user0"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | user0 |
+ | uid_file_owner | user3 |
+ | share_with | group1 |
Scenario: transfering ownership does not transfer received shares
Given user "user0" exists
@@ -103,6 +262,15 @@ Feature: transfer-ownership
And As an "user1"
And using received transfer folder of "user1" as dav path
Then as "user1" the folder "/test" does not exist
+ And using old dav path
+ And as "user0" the folder "/test" exists
+ And As an "user2"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | user2 |
+ | uid_file_owner | user2 |
+ | share_with | user0 |
@local_storage
Scenario: transfering ownership does not transfer external storage
@@ -138,6 +306,20 @@ Feature: transfer-ownership
Then the command error output contains the text "Unknown target user"
And the command failed with exit code 1
+ Scenario: transfering ownership of a file
+ Given user "user0" exists
+ And user "user1" exists
+ And User "user0" uploads file "data/textfile.txt" to "/somefile.txt"
+ When transfering ownership of path "somefile.txt" from "user0" to "user1"
+ And the command was successful
+ And As an "user1"
+ And using received transfer folder of "user1" as dav path
+ Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the file "/somefile.txt" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the file "/somefile.txt" exists
+
Scenario: transfering ownership of a folder
Given user "user0" exists
And user "user1" exists
@@ -148,6 +330,77 @@ Feature: transfer-ownership
And As an "user1"
And using received transfer folder of "user1" as dav path
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+
+ Scenario: transfering ownership from user with risky display name
+ Given user "user0" with displayname "user0 \"risky\"? ヂspḷay 'na|\/|e':.#" exists
+ And user "user1" exists
+ And User "user0" created a folder "/test"
+ And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt"
+ When transfering ownership of path "test" from "user0" to "user1"
+ And the command was successful
+ And As an "user1"
+ And using received transfer folder of "user1" as dav path
+ Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And transfer folder name contains "transferred from user0 -risky- ヂspḷay -na|-|e- on"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+
+ Scenario: transfering ownership of path does not affect other files
+ Given user "user0" exists
+ And user "user1" exists
+ And User "user0" created a folder "/test"
+ And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt"
+ And User "user0" created a folder "/test2"
+ And User "user0" uploads file "data/textfile.txt" to "/test2/somefile.txt"
+ When transfering ownership of path "test" from "user0" to "user1"
+ And the command was successful
+ And As an "user1"
+ And using received transfer folder of "user1" as dav path
+ Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And as "user0" the folder "/test2" exists
+ And as "user0" the file "/test2/somefile.txt" exists
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+ And as "user1" the folder "/test2" does not exist
+
+ Scenario: transfering ownership of path does not affect other shares
+ Given user "user0" exists
+ And user "user1" exists
+ And User "user0" created a folder "/test"
+ And User "user0" uploads file "data/textfile.txt" to "/test/somefile.txt"
+ And User "user0" created a folder "/test2"
+ And User "user0" uploads file "data/textfile.txt" to "/test2/sharedfile.txt"
+ And file "/test2/sharedfile.txt" of user "user0" is shared with user "user1" with permissions 19
+ And user "user1" accepts last share
+ When transfering ownership of path "test" from "user0" to "user1"
+ And the command was successful
+ And As an "user1"
+ And using received transfer folder of "user1" as dav path
+ Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And as "user0" the folder "/test2" exists
+ And as "user0" the file "/test2/sharedfile.txt" exists
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+ And as "user1" the folder "/test2" does not exist
+ And using old dav path
+ And as "user1" the file "/sharedfile.txt" exists
+ And As an "user1"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | user0 |
+ | uid_file_owner | user0 |
+ | share_with | user1 |
Scenario: transfering ownership of file shares
Given user "user0" exists
@@ -161,6 +414,17 @@ Feature: transfer-ownership
And the command was successful
And As an "user2"
Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+ And As an "user1"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | user1 |
+ | uid_file_owner | user1 |
+ | share_with | user2 |
Scenario: transfering ownership of folder shared with third user
Given user "user0" exists
@@ -174,6 +438,17 @@ Feature: transfer-ownership
And the command was successful
And As an "user2"
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+ And As an "user1"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | user1 |
+ | uid_file_owner | user1 |
+ | share_with | user2 |
Scenario: transfering ownership of folder shared with transfer recipient
Given user "user0" exists
@@ -188,6 +463,12 @@ Feature: transfer-ownership
Then as "user1" the folder "/test" does not exist
And using received transfer folder of "user1" as dav path
And Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+ And Getting info of last share
+ And the OCS status code should be "404"
Scenario: transfering ownership of folder doubly shared with third user
Given group "group1" exists
@@ -205,6 +486,32 @@ Feature: transfer-ownership
And the command was successful
And As an "user2"
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"
+ And using old dav path
+ And as "user0" the folder "/test" does not exist
+ And using received transfer folder of "user1" as dav path
+ And as "user1" the folder "/test" exists
+ And As an "user1"
+ And Getting info of last share
+ And the OCS status code should be "100"
+ And Share fields of last share match with
+ | uid_owner | user1 |
+ | uid_file_owner | user1 |
+ | share_with | user2 |
+
+ Scenario: transfering ownership of path fails for reshares
+ Given user "user0" exists
+ And user "user1" exists
+ And user "user2" exists
+ And user "user3" exists
+ And User "user3" created a folder "/test"
+ And User "user3" uploads file "data/textfile.txt" to "/test/somefile.txt"
+ And folder "/test" of user "user3" is shared with user "user0" with permissions 31
+ And user "user0" accepts last share
+ And folder "/test" of user "user0" is shared with user "user2" with permissions 31
+ And user "user2" accepts last share
+ When transfering ownership of path "test" from "user0" to "user1"
+ Then the command failed with exit code 1
+ And the command error output contains the text "Could not transfer files."
Scenario: transfering ownership does not transfer received shares
Given user "user0" exists
@@ -219,7 +526,12 @@ Feature: transfer-ownership
And the command was successful
And As an "user1"
And using received transfer folder of "user1" as dav path
- Then as "user1" the folder "/sub/test" does not exist
+ Then as "user1" the folder "/sub" exists
+ And as "user1" the folder "/sub/test" does not exist
+ And using old dav path
+ And as "user0" the folder "/sub" does not exist
+ And Getting info of last share
+ And the OCS status code should be "404"
Scenario: transfering ownership does not transfer external storage
Given user "user0" exists
diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php
index 9cf3b43a431..32bfd5a71f3 100644
--- a/lib/private/Files/Config/UserMountCache.php
+++ b/lib/private/Files/Config/UserMountCache.php
@@ -409,4 +409,9 @@ class UserMountCache implements IUserMountCache {
$result->closeCursor();
return $results;
}
+
+ public function clear(): void {
+ $this->cacheInfoCache = new CappedMemoryCache();
+ $this->mountsForUsers = new CappedMemoryCache();
+ }
}
diff --git a/lib/public/Files/Config/IUserMountCache.php b/lib/public/Files/Config/IUserMountCache.php
index 9fca98dc843..fde4898bd39 100644
--- a/lib/public/Files/Config/IUserMountCache.php
+++ b/lib/public/Files/Config/IUserMountCache.php
@@ -117,4 +117,11 @@ interface IUserMountCache {
* @since 13.0.0
*/
public function getUsedSpaceForUsers(array $users);
+
+ /**
+ * Clear all entries from the in-memory cache
+ *
+ * @since 20.0.0
+ */
+ public function clear(): void;
}