diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index baa0c4cbe7..853bc1eda6 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -175,6 +175,10 @@ class Trashbin { } self::setUpTrash($user); + if ($owner !== $user) { + // also setup for owner + self::setUpTrash($owner); + } $path_parts = pathinfo($file_path); @@ -222,7 +226,7 @@ class Trashbin { \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', array('filePath' => \OC\Files\Filesystem::normalizePath($file_path), 'trashPath' => \OC\Files\Filesystem::normalizePath($filename . '.d' . $timestamp))); - $size += self::retainVersions($file_path, $filename, $timestamp); + $size += self::retainVersions($file_path, $filename, $owner, $ownerPath, $timestamp); // if owner !== user we need to also add a copy to the owners trash if ($user !== $owner) { @@ -248,23 +252,19 @@ class Trashbin { * * @param string $file_path path to original file * @param string $filename of deleted file + * @param string $owner owner user id + * @param string $ownerPath path relative to the owner's home storage * @param integer $timestamp when the file was deleted * * @return int size of stored versions */ - private static function retainVersions($file_path, $filename, $timestamp) { + private static function retainVersions($file_path, $filename, $owner, $ownerPath, $timestamp) { $size = 0; - if (\OCP\App::isEnabled('files_versions')) { + if (\OCP\App::isEnabled('files_versions') && !empty($ownerPath)) { $user = \OCP\User::getUser(); $rootView = new \OC\Files\View('/'); - list($owner, $ownerPath) = self::getUidAndFilename($file_path); - // file has been deleted in between - if (empty($ownerPath)) { - return 0; - } - if ($rootView->is_dir($owner . '/files_versions/' . $ownerPath)) { $size += self::calculateSize(new \OC\Files\View('/' . $owner . '/files_versions/' . $ownerPath)); if ($owner !== $user) { diff --git a/apps/files_trashbin/tests/storage.php b/apps/files_trashbin/tests/storage.php index f99bc91dd2..637543683d 100644 --- a/apps/files_trashbin/tests/storage.php +++ b/apps/files_trashbin/tests/storage.php @@ -192,6 +192,10 @@ class Storage extends \Test\TestCase { $this->assertEquals(1, count($results)); $name = $results[0]->getName(); $this->assertEquals('test.txt.v', substr($name, 0, strlen('test.txt.v'))); + + // versions deleted + $results = $this->rootView->getDirectoryContent($this->user . '/files_versions/'); + $this->assertEquals(0, count($results)); } /** @@ -223,6 +227,118 @@ class Storage extends \Test\TestCase { $this->assertEquals(1, count($results)); $name = $results[0]->getName(); $this->assertEquals('inside.txt.v', substr($name, 0, strlen('inside.txt.v'))); + + // versions deleted + $results = $this->rootView->getDirectoryContent($this->user . '/files_versions/folder/'); + $this->assertEquals(0, count($results)); + } + + /** + * Test that deleted versions properly land in the trashbin when deleting as share recipient. + */ + public function testDeleteVersionsOfFileAsRecipient() { + \OCA\Files_Versions\Hooks::connectHooks(); + + $this->userView->mkdir('share'); + // trigger a version (multiple would not work because of the expire logic) + $this->userView->file_put_contents('share/test.txt', 'v1'); + $this->userView->file_put_contents('share/test.txt', 'v2'); + + $results = $this->rootView->getDirectoryContent($this->user . '/files_versions/share/'); + $this->assertEquals(1, count($results)); + + $recipientUser = $this->getUniqueId('recipient_'); + \OC::$server->getUserManager()->createUser($recipientUser, $recipientUser); + + $fileinfo = $this->userView->getFileInfo('share'); + $this->assertTrue(\OCP\Share::shareItem('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER, + $recipientUser, 31)); + + $this->loginAsUser($recipientUser); + + // delete as recipient + $recipientView = new \OC\Files\View('/' . $recipientUser . '/files'); + $recipientView->unlink('share/test.txt'); + + // rescan trash storage for both users + list($rootStorage,) = $this->rootView->resolvePath($this->user . '/files_trashbin'); + $rootStorage->getScanner()->scan(''); + + // check if versions are in trashbin for both users + $results = $this->rootView->getDirectoryContent($this->user . '/files_trashbin/versions'); + $this->assertEquals(1, count($results), 'Versions in owner\'s trashbin'); + $name = $results[0]->getName(); + $this->assertEquals('test.txt.v', substr($name, 0, strlen('test.txt.v'))); + + $results = $this->rootView->getDirectoryContent($recipientUser . '/files_trashbin/versions'); + $this->assertEquals(1, count($results), 'Versions in recipient\'s trashbin'); + $name = $results[0]->getName(); + $this->assertEquals('test.txt.v', substr($name, 0, strlen('test.txt.v'))); + + // versions deleted + $results = $this->rootView->getDirectoryContent($this->user . '/files_versions/share/'); + $this->assertEquals(0, count($results)); + } + + /** + * Test that deleted versions properly land in the trashbin when deleting as share recipient. + */ + public function testDeleteVersionsOfFolderAsRecipient() { + \OCA\Files_Versions\Hooks::connectHooks(); + + $this->userView->mkdir('share'); + $this->userView->mkdir('share/folder'); + // trigger a version (multiple would not work because of the expire logic) + $this->userView->file_put_contents('share/folder/test.txt', 'v1'); + $this->userView->file_put_contents('share/folder/test.txt', 'v2'); + + $results = $this->rootView->getDirectoryContent($this->user . '/files_versions/share/folder/'); + $this->assertEquals(1, count($results)); + + $recipientUser = $this->getUniqueId('recipient_'); + \OC::$server->getUserManager()->createUser($recipientUser, $recipientUser); + + $fileinfo = $this->userView->getFileInfo('share'); + $this->assertTrue(\OCP\Share::shareItem('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER, + $recipientUser, 31)); + + $this->loginAsUser($recipientUser); + + // delete as recipient + $recipientView = new \OC\Files\View('/' . $recipientUser . '/files'); + $recipientView->rmdir('share/folder'); + + // rescan trash storage + list($rootStorage,) = $this->rootView->resolvePath($this->user . '/files_trashbin'); + $rootStorage->getScanner()->scan(''); + + // check if versions are in trashbin for owner + $results = $this->rootView->getDirectoryContent($this->user . '/files_trashbin/versions'); + $this->assertEquals(1, count($results)); + $name = $results[0]->getName(); + $this->assertEquals('folder.d', substr($name, 0, strlen('folder.d'))); + + // check if file versions are in trashbin for owner + $results = $this->rootView->getDirectoryContent($this->user . '/files_trashbin/versions/' . $name . '/'); + $this->assertEquals(1, count($results)); + $name = $results[0]->getName(); + $this->assertEquals('test.txt.v', substr($name, 0, strlen('test.txt.v'))); + + // check if versions are in trashbin for recipient + $results = $this->rootView->getDirectoryContent($recipientUser . '/files_trashbin/versions'); + $this->assertEquals(1, count($results)); + $name = $results[0]->getName(); + $this->assertEquals('folder.d', substr($name, 0, strlen('folder.d'))); + + // check if file versions are in trashbin for recipient + $results = $this->rootView->getDirectoryContent($recipientUser . '/files_trashbin/versions/' . $name . '/'); + $this->assertEquals(1, count($results)); + $name = $results[0]->getName(); + $this->assertEquals('test.txt.v', substr($name, 0, strlen('test.txt.v'))); + + // versions deleted + $results = $this->rootView->getDirectoryContent($recipientUser . '/files_versions/share/folder/'); + $this->assertEquals(0, count($results)); } /**