From b13e46948799ecd36a031f1095063ef68b191565 Mon Sep 17 00:00:00 2001 From: VicDeo Date: Tue, 26 Mar 2019 17:40:13 +0100 Subject: [PATCH] Add a command to check federated share updates --- apps/federatedfilesharing/appinfo/info.xml | 3 + .../lib/Command/SyncIncomingShares.php | 132 ++++++++++++++++++ .../tests/Command/SyncIncomingSharesTest.php | 72 ++++++++++ 3 files changed, 207 insertions(+) create mode 100644 apps/federatedfilesharing/lib/Command/SyncIncomingShares.php create mode 100644 apps/federatedfilesharing/tests/Command/SyncIncomingSharesTest.php diff --git a/apps/federatedfilesharing/appinfo/info.xml b/apps/federatedfilesharing/appinfo/info.xml index e4f7777cf249..c52841e21e2a 100644 --- a/apps/federatedfilesharing/appinfo/info.xml +++ b/apps/federatedfilesharing/appinfo/info.xml @@ -20,4 +20,7 @@ OCA\FederatedFileSharing\Panels\GeneralPersonalPanel OCA\FederatedFileSharing\Panels\SharingPersonalPanel + + OCA\FederatedFileSharing\Command\SyncIncomingShares + diff --git a/apps/federatedfilesharing/lib/Command/SyncIncomingShares.php b/apps/federatedfilesharing/lib/Command/SyncIncomingShares.php new file mode 100644 index 000000000000..71d4baab7262 --- /dev/null +++ b/apps/federatedfilesharing/lib/Command/SyncIncomingShares.php @@ -0,0 +1,132 @@ + + * + * @copyright Copyright (c) 2019, ownCloud GmbH + * @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\FederatedFileSharing\Command; + +use OC\ServerNotAvailableException; +use OCA\Files_Sharing\AppInfo\Application; +use OCP\Files\Storage\IStorage; +use OCP\Files\StorageInvalidException; +use OCP\Files\StorageNotAvailableException; +use OCP\IDBConnection; +use OCP\IUserManager; +use OCP\Lock\LockedException; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class SyncIncomingShares extends Command { + /** @var IDBConnection */ + private $dbConnection; + + /** @var IUserManager */ + private $userManager; + + /** + * SyncIncomingShares constructor. + * + * @param IDBConnection $dbConnection + * @param IUserManager $userManager + */ + public function __construct(IDBConnection $dbConnection, IUserManager $userManager) { + parent::__construct(); + $this->dbConnection = $dbConnection; + $this->userManager = $userManager; + } + + protected function configure() { + $this->setName('incomingShares:sync') + ->setDescription('Manual synchronisation of incoming federated shares'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * + * @return int|null|void + */ + public function execute(InputInterface $input, OutputInterface $output) { + $mountProvider = $this->getExternalMountProvider(); + $loader = $this->getLoader(); + $cursor = $this->getCursor(); + while ($data = $cursor->fetch()) { + $user = $this->userManager->get($data['user']); + $userMounts = $mountProvider->getMountsForUser($user, $loader); + /** @var \OCA\Files_Sharing\External\Mount $mount */ + foreach ($userMounts as $mount) { + /** @var Storage $storage */ + $storage = $mount->getStorage(); + $this->refreshStorageRoot($storage); + } + } + $cursor->closeCursor(); + } + + /** + * @param IStorage $storage + */ + protected function refreshStorageRoot(IStorage $storage) { + try { + $localMtime = $storage->filemtime(''); + /** @var \OCA\Files_Sharing\External\Storage $storage */ + if ($storage->hasUpdated('', $localMtime)) { + try { + $storage->getScanner('')->scan('', false, 0); + } catch (LockedException $e) { + // it can be locked, let's skip it then + } catch (ServerNotAvailableException $e) { + // remote server hasn't responded + } + } + } catch (StorageNotAvailableException $e) { + // pass + } catch (StorageInvalidException $e) { + // pass + } + } + + /** + * @return \Doctrine\DBAL\Driver\Statement + */ + protected function getCursor() { + $qb = $this->dbConnection->getQueryBuilder(); + $qb->selectDistinct('user') + ->from('share_external') + ->where($qb->expr()->eq('accepted', $qb->expr()->literal('1'))); + + return $qb->execute(); + } + + /** + * @return \OCP\Files\Storage\IStorageFactory + */ + protected function getLoader() { + return \OC\Files\Filesystem::getLoader(); + } + + /** + * @return \OCA\Files_Sharing\External\MountProvider + */ + protected function getExternalMountProvider() { + $app = new Application(); + return $app->getContainer()->query('ExternalMountProvider'); + } +} diff --git a/apps/federatedfilesharing/tests/Command/SyncIncomingSharesTest.php b/apps/federatedfilesharing/tests/Command/SyncIncomingSharesTest.php new file mode 100644 index 000000000000..843099cba6f7 --- /dev/null +++ b/apps/federatedfilesharing/tests/Command/SyncIncomingSharesTest.php @@ -0,0 +1,72 @@ + + * + * @copyright Copyright (c) 2019, ownCloud GmbH + * @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\FederatedFileSharing\Tests\Command; + +use Doctrine\DBAL\Driver\Statement; +use OCA\FederatedFileSharing\Tests\TestCase; +use OCA\FederatedFileSharing\Command\SyncIncomingShares; +use OCP\DB\QueryBuilder\IExpressionBuilder; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; +use OCP\IUserManager; +use Symfony\Component\Console\Tester\CommandTester; + +/** + * Class SyncIncomingSharesTest + * + * @group DB + * @package OCA\FederatedFileSharing\Tests\Command + */ +class SyncIncomingSharesTest extends TestCase { + /** @var CommandTester */ + private $commandTester; + + /** @var IDBConnection | \PHPUnit_Framework_MockObject_MockObject */ + private $dbConnection; + + /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */ + private $userManager; + + protected function setUp() { + parent::setUp(); + $this->dbConnection = $this->createMock(IDBConnection::class); + $this->userManager = $this->createMock(IUserManager::class); + $command = new SyncIncomingShares($this->dbConnection, $this->userManager); + $this->commandTester = new CommandTester($command); + } + + public function testNoSharesSync() { + $exprBuilder = $this->createMock(IExpressionBuilder::class); + $statementMock = $this->createMock(Statement::class); + $qbMock = $this->createMock(IQueryBuilder::class); + $qbMock->method('selectDistinct')->willReturnSelf(); + $qbMock->method('from')->willReturnSelf(); + $qbMock->method('where')->willReturnSelf(); + $qbMock->method('expr')->willReturn($exprBuilder); + $qbMock->method('execute')->willReturn($statementMock); + + $this->dbConnection->method('getQueryBuilder')->willReturn($qbMock); + $this->commandTester->execute([]); + $output = $this->commandTester->getDisplay(); + $this->assertEmpty($output); + } +}