Skip to content

Commit

Permalink
Add a command to check federated share updates
Browse files Browse the repository at this point in the history
  • Loading branch information
VicDeo committed Mar 27, 2019
1 parent 67c4ba1 commit b13e469
Show file tree
Hide file tree
Showing 3 changed files with 207 additions and 0 deletions.
3 changes: 3 additions & 0 deletions apps/federatedfilesharing/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@
<personal>OCA\FederatedFileSharing\Panels\GeneralPersonalPanel</personal>
<personal>OCA\FederatedFileSharing\Panels\SharingPersonalPanel</personal>
</settings>
<commands>
<command>OCA\FederatedFileSharing\Command\SyncIncomingShares</command>
</commands>
</info>
132 changes: 132 additions & 0 deletions apps/federatedfilesharing/lib/Command/SyncIncomingShares.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?php
/**
* @author Viktar Dubiniuk <dubiniuk@owncloud.com>
*
* @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 <http://www.gnu.org/licenses/>
*
*/

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');
}
}
72 changes: 72 additions & 0 deletions apps/federatedfilesharing/tests/Command/SyncIncomingSharesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php
/**
* @author Viktar Dubiniuk <dubiniuk@owncloud.com>
*
* @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 <http://www.gnu.org/licenses/>
*
*/

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);
}
}

0 comments on commit b13e469

Please sign in to comment.