summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoeland Jago Douma <rullzer@users.noreply.github.com>2019-10-31 19:28:29 +0100
committerGitHub <noreply@github.com>2019-10-31 19:28:29 +0100
commitfd475d421232e3d83103304002bce23a0b267a60 (patch)
treef7ccb86835b1bf8b6767368be9e0d62135c1a062
parentef6806a23579c50ff9740662aec17ae2551a2f86 (diff)
parent2f49806c201c0aaaf400e84a7580d0789c90dc57 (diff)
downloadnextcloud-server-fd475d421232e3d83103304002bce23a0b267a60.tar.gz
nextcloud-server-fd475d421232e3d83103304002bce23a0b267a60.zip
Merge pull request #17739 from nextcloud/enh/share/filter
Get all shares iterable
-rw-r--r--apps/federatedfilesharing/lib/FederatedShareProvider.php27
-rw-r--r--apps/sharebymail/lib/ShareByMailProvider.php25
-rw-r--r--lib/private/Share20/DefaultShareProvider.php26
-rw-r--r--lib/private/Share20/Manager.php7
-rw-r--r--lib/public/Share/IManager.php12
-rw-r--r--lib/public/Share/IShareProvider.php9
-rw-r--r--tests/lib/Share20/DefaultShareProviderTest.php165
-rw-r--r--tests/lib/Share20/ManagerTest.php51
8 files changed, 322 insertions, 0 deletions
diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php
index 67089cba9d3..4d93dec18f7 100644
--- a/apps/federatedfilesharing/lib/FederatedShareProvider.php
+++ b/apps/federatedfilesharing/lib/FederatedShareProvider.php
@@ -1100,4 +1100,31 @@ class FederatedShareProvider implements IShareProvider {
return ['remote' => $remote];
}
+
+ public function getAllShares(): iterable {
+ $qb = $this->dbConnection->getQueryBuilder();
+
+ $qb->select('*')
+ ->from('share')
+ ->where(
+ $qb->expr()->orX(
+ $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE)),
+ $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE_GROUP))
+ )
+ );
+
+ $cursor = $qb->execute();
+ while($data = $cursor->fetch()) {
+ try {
+ $share = $this->createShareObject($data);
+ } catch (InvalidShare $e) {
+ continue;
+ } catch (ShareNotFound $e) {
+ continue;
+ }
+
+ yield $share;
+ }
+ $cursor->closeCursor();
+ }
}
diff --git a/apps/sharebymail/lib/ShareByMailProvider.php b/apps/sharebymail/lib/ShareByMailProvider.php
index 9bfe5e733f4..903df175e9c 100644
--- a/apps/sharebymail/lib/ShareByMailProvider.php
+++ b/apps/sharebymail/lib/ShareByMailProvider.php
@@ -1166,4 +1166,29 @@ class ShareByMailProvider implements IShareProvider {
return ['public' => $mail];
}
+ public function getAllShares(): iterable {
+ $qb = $this->dbConnection->getQueryBuilder();
+
+ $qb->select('*')
+ ->from('share')
+ ->where(
+ $qb->expr()->orX(
+ $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_EMAIL))
+ )
+ );
+
+ $cursor = $qb->execute();
+ while($data = $cursor->fetch()) {
+ try {
+ $share = $this->createShareObject($data);
+ } catch (InvalidShare $e) {
+ continue;
+ } catch (ShareNotFound $e) {
+ continue;
+ }
+
+ yield $share;
+ }
+ $cursor->closeCursor();
+ }
}
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index aea50dfcdb6..05b3094e6a2 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -1382,4 +1382,30 @@ class DefaultShareProvider implements IShareProvider {
}
}
+
+ public function getAllShares(): iterable {
+ $qb = $this->dbConn->getQueryBuilder();
+
+ $qb->select('*')
+ ->from('share')
+ ->where(
+ $qb->expr()->orX(
+ $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_USER)),
+ $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_GROUP)),
+ $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_LINK))
+ )
+ );
+
+ $cursor = $qb->execute();
+ while($data = $cursor->fetch()) {
+ try {
+ $share = $this->createShare($data);
+ } catch (InvalidShare $e) {
+ continue;
+ }
+
+ yield $share;
+ }
+ $cursor->closeCursor();
+ }
}
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 2e8e6f9a3af..df537062e4a 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -1671,4 +1671,11 @@ class Manager implements IManager {
return true;
}
+ public function getAllShares(): iterable {
+ $providers = $this->factory->getAllProviders();
+
+ foreach ($providers as $provider) {
+ yield from $provider->getAllShares();
+ }
+ }
}
diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php
index 302be523327..8bb7291d6ba 100644
--- a/lib/public/Share/IManager.php
+++ b/lib/public/Share/IManager.php
@@ -385,4 +385,16 @@ interface IManager {
*/
public function shareProviderExists($shareType);
+ /**
+ * @Internal
+ *
+ * Get all the shares as iterable to reduce memory overhead
+ * Note, since this opens up database cursors the iterable should
+ * be fully itterated.
+ *
+ * @return iterable
+ * @since 18.0.0
+ */
+ public function getAllShares(): iterable;
+
}
diff --git a/lib/public/Share/IShareProvider.php b/lib/public/Share/IShareProvider.php
index 6731bf8882b..c8815928269 100644
--- a/lib/public/Share/IShareProvider.php
+++ b/lib/public/Share/IShareProvider.php
@@ -217,4 +217,13 @@ interface IShareProvider {
* @since 12
*/
public function getAccessList($nodes, $currentAccess);
+
+ /**
+ * Get all the shares in this provider returned as iterable to reduce memory
+ * overhead
+ *
+ * @return iterable
+ * @since 18.0.0
+ */
+ public function getAllShares(): iterable;
}
diff --git a/tests/lib/Share20/DefaultShareProviderTest.php b/tests/lib/Share20/DefaultShareProviderTest.php
index f5f710cbbd3..8f725022eda 100644
--- a/tests/lib/Share20/DefaultShareProviderTest.php
+++ b/tests/lib/Share20/DefaultShareProviderTest.php
@@ -2742,4 +2742,169 @@ class DefaultShareProviderTest extends \Test\TestCase {
$u5->delete();
$g1->delete();
}
+
+ public function testGetAllShares() {
+ $qb = $this->dbConn->getQueryBuilder();
+
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
+ 'share_with' => $qb->expr()->literal('sharedWith1'),
+ 'uid_owner' => $qb->expr()->literal('shareOwner1'),
+ 'uid_initiator' => $qb->expr()->literal('sharedBy1'),
+ 'item_type' => $qb->expr()->literal('file'),
+ 'file_source' => $qb->expr()->literal(42),
+ 'file_target' => $qb->expr()->literal('myTarget1'),
+ 'permissions' => $qb->expr()->literal(13),
+ ]);
+ $qb->execute();
+
+ $id1 = $qb->getLastInsertId();
+
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_GROUP),
+ 'share_with' => $qb->expr()->literal('sharedWith2'),
+ 'uid_owner' => $qb->expr()->literal('shareOwner2'),
+ 'uid_initiator' => $qb->expr()->literal('sharedBy2'),
+ 'item_type' => $qb->expr()->literal('file'),
+ 'file_source' => $qb->expr()->literal(43),
+ 'file_target' => $qb->expr()->literal('myTarget2'),
+ 'permissions' => $qb->expr()->literal(14),
+ ]);
+ $qb->execute();
+
+ $id2 = $qb->getLastInsertId();
+
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK),
+ 'token' => $qb->expr()->literal('token3'),
+ 'uid_owner' => $qb->expr()->literal('shareOwner3'),
+ 'uid_initiator' => $qb->expr()->literal('sharedBy3'),
+ 'item_type' => $qb->expr()->literal('file'),
+ 'file_source' => $qb->expr()->literal(44),
+ 'file_target' => $qb->expr()->literal('myTarget3'),
+ 'permissions' => $qb->expr()->literal(15),
+ ]);
+ $qb->execute();
+
+ $id3 = $qb->getLastInsertId();
+
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_EMAIL),
+ 'share_with' => $qb->expr()->literal('shareOwner4'),
+ 'token' => $qb->expr()->literal('token4'),
+ 'uid_owner' => $qb->expr()->literal('shareOwner4'),
+ 'uid_initiator' => $qb->expr()->literal('sharedBy4'),
+ 'item_type' => $qb->expr()->literal('file'),
+ 'file_source' => $qb->expr()->literal(45),
+ 'file_target' => $qb->expr()->literal('myTarget4'),
+ 'permissions' => $qb->expr()->literal(16),
+ ]);
+ $qb->execute();
+
+ $id4 = $qb->getLastInsertId();
+
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK),
+ 'token' => $qb->expr()->literal('token5'),
+ 'uid_owner' => $qb->expr()->literal('shareOwner5'),
+ 'uid_initiator' => $qb->expr()->literal('sharedBy5'),
+ 'item_type' => $qb->expr()->literal('file'),
+ 'file_source' => $qb->expr()->literal(46),
+ 'file_target' => $qb->expr()->literal('myTarget5'),
+ 'permissions' => $qb->expr()->literal(17),
+ ]);
+ $qb->execute();
+
+ $id5 = $qb->getLastInsertId();
+
+ $ownerPath1 = $this->createMock(File::class);
+ $shareOwner1Folder = $this->createMock(Folder::class);
+ $shareOwner1Folder->method('getById')->willReturn([$ownerPath1]);
+
+ $ownerPath2 = $this->createMock(File::class);
+ $shareOwner2Folder = $this->createMock(Folder::class);
+ $shareOwner2Folder->method('getById')->willReturn([$ownerPath2]);
+
+ $ownerPath3 = $this->createMock(File::class);
+ $shareOwner3Folder = $this->createMock(Folder::class);
+ $shareOwner3Folder->method('getById')->willReturn([$ownerPath3]);
+
+ $ownerPath4 = $this->createMock(File::class);
+ $shareOwner4Folder = $this->createMock(Folder::class);
+ $shareOwner4Folder->method('getById')->willReturn([$ownerPath4]);
+
+ $ownerPath5 = $this->createMock(File::class);
+ $shareOwner5Folder = $this->createMock(Folder::class);
+ $shareOwner5Folder->method('getById')->willReturn([$ownerPath5]);
+
+ $this->rootFolder
+ ->method('getUserFolder')
+ ->will($this->returnValueMap(
+ [
+ ['shareOwner1', $shareOwner1Folder],
+ ['shareOwner2', $shareOwner2Folder],
+ ['shareOwner3', $shareOwner3Folder],
+ ['shareOwner4', $shareOwner4Folder],
+ ['shareOwner5', $shareOwner5Folder],
+ ]
+ ));
+
+ $shares = iterator_to_array($this->provider->getAllShares());
+ $this->assertEquals(4, count($shares));
+
+ $share = $shares[0];
+
+ // We fetch the node so the root folder is eventually called
+
+ $this->assertEquals($id1, $share->getId());
+ $this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
+ $this->assertEquals('sharedWith1', $share->getSharedWith());
+ $this->assertEquals('sharedBy1', $share->getSharedBy());
+ $this->assertEquals('shareOwner1', $share->getShareOwner());
+ $this->assertEquals($ownerPath1, $share->getNode());
+ $this->assertEquals(13, $share->getPermissions());
+ $this->assertEquals(null, $share->getToken());
+ $this->assertEquals('myTarget1', $share->getTarget());
+
+ $share = $shares[1];
+
+ $this->assertEquals($id2, $share->getId());
+ $this->assertEquals(\OCP\Share::SHARE_TYPE_GROUP, $share->getShareType());
+ $this->assertEquals('sharedWith2', $share->getSharedWith());
+ $this->assertEquals('sharedBy2', $share->getSharedBy());
+ $this->assertEquals('shareOwner2', $share->getShareOwner());
+ $this->assertEquals($ownerPath2, $share->getNode());
+ $this->assertEquals(14, $share->getPermissions());
+ $this->assertEquals(null, $share->getToken());
+ $this->assertEquals('myTarget2', $share->getTarget());
+
+ $share = $shares[2];
+
+ $this->assertEquals($id3, $share->getId());
+ $this->assertEquals(\OCP\Share::SHARE_TYPE_LINK, $share->getShareType());
+ $this->assertEquals(null, $share->getSharedWith());
+ $this->assertEquals('sharedBy3', $share->getSharedBy());
+ $this->assertEquals('shareOwner3', $share->getShareOwner());
+ $this->assertEquals($ownerPath3, $share->getNode());
+ $this->assertEquals(15, $share->getPermissions());
+ $this->assertEquals('token3', $share->getToken());
+ $this->assertEquals('myTarget3', $share->getTarget());
+
+ $share = $shares[3];
+
+ $this->assertEquals($id5, $share->getId());
+ $this->assertEquals(\OCP\Share::SHARE_TYPE_LINK, $share->getShareType());
+ $this->assertEquals(null, $share->getSharedWith());
+ $this->assertEquals('sharedBy5', $share->getSharedBy());
+ $this->assertEquals('shareOwner5', $share->getShareOwner());
+ $this->assertEquals($ownerPath5, $share->getNode());
+ $this->assertEquals(17, $share->getPermissions());
+ $this->assertEquals('token5', $share->getToken());
+ $this->assertEquals('myTarget5', $share->getTarget());
+ }
}
diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php
index 6f46d69d8df..4a7686acd35 100644
--- a/tests/lib/Share20/ManagerTest.php
+++ b/tests/lib/Share20/ManagerTest.php
@@ -3685,6 +3685,57 @@ class ManagerTest extends \Test\TestCase {
$this->assertSame($expected['users'], $result['users']);
}
+
+ public function testGetAllShares() {
+ $factory = new DummyFactory2($this->createMock(IServerContainer::class));
+
+ $manager = new Manager(
+ $this->logger,
+ $this->config,
+ $this->secureRandom,
+ $this->hasher,
+ $this->mountManager,
+ $this->groupManager,
+ $this->l,
+ $this->l10nFactory,
+ $factory,
+ $this->userManager,
+ $this->rootFolder,
+ $this->eventDispatcher,
+ $this->mailer,
+ $this->urlGenerator,
+ $this->defaults
+ );
+
+ $factory->setProvider($this->defaultProvider);
+ $extraProvider = $this->createMock(IShareProvider::class);
+ $factory->setSecondProvider($extraProvider);
+
+ $share1 = $this->createMock(IShare::class);
+ $share2 = $this->createMock(IShare::class);
+ $share3 = $this->createMock(IShare::class);
+ $share4 = $this->createMock(IShare::class);
+
+ $this->defaultProvider->method('getAllShares')
+ ->willReturnCallback(function() use ($share1, $share2) {
+ yield $share1;
+ yield $share2;
+ });
+ $extraProvider->method('getAllShares')
+ ->willReturnCallback(function() use ($share3, $share4) {
+ yield $share3;
+ yield $share4;
+ });
+
+ // "yield from", used in "getAllShares()", does not reset the keys, so
+ // "use_keys" has to be disabled to collect all the values while
+ // ignoring the keys returned by the generator.
+ $result = iterator_to_array($manager->getAllShares(), $use_keys = false);
+
+ $expects = [$share1, $share2, $share3, $share4];
+
+ $this->assertSame($expects, $result);
+ }
}
class DummyFactory implements IProviderFactory {