From ec296b0b7df7996419204a51d2e2643a1936d41e Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Wed, 7 Oct 2015 21:05:44 +0200 Subject: [PATCH] Add backgroundjob to expire link shares Simple background job to expire the link shares. * added unit tests --- apps/files_sharing/appinfo/info.xml | 2 +- apps/files_sharing/appinfo/install.php | 1 + apps/files_sharing/appinfo/update.php | 1 + apps/files_sharing/lib/expiresharesjob.php | 76 +++++++ .../tests/expiresharesjobtest.php | 204 ++++++++++++++++++ 5 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 apps/files_sharing/lib/expiresharesjob.php create mode 100644 apps/files_sharing/tests/expiresharesjobtest.php diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml index 80925dd3d6..72e5645696 100644 --- a/apps/files_sharing/appinfo/info.xml +++ b/apps/files_sharing/appinfo/info.xml @@ -11,7 +11,7 @@ Turning the feature off removes shared files and folders on the server for all s Michael Gapczynski, Bjoern Schiessle true - 0.8.0 + 0.8.1 diff --git a/apps/files_sharing/appinfo/install.php b/apps/files_sharing/appinfo/install.php index f076a17e44..605aaed933 100644 --- a/apps/files_sharing/appinfo/install.php +++ b/apps/files_sharing/appinfo/install.php @@ -20,3 +20,4 @@ */ \OC::$server->getJobList()->add('OCA\Files_sharing\Lib\DeleteOrphanedSharesJob'); +\OC::$server->getJobList()->add('OCA\Files_sharing\Lib\ExpireSharesJob'); diff --git a/apps/files_sharing/appinfo/update.php b/apps/files_sharing/appinfo/update.php index 0eb3224c1c..02b9873dff 100644 --- a/apps/files_sharing/appinfo/update.php +++ b/apps/files_sharing/appinfo/update.php @@ -30,3 +30,4 @@ if (version_compare($installedVersion, '0.6.0', '<')) { } \OC::$server->getJobList()->add('OCA\Files_sharing\Lib\DeleteOrphanedSharesJob'); +\OC::$server->getJobList()->add('OCA\Files_sharing\Lib\ExpireSharesJob'); diff --git a/apps/files_sharing/lib/expiresharesjob.php b/apps/files_sharing/lib/expiresharesjob.php new file mode 100644 index 0000000000..bcd3fbe460 --- /dev/null +++ b/apps/files_sharing/lib/expiresharesjob.php @@ -0,0 +1,76 @@ + + * + * @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 + * + */ + +namespace OCA\Files_Sharing; + +use OC\BackgroundJob\TimedJob; + +/** + * Delete all shares that are expired + */ +class ExpireSharesJob extends TimedJob { + + /** + * sets the correct interval for this timed job + */ + public function __construct() { + // Run once a day + $this->setInterval(24 * 60 * 60); + } + + /** + * Makes the background job do its work + * + * @param array $argument unused argument + */ + public function run($argument) { + $connection = \OC::$server->getDatabaseConnection(); + $logger = \OC::$server->getLogger(); + + //Current time + $now = new \DateTime(); + $now = $now->format('Y-m-d H:i:s'); + + /* + * Expire file link shares only (for now) + */ + $qb = $connection->getQueryBuilder(); + $qb->select('id', 'file_source', 'uid_owner', 'item_type') + ->from('share') + ->where( + $qb->expr()->andX( + $qb->expr()->eq('share_type', $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK)), + $qb->expr()->lte('expiration', $qb->expr()->literal($now)), + $qb->expr()->orX( + $qb->expr()->eq('item_type', $qb->expr()->literal('file')), + $qb->expr()->eq('item_type', $qb->expr()->literal('folder')) + ) + ) + ); + + $shares = $qb->execute(); + while($share = $shares->fetch()) { + \OCP\Share::unshare($share['item_type'], $share['file_source'], \OCP\Share::SHARE_TYPE_LINK, null, $share['uid_owner']); + } + $shares->closeCursor(); + } + +} diff --git a/apps/files_sharing/tests/expiresharesjobtest.php b/apps/files_sharing/tests/expiresharesjobtest.php new file mode 100644 index 0000000000..90da4011d8 --- /dev/null +++ b/apps/files_sharing/tests/expiresharesjobtest.php @@ -0,0 +1,204 @@ + + * + * @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 + * + */ + +namespace OCA\Files_Sharing\Tests; + +use OCA\Files_Sharing\ExpireSharesJob; + +class ExpireSharesJobTest extends \Test\TestCase { + + /** + * @var ExpireSharesJob + */ + private $job; + + /** + * @var \OCP\IDBConnection + */ + private $connection; + + /** + * @var string + */ + private $user1; + + /** + * @var string + */ + private $user2; + + protected function setup() { + parent::setUp(); + + $this->connection = \OC::$server->getDatabaseConnection(); + // clear occasional leftover shares from other tests + $this->connection->executeUpdate('DELETE FROM `*PREFIX*share`'); + + $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 ExpireSharesJob(); + } + + protected function tearDown() { + $this->connection->executeUpdate('DELETE FROM `*PREFIX*share`'); + + $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 = []; + $qb = $this->connection->getQueryBuilder(); + + $result = $qb->select('*') + ->from('share') + ->execute(); + + while ($row = $result->fetch()) { + $shares[] = $row; + } + $result->closeCursor(); + return $shares; + } + + public function dataExpireLinkShare() { + return [ + [false, '', false, false], + [false, '', true, false], + [true, 'P1D', false, true], + [true, 'P1D', true, false], + [true, 'P1W', false, true], + [true, 'P1W', true, false], + [true, 'P1M', false, true], + [true, 'P1M', true, false], + [true, 'P1Y', false, true], + [true, 'P1Y', true, false], + ]; + } + + /** + * @dataProvider dataExpireLinkShare + * + * @param bool addExpiration Should we add an expire date + * @param string $interval The dateInterval + * @param bool $addInterval If true add to the current time if false subtract + * @param bool $shouldExpire Should this share be expired + */ + public function testExpireLinkShare($addExpiration, $interval, $addInterval, $shouldExpire) { + $this->loginAsUser($this->user1); + + $view = new \OC\Files\View('/' . $this->user1 . '/'); + $view->mkdir('files/test'); + + $fileInfo = $view->getFileInfo('files/test'); + + $this->assertNotNull( + \OCP\Share::shareItem('folder', $fileInfo->getId(), \OCP\Share::SHARE_TYPE_LINK, null, \OCP\Constants::PERMISSION_READ), + 'Failed asserting that user 1 successfully shared "test" by link.' + ); + + $shares = $this->getShares(); + $this->assertCount(1, $shares); + reset($shares); + $share = current($shares); + + if ($addExpiration) { + $expire = new \DateTime(); + $expire->setTime(0, 0, 0); + if ($addInterval) { + $expire->add(new \DateInterval($interval)); + } else { + $expire->sub(new \DateInterval($interval)); + } + $expire = $expire->format('Y-m-d 00:00:00'); + + // Set expiration date to yesterday + $qb = $this->connection->getQueryBuilder(); + $qb->update('share') + ->set('expiration', $qb->createParameter('expiration')) + ->where($qb->expr()->eq('id', $qb->createParameter('id'))) + ->setParameter('id', $share['id']) + ->setParameter('expiration', $expire) + ->execute(); + + $shares = $this->getShares(); + $this->assertCount(1, $shares); + } + + $this->logout(); + + $this->job->run([]); + + $shares = $this->getShares(); + + if ($shouldExpire) { + $this->assertCount(0, $shares); + } else { + $this->assertCount(1, $shares); + } + } + + public function testDoNotExpireOtherShares() { + $this->loginAsUser($this->user1); + + $view = new \OC\Files\View('/' . $this->user1 . '/'); + $view->mkdir('files/test'); + + $fileInfo = $view->getFileInfo('files/test'); + + $this->assertNotNull( + \OCP\Share::shareItem('folder', $fileInfo->getId(), \OCP\Share::SHARE_TYPE_USER, $this->user2, \OCP\Constants::PERMISSION_READ), + 'Failed asserting that user 1 successfully shared "test" by link with user2.' + ); + + $shares = $this->getShares(); + $this->assertCount(1, $shares); + reset($shares); + $share = current($shares); + + $this->logout(); + + $this->job->run([]); + + $shares = $this->getShares(); + $this->assertCount(1, $shares); + } + +} +