diff options
Diffstat (limited to 'apps/files_sharing')
-rw-r--r-- | apps/files_sharing/api/local.php | 43 | ||||
-rw-r--r-- | apps/files_sharing/appinfo/app.php | 4 | ||||
-rw-r--r-- | apps/files_sharing/js/settings-admin.js | 1 | ||||
-rw-r--r-- | apps/files_sharing/lib/deleteorphanedsharesjob.php | 59 | ||||
-rw-r--r-- | apps/files_sharing/lib/helper.php | 1 | ||||
-rw-r--r-- | apps/files_sharing/lib/updater.php | 35 | ||||
-rw-r--r-- | apps/files_sharing/templates/settings-admin.php | 3 | ||||
-rw-r--r-- | apps/files_sharing/tests/deleteorphanedsharesjobtest.php | 162 |
8 files changed, 238 insertions, 70 deletions
diff --git a/apps/files_sharing/api/local.php b/apps/files_sharing/api/local.php index 571982d153b..1a5edbfd070 100644 --- a/apps/files_sharing/api/local.php +++ b/apps/files_sharing/api/local.php @@ -343,7 +343,7 @@ class Local { if(isset($params['_put']['permissions'])) { return self::updatePermissions($share, $params); } elseif (isset($params['_put']['password'])) { - return self::updatePassword($share, $params); + return self::updatePassword($params['id'], (int)$share['share_type'], $params['_put']['password']); } elseif (isset($params['_put']['publicUpload'])) { return self::updatePublicUpload($share, $params); } elseif (isset($params['_put']['expireDate'])) { @@ -457,47 +457,22 @@ class Local { /** * update password for public link share - * @param array $share information about the share - * @param array $params 'password' + * @param int $shareId + * @param int $shareType + * @param string $password * @return \OC_OCS_Result */ - private static function updatePassword($share, $params) { - - $itemSource = $share['item_source']; - $itemType = $share['item_type']; - - if( (int)$share['share_type'] !== \OCP\Share::SHARE_TYPE_LINK) { + private static function updatePassword($shareId, $shareType, $password) { + if($shareType !== \OCP\Share::SHARE_TYPE_LINK) { return new \OC_OCS_Result(null, 400, "password protection is only supported for public shares"); } - $shareWith = isset($params['_put']['password']) ? $params['_put']['password'] : null; - - if($shareWith === '') { - $shareWith = null; - } - - $items = \OCP\Share::getItemShared($itemType, $itemSource); - - $checkExists = false; - foreach ($items as $item) { - if($item['share_type'] === \OCP\Share::SHARE_TYPE_LINK) { - $checkExists = true; - $permissions = $item['permissions']; - } - } - - if (!$checkExists) { - return new \OC_OCS_Result(null, 404, "share doesn't exists, can't change password"); + if($password === '') { + $password = null; } try { - $result = \OCP\Share::shareItem( - $itemType, - $itemSource, - \OCP\Share::SHARE_TYPE_LINK, - $shareWith, - $permissions - ); + $result = \OCP\Share::setPassword($shareId, $password); } catch (\Exception $e) { return new \OC_OCS_Result(null, 403, $e->getMessage()); } diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index a222973fc34..d009fbca3b9 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -51,6 +51,10 @@ OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file'); OCP\Util::addScript('files_sharing', 'share'); OCP\Util::addScript('files_sharing', 'external'); +// FIXME: registering a job here will cause additional useless SQL queries +// when the route is not cron.php, needs a better way +\OC::$server->getJobList()->add('OCA\Files_sharing\Lib\DeleteOrphanedSharesJob'); + \OC::$server->getActivityManager()->registerExtension(function() { return new \OCA\Files_Sharing\Activity( \OC::$server->query('L10NFactory'), diff --git a/apps/files_sharing/js/settings-admin.js b/apps/files_sharing/js/settings-admin.js index 257c864b04f..95578bff548 100644 --- a/apps/files_sharing/js/settings-admin.js +++ b/apps/files_sharing/js/settings-admin.js @@ -8,4 +8,5 @@ $(document).ready(function() { OC.AppConfig.setValue('files_sharing', $(this).attr('name'), value); }); + $('.section .icon-info').tipsy({gravity: 'w'}); }); diff --git a/apps/files_sharing/lib/deleteorphanedsharesjob.php b/apps/files_sharing/lib/deleteorphanedsharesjob.php new file mode 100644 index 00000000000..f39078b778f --- /dev/null +++ b/apps/files_sharing/lib/deleteorphanedsharesjob.php @@ -0,0 +1,59 @@ +<?php +/** + * @author Morris Jobke <hey@morrisjobke.de> + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\Files_sharing\Lib; + +use Doctrine\DBAL\Platforms\SqlitePlatform; +use OCP\IDBConnection; +use OC\BackgroundJob\TimedJob; + +/** + * Delete all share entries that have no matching entries in the file cache table. + */ +class DeleteOrphanedSharesJob extends TimedJob { + + /** + * Default interval in minutes + * + * @var int $defaultIntervalMin + **/ + protected $defaultIntervalMin = 15; + + /** + * Makes the background job do its work + * + * @param array $argument unused argument + */ + public function run($argument) { + $connection = \OC::$server->getDatabaseConnection(); + $logger = \OC::$server->getLogger(); + + $sql = + 'DELETE FROM `*PREFIX*share` ' . + 'WHERE `item_type` in (\'file\', \'folder\') ' . + 'AND NOT EXISTS (SELECT `fileid` FROM `*PREFIX*filecache` WHERE `file_source` = `fileid`)'; + + $deletedEntries = $connection->executeUpdate($sql); + $logger->info("$deletedEntries orphaned share(s) deleted", ['app' => 'DeleteOrphanedSharesJob']); + } + +} diff --git a/apps/files_sharing/lib/helper.php b/apps/files_sharing/lib/helper.php index 3f1de7233ae..5b5525e244f 100644 --- a/apps/files_sharing/lib/helper.php +++ b/apps/files_sharing/lib/helper.php @@ -33,7 +33,6 @@ class Helper { \OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup'); \OCP\Util::connectHook('OC_Filesystem', 'setup', '\OCA\Files_Sharing\External\Manager', 'setup'); \OCP\Util::connectHook('OC_Filesystem', 'post_write', '\OC\Files\Cache\Shared_Updater', 'writeHook'); - \OCP\Util::connectHook('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Shared_Updater', 'postDeleteHook'); \OCP\Util::connectHook('OC_Filesystem', 'delete', '\OC\Files\Cache\Shared_Updater', 'deleteHook'); \OCP\Util::connectHook('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Shared_Updater', 'renameHook'); \OCP\Util::connectHook('OC_Filesystem', 'post_delete', '\OCA\Files_Sharing\Hooks', 'unshareChildren'); diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php index d748d5555f6..322c031f2f1 100644 --- a/apps/files_sharing/lib/updater.php +++ b/apps/files_sharing/lib/updater.php @@ -27,9 +27,6 @@ namespace OC\Files\Cache; class Shared_Updater { - // shares which can be removed from oc_share after the delete operation was successful - static private $toRemove = array(); - /** * walk up the users file tree and update the etags * @param string $user @@ -82,25 +79,6 @@ class Shared_Updater { } /** - * remove all shares for a given file if the file was deleted - * - * @param string $path - */ - private static function removeShare($path) { - $fileSource = self::$toRemove[$path]; - - if (!\OC\Files\Filesystem::file_exists($path)) { - $query = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `file_source`=?'); - try { - \OC_DB::executeAudited($query, array($fileSource)); - } catch (\Exception $e) { - \OCP\Util::writeLog('files_sharing', "can't remove share: " . $e->getMessage(), \OCP\Util::WARN); - } - } - unset(self::$toRemove[$path]); - } - - /** * @param array $params */ static public function writeHook($params) { @@ -122,19 +100,6 @@ class Shared_Updater { static public function deleteHook($params) { $path = $params['path']; self::correctFolders($path); - - $fileInfo = \OC\Files\Filesystem::getFileInfo($path); - - // mark file as deleted so that we can clean up the share table if - // the file was deleted successfully - self::$toRemove[$path] = $fileInfo['fileid']; - } - - /** - * @param array $params - */ - static public function postDeleteHook($params) { - self::removeShare($params['path']); } /** diff --git a/apps/files_sharing/templates/settings-admin.php b/apps/files_sharing/templates/settings-admin.php index bd803517597..376f2b71aee 100644 --- a/apps/files_sharing/templates/settings-admin.php +++ b/apps/files_sharing/templates/settings-admin.php @@ -4,6 +4,9 @@ ?> <div id="fileSharingSettings"> <h3><?php p($l->t('Federated Cloud Sharing'));?></h3> + <a target="_blank" class="icon-info svg" + title="<?php p($l->t('Open documentation'));?>" + href="<?php p(link_to_docs('admin-sharing-federated')); ?>"></a> <p> <input type="checkbox" name="outgoing_server2server_share_enabled" id="outgoingServer2serverShareEnabled" diff --git a/apps/files_sharing/tests/deleteorphanedsharesjobtest.php b/apps/files_sharing/tests/deleteorphanedsharesjobtest.php new file mode 100644 index 00000000000..20f3bcd5ebd --- /dev/null +++ b/apps/files_sharing/tests/deleteorphanedsharesjobtest.php @@ -0,0 +1,162 @@ +<?php +/** + * @author Morris Jobke <hey@morrisjobke.de> + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace Test\BackgroundJob; + +use OCA\Files_sharing\Lib\DeleteOrphanedSharesJob; + +class DeleteOrphanedSharesJobTest extends \Test\TestCase { + + /** + * @var bool + */ + private static $trashBinStatus; + + /** + * @var DeleteOrphanedSharesJob + */ + private $job; + + /** + * @var \OCP\IDBConnection + */ + private $connection; + + /** + * @var string + */ + private $user1; + + /** + * @var string + */ + private $user2; + + public static function setUpBeforeClass() { + $appManager = \OC::$server->getAppManager(); + self::$trashBinStatus = $appManager->isEnabledForUser('files_trashbin'); + $appManager->disableApp('files_trashbin'); + + // just in case... + \OC\Files\Filesystem::getLoader()->removeStorageWrapper('oc_trashbin'); + } + + public static function tearDownAfterClass() { + if (self::$trashBinStatus) { + \OC::$server->getAppManager()->enableApp('files_trashbin'); + } + } + + protected function setup() { + parent::setUp(); + + $this->connection = \OC::$server->getDatabaseConnection(); + + $this->user1 = $this->getUniqueID('user1_'); + $this->user2 = $this->getUniqueID('user2_'); + + $userManager = \OC::$server->getUserManager(); + $userManager->createUser($this->user1, 'pass'); + $userManager->createUser($this->user2, 'pass'); + + \OC::registerShareHooks(); + + $this->job = new DeleteOrphanedSharesJob(); + } + + protected function tearDown() { + $this->connection->executeUpdate('DELETE FROM `*PREFIX*share` WHERE `item_type` in (\'file\', \'folder\')'); + + $userManager = \OC::$server->getUserManager(); + $user1 = $userManager->get($this->user1); + if($user1) { + $user1->delete(); + } + $user2 = $userManager->get($this->user2); + if($user2) { + $user2->delete(); + } + + $this->logout(); + + parent::tearDown(); + } + + private function getShares() { + $shares = []; + $result = $this->connection->executeQuery('SELECT * FROM `*PREFIX*share`'); + while ($row = $result->fetch()) { + $shares[] = $row; + } + $result->closeCursor(); + return $shares; + } + + /** + * Test clearing orphaned shares + */ + public function testClearShares() { + $this->loginAsUser($this->user1); + + $view = new \OC\Files\View('/' . $this->user1 . '/'); + $view->mkdir('files/test'); + $view->mkdir('files/test/sub'); + + $fileInfo = $view->getFileInfo('files/test/sub'); + $fileId = $fileInfo->getId(); + + $this->assertTrue( + \OCP\Share::shareItem('folder', $fileId, \OCP\Share::SHARE_TYPE_USER, $this->user2, \OCP\Constants::PERMISSION_READ), + 'Failed asserting that user 1 successfully shared "test/sub" with user 2.' + ); + + $this->assertCount(1, $this->getShares()); + + $this->job->run([]); + + $this->assertCount(1, $this->getShares(), 'Linked shares not deleted'); + + $view->unlink('files/test'); + + $this->job->run([]); + + $this->assertCount(0, $this->getShares(), 'Orphaned shares deleted'); + } + + public function testKeepNonFileShares() { + $this->loginAsUser($this->user1); + + \OCP\Share::registerBackend('test', 'Test_Share_Backend'); + + $this->assertTrue( + \OCP\Share::shareItem('test', 'test.txt', \OCP\Share::SHARE_TYPE_USER, $this->user2, \OCP\Constants::PERMISSION_READ), + 'Failed asserting that user 1 successfully shared something with user 2.' + ); + + $this->assertCount(1, $this->getShares()); + + $this->job->run([]); + + $this->assertCount(1, $this->getShares(), 'Non-file shares kept'); + } +} + |