Merge pull request #22804 from nextcloud/backport/stable19/22116-22648-22761

[stable19] Fix share transfer of single files and on the transfered node
This commit is contained in:
Roeland Jago Douma 2020-09-28 19:15:12 +02:00 committed by GitHub
commit 164096aa26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 371 additions and 5 deletions

View File

@ -35,12 +35,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;
@ -62,12 +64,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;
}
/**
@ -148,7 +155,9 @@ class OwnershipTransferService {
// collect all the shares
$shares = $this->collectUsersShares(
$sourceUid,
$output
$output,
$view,
$sourcePath
);
// transfer the files
@ -233,7 +242,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 = [];
@ -246,6 +257,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;
}
@ -306,6 +334,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) {

View File

@ -26,6 +26,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;
@ -128,4 +129,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);
}
}

View File

@ -70,7 +70,7 @@ trait Provisioning {
}
/**
* @Given /^user "([^"]*)" with displayname "([^"]*)" exists$/
* @Given /^user "([^"]*)" with displayname "((?:[^"]|\\")*)" exists$/
* @param string $user
*/
public function assureUserWithDisplaynameExists($user, $displayname) {

View File

@ -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\"? spay '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- spay -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\"? spay '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- spay -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

View File

@ -409,4 +409,9 @@ class UserMountCache implements IUserMountCache {
$result->closeCursor();
return $results;
}
public function clear(): void {
$this->cacheInfoCache = new CappedMemoryCache();
$this->mountsForUsers = new CappedMemoryCache();
}
}

View File

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