diff --git a/apps/files_sharing/api/share20ocs.php b/apps/files_sharing/api/share20ocs.php index 2dadc0888e..8fe8991f9c 100644 --- a/apps/files_sharing/api/share20ocs.php +++ b/apps/files_sharing/api/share20ocs.php @@ -329,9 +329,13 @@ class Share20OCS { return new \OC_OCS_Result($share); } - private function getSharedWithMe() { - $userShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_USER, -1, 0); - $groupShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, -1, 0); + /** + * @param \OCP\Files\File|\OCP\Files\Folder $node + * @return \OC_OCS_Result + */ + private function getSharedWithMe($node = null) { + $userShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_USER, $node, -1, 0); + $groupShares = $this->shareManager->getSharedWith($this->currentUser, \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0); $shares = array_merge($userShares, $groupShares); @@ -390,10 +394,6 @@ class Share20OCS { $subfiles = $this->request->getParam('subfiles'); $path = $this->request->getParam('path', null); - if ($sharedWithMe === 'true') { - return $this->getSharedWithMe(); - } - if ($path !== null) { $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); try { @@ -403,6 +403,10 @@ class Share20OCS { } } + if ($sharedWithMe === 'true') { + return $this->getSharedWithMe($path); + } + if ($subfiles === 'true') { return $this->getSharesInDir($path); } diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature index dedf2c388f..bdc1a4224d 100644 --- a/build/integration/features/sharing-v1.feature +++ b/build/integration/features/sharing-v1.feature @@ -313,6 +313,28 @@ Feature: sharing And the HTTP status code should be "200" And last share_id is included in the answer + Scenario: Sharee can see the filtered share + Given user "user0" exists + And user "user1" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And file "textfile1.txt" of user "user0" is shared with user "user1" + And As an "user1" + When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true&path=textfile1 (2).txt" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is included in the answer + + Scenario: Sharee can't see the share that is filtered out + Given user "user0" exists + And user "user1" exists + And file "textfile0.txt" of user "user0" is shared with user "user1" + And file "textfile1.txt" of user "user0" is shared with user "user1" + And As an "user1" + When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true&path=textfile0 (2).txt" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is not included in the answer + Scenario: Sharee can see the group share Given As an "admin" And user "user0" exists diff --git a/lib/private/share20/defaultshareprovider.php b/lib/private/share20/defaultshareprovider.php index 35b3f71f3d..0fa1552a1e 100644 --- a/lib/private/share20/defaultshareprovider.php +++ b/lib/private/share20/defaultshareprovider.php @@ -518,16 +518,9 @@ class DefaultShareProvider implements IShareProvider { } /** - * Get shared with the given user - * - * @param IUser $user get shares where this user is the recipient - * @param int $shareType \OCP\Share::SHARE_TYPE_USER or \OCP\Share::SHARE_TYPE_GROUP are supported - * @param int $limit The maximum number of shares, -1 for all - * @param int $offset - * @return IShare[] - * @throws BackendError + * @inheritdoc */ - public function getSharedWith(IUser $user, $shareType, $limit, $offset) { + public function getSharedWith(IUser $user, $shareType, $node, $limit, $offset) { /** @var Share[] $shares */ $shares = []; @@ -549,6 +542,11 @@ class DefaultShareProvider implements IShareProvider { $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_USER))); $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($user->getUID()))); + // Filter by node if provided + if ($node !== null) { + $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId()))); + } + $cursor = $qb->execute(); while($data = $cursor->fetch()) { @@ -581,9 +579,14 @@ class DefaultShareProvider implements IShareProvider { $qb->setMaxResults($limit - count($shares)); } + // Filter by node if provided + if ($node !== null) { + $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId()))); + } + $groups = array_map(function(IGroup $group) { return $group->getGID(); }, $groups); - $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP))); + $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_GROUP))); $qb->andWhere($qb->expr()->in('share_with', $qb->createNamedParameter( $groups, IQueryBuilder::PARAM_STR_ARRAY diff --git a/lib/private/share20/manager.php b/lib/private/share20/manager.php index d6245f4bea..ad5fed9390 100644 --- a/lib/private/share20/manager.php +++ b/lib/private/share20/manager.php @@ -21,6 +21,7 @@ namespace OC\Share20; +use OCP\Files\Node; use OCP\Share\IManager; use OCP\Share\IProviderFactory; use OC\Share20\Exception\BackendError; @@ -722,18 +723,12 @@ class Manager implements IManager { } /** - * Get shares shared with $user. - * - * @param IUser $user - * @param int $shareType - * @param int $limit The maximum number of shares returned, -1 for all - * @param int $offset - * @return \OCP\Share\IShare[] + * @inheritdoc */ - public function getSharedWith(IUser $user, $shareType, $limit = 50, $offset = 0) { + public function getSharedWith(IUser $user, $shareType, $node = null, $limit = 50, $offset = 0) { $provider = $this->factory->getProviderForType($shareType); - return $provider->getSharedWith($user, $shareType, $limit, $offset); + return $provider->getSharedWith($user, $shareType, $node, $limit, $offset); } /** diff --git a/lib/public/share/imanager.php b/lib/public/share/imanager.php index 6531c14a85..b2d9953e9e 100644 --- a/lib/public/share/imanager.php +++ b/lib/public/share/imanager.php @@ -88,15 +88,17 @@ interface IManager { /** * Get shares shared with $user. + * Filter by $node if provided * * @param IUser $user * @param int $shareType + * @param File|Folder|null $node * @param int $limit The maximum number of shares returned, -1 for all * @param int $offset * @return IShare[] * @since 9.0.0 */ - public function getSharedWith(IUser $user, $shareType, $limit = 50, $offset = 0); + public function getSharedWith(IUser $user, $shareType, $node = null, $limit = 50, $offset = 0); /** * Retrieve a share by the share id diff --git a/lib/public/share/ishareprovider.php b/lib/public/share/ishareprovider.php index 50964c88dd..8507462cbe 100644 --- a/lib/public/share/ishareprovider.php +++ b/lib/public/share/ishareprovider.php @@ -23,6 +23,7 @@ namespace OCP\Share; use OC\Share20\Exception\ShareNotFound; use OC\Share20\Exception\BackendError; +use OCP\Files\Node; use OCP\IUser; /** @@ -116,12 +117,13 @@ interface IShareProvider { * * @param IUser $user get shares where this user is the recipient * @param int $shareType + * @param Node|null $node * @param int $limit The max number of entries returned, -1 for all * @param int $offset * @return \OCP\Share\IShare[] * @since 9.0.0 */ - public function getSharedWith(IUser $user, $shareType, $limit, $offset); + public function getSharedWith(IUser $user, $shareType, $node, $limit, $offset); /** * Get a share by token diff --git a/tests/lib/share20/defaultshareprovidertest.php b/tests/lib/share20/defaultshareprovidertest.php index 45f2bedcb6..28b57435e1 100644 --- a/tests/lib/share20/defaultshareprovidertest.php +++ b/tests/lib/share20/defaultshareprovidertest.php @@ -824,7 +824,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->rootFolder->method('getUserFolder')->with('shareOwner')->will($this->returnSelf()); $this->rootFolder->method('getById')->with(42)->willReturn([$file]); - $share = $this->provider->getSharedWith($user, \OCP\Share::SHARE_TYPE_USER, 1 , 0); + $share = $this->provider->getSharedWith($user, \OCP\Share::SHARE_TYPE_USER, null, 1 , 0); $this->assertCount(1, $share); $share = $share[0]; @@ -894,7 +894,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->rootFolder->method('getUserFolder')->with('shareOwner')->will($this->returnSelf()); $this->rootFolder->method('getById')->with(42)->willReturn([$file]); - $share = $this->provider->getSharedWith($user, \OCP\Share::SHARE_TYPE_GROUP, 20 , 1); + $share = $this->provider->getSharedWith($user, \OCP\Share::SHARE_TYPE_GROUP, null, 20 , 1); $this->assertCount(1, $share); $share = $share[0]; @@ -979,7 +979,7 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->rootFolder->method('getUserFolder')->with('shareOwner')->will($this->returnSelf()); $this->rootFolder->method('getById')->with(42)->willReturn([$file]); - $share = $this->provider->getSharedWith($user, \OCP\Share::SHARE_TYPE_GROUP, -1, 0); + $share = $this->provider->getSharedWith($user, \OCP\Share::SHARE_TYPE_GROUP, null, -1, 0); $this->assertCount(1, $share); $share = $share[0]; @@ -992,6 +992,78 @@ class DefaultShareProviderTest extends \Test\TestCase { $this->assertSame('userTarget', $share->getTarget()); } + public function testGetSharedWithUserWithNode() { + $this->addShareToDB(\OCP\Share::SHARE_TYPE_USER, 'user0', 'user1', 'user1', + 'file', 42, 'myTarget', 31, null, null, null); + $id = $this->addShareToDB(\OCP\Share::SHARE_TYPE_USER, 'user0', 'user1', 'user1', + 'file', 43, 'myTarget', 31, null, null, null); + + $user0 = $this->getMock('\OCP\IUser'); + $user0->method('getUID')->willReturn('user0'); + $user1 = $this->getMock('\OCP\IUser'); + $user1->method('getUID')->willReturn('user1'); + + $this->userManager->method('get')->willReturnMap([ + ['user0', $user0], + ['user1', $user1], + ]); + + $file = $this->getMock('\OCP\Files\File'); + $file->method('getId')->willReturn(43); + $this->rootFolder->method('getUserFolder')->with('user1')->will($this->returnSelf()); + $this->rootFolder->method('getById')->with(43)->willReturn([$file]); + + $share = $this->provider->getSharedWith($user0, \OCP\Share::SHARE_TYPE_USER, $file, -1, 0); + $this->assertCount(1, $share); + + $share = $share[0]; + $this->assertEquals($id, $share->getId()); + $this->assertSame($user0, $share->getSharedWith()); + $this->assertSame($user1, $share->getShareOwner()); + $this->assertSame($user1, $share->getSharedBy()); + $this->assertSame($file, $share->getNode()); + $this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType()); + } + + public function testGetSharedWithGroupWithNode() { + $this->addShareToDB(\OCP\Share::SHARE_TYPE_GROUP, 'group0', 'user1', 'user1', + 'file', 42, 'myTarget', 31, null, null, null); + $id = $this->addShareToDB(\OCP\Share::SHARE_TYPE_GROUP, 'group0', 'user1', 'user1', + 'file', 43, 'myTarget', 31, null, null, null); + + $user0 = $this->getMock('\OCP\IUser'); + $user0->method('getUID')->willReturn('user0'); + $user1 = $this->getMock('\OCP\IUser'); + $user1->method('getUID')->willReturn('user1'); + + $this->userManager->method('get')->willReturnMap([ + ['user0', $user0], + ['user1', $user1], + ]); + + $group0 = $this->getMock('\OCP\IGroup'); + $group0->method('getGID')->willReturn('group0'); + + $this->groupManager->method('get')->with('group0')->willReturn($group0); + $this->groupManager->method('getUserGroups')->with($user0)->willReturn([$group0]); + + $node = $this->getMock('\OCP\Files\Folder'); + $node->method('getId')->willReturn(43); + $this->rootFolder->method('getUserFolder')->with('user1')->will($this->returnSelf()); + $this->rootFolder->method('getById')->with(43)->willReturn([$node]); + + $share = $this->provider->getSharedWith($user0, \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0); + $this->assertCount(1, $share); + + $share = $share[0]; + $this->assertEquals($id, $share->getId()); + $this->assertSame($group0, $share->getSharedWith()); + $this->assertSame($user1, $share->getShareOwner()); + $this->assertSame($user1, $share->getSharedBy()); + $this->assertSame($node, $share->getNode()); + $this->assertEquals(\OCP\Share::SHARE_TYPE_GROUP, $share->getShareType()); + } + public function testGetSharesBy() { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('share')