Skip to content

Commit d0b8979

Browse files
Merge pull request #3358 from nextcloud/fix/trash/empty-original-location
2 parents 3b251ea + f7d1505 commit d0b8979

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

lib/Trash/TrashBackend.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use OCP\Files\Node;
2424
use OCP\Files\NotFoundException;
2525
use OCP\Files\NotPermittedException;
26+
use OCP\Files\Storage\ISharedStorage;
2627
use OCP\Files\Storage\IStorage;
2728
use OCP\IUser;
2829
use OCP\IUserManager;
@@ -254,7 +255,12 @@ public function moveToTrash(IStorage $storage, string $internalPath): bool {
254255
$result = $trashStorage->moveFromStorage($storage, $internalPath, $targetInternalPath);
255256
}
256257
if ($result) {
257-
$this->trashManager->addTrashItem($folderId, $name, $time, $internalPath, $fileEntry->getId(), $user->getUID());
258+
$originalLocation = $internalPath;
259+
if ($storage->instanceOfStorage(ISharedStorage::class)) {
260+
$originalLocation = $storage->getWrapperStorage()->getUnjailedPath($originalLocation);
261+
}
262+
263+
$this->trashManager->addTrashItem($folderId, $name, $time, $originalLocation, $fileEntry->getId(), $user->getUID());
258264

259265
// some storage backends (object/encryption) can either already move the cache item or cause the target to be scanned
260266
// so we only conditionally do the cache move here

tests/Trash/TrashBackendTest.php

+71
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919
use OCA\GroupFolders\Folder\FolderManager;
2020
use OCA\GroupFolders\Mount\GroupFolderStorage;
2121
use OCA\GroupFolders\Trash\TrashBackend;
22+
use OCP\Constants;
2223
use OCP\Files\Folder;
2324
use OCP\Files\IRootFolder;
2425
use OCP\IUser;
26+
use OCP\Server;
27+
use OCP\Share;
2528
use Test\TestCase;
2629
use Test\Traits\UserTrait;
2730

@@ -213,4 +216,72 @@ public function testHideDeletedTrashItemInDeletedParentFolderAcl(): void {
213216

214217
$this->logout();
215218
}
219+
220+
public function testWrongOriginalLocation(): void {
221+
$shareManager = Server::get(Share\IManager::class);
222+
223+
$userA = $this->createUser('A', 'test');
224+
$userAFolder = Server::get(IRootFolder::class)->getUserFolder('A');
225+
226+
$userB = $this->createUser('B', 'test');
227+
$userBFolder = Server::get(IRootFolder::class)->getUserFolder('B');
228+
229+
$groupBackend = Server::get(Database::class);
230+
$groupBackend->createGroup('C');
231+
$groupBackend->addToGroup('A', 'C');
232+
$groupBackend->addToGroup('B', 'C');
233+
$this->assertCount(2, $groupBackend->usersInGroup('C'));
234+
235+
$groupFolderId = $this->folderManager->createFolder('D');
236+
$this->folderManager->setFolderACL($groupFolderId, true);
237+
$this->folderManager->addApplicableGroup($groupFolderId, 'C');
238+
$this->folderManager->setGroupPermissions($groupFolderId, 'C', Constants::PERMISSION_ALL);
239+
$this->assertInstanceOf(Folder::class, $userAFolder->get('D'));
240+
$this->assertInstanceOf(Folder::class, $userBFolder->get('D'));
241+
242+
$this->loginAsUser('A');
243+
$userAFolder->newFolder('D/E/F');
244+
$userAFolder->newFile('D/E/F/G', 'foo');
245+
246+
$this->ruleManager->saveRule(new Rule(new UserMapping('group', 'C'), $userAFolder->get('D/E')->getId(), Constants::PERMISSION_READ, 0));
247+
$this->ruleManager->saveRule(new Rule(new UserMapping('user', 'A'), $userAFolder->get('D/E')->getId(), Constants::PERMISSION_ALL, Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE | Constants::PERMISSION_CREATE));
248+
$this->ruleManager->saveRule(new Rule(new UserMapping('user', 'A'), $userAFolder->get('D/E/F')->getId(), Constants::PERMISSION_ALL, Constants::PERMISSION_ALL));
249+
250+
$folderShare = $shareManager->newShare();
251+
$folderShare->setShareType(Share\IShare::TYPE_USER);
252+
$folderShare->setSharedWith('B');
253+
$folderShare->setSharedBy('A');
254+
$folderShare->setPermissions(Constants::PERMISSION_ALL);
255+
$folderShare->setNode($userAFolder->get('D/E/F'));
256+
$folderShare = $shareManager->createShare($folderShare);
257+
$this->assertNotEmpty($folderShare->getId());
258+
259+
$fileShare = $shareManager->newShare();
260+
$fileShare->setShareType(Share\IShare::TYPE_USER);
261+
$fileShare->setSharedWith('B');
262+
$fileShare->setSharedBy('A');
263+
$fileShare->setPermissions(19);
264+
$fileShare->setNode($userAFolder->get('D/E/F/G'));
265+
$fileShare = $shareManager->createShare($fileShare);
266+
$this->assertNotEmpty($fileShare->getId());
267+
268+
$this->loginAsUser('B');
269+
$this->assertTrue($userBFolder->get('F/G')->isDeletable());
270+
$userBFolder->get('F/G')->delete();
271+
272+
$this->assertFalse($userAFolder->nodeExists('D/E/F/G'));
273+
274+
$trashedOfUserA = $this->trashBackend->listTrashRoot($userA);
275+
$this->assertCount(1, $trashedOfUserA);
276+
// Ensure original location inside share is correct
277+
$this->assertSame('D/E/F/G', $trashedOfUserA[0]->getOriginalLocation());
278+
279+
$trashedOfUserB = $this->trashBackend->listTrashRoot($userB);
280+
// Deleting share only unshares it, so no trash here
281+
$this->assertCount(0, $trashedOfUserB);
282+
283+
// Restoring to original location works
284+
$this->trashBackend->restoreItem($trashedOfUserA[0]);
285+
$this->assertTrue($userAFolder->nodeExists('D/E/F/G'));
286+
}
216287
}

0 commit comments

Comments
 (0)