Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/files_sharing/lib/API/Share20OCS.php
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ protected function canAccessShare(\OCP\Share\IShare $share) {

if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
$sharedWith = $this->groupManager->get($share->getSharedWith());
if ($sharedWith->inGroup($this->currentUser)) {
if (!is_null($sharedWith) && $sharedWith->inGroup($this->currentUser)) {
return true;
}
}
Expand Down
18 changes: 17 additions & 1 deletion apps/files_sharing/lib/MountProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,23 @@ private function buildSuperShares(array $allShares, \OCP\IUser $user) {
if ($share->getTarget() !== $superShare->getTarget()) {
// adjust target, for database consistency
$share->setTarget($superShare->getTarget());
$this->shareManager->moveShare($share, $user->getUID());
try {
$this->shareManager->moveShare($share, $user->getUID());
} catch (\InvalidArgumentException $e) {
// ignore as it is not important and we don't want to
// block FS setup

// the subsequent code anyway only uses the target of the
// super share

// such issue can usually happen when dealing with
// null groups which usually appear with group backend
// caching inconsistencies
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather log something. It will be easier to debug possible errors or to know what is being ignored.

\OC::$server->getLogger()->debug(
'Could not adjust share target for share ' . $share->getId() . ' to make it consistent: ' . $e->getMessage(),
['app' => 'files_sharing']
);
}
}
}

Expand Down
7 changes: 6 additions & 1 deletion apps/files_sharing/tests/API/Share20OCSTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -521,14 +521,19 @@ public function testCanAccessShare() {
$this->groupManager->method('get')->will($this->returnValueMap([
['group', $group],
['group2', $group2],
['groupnull', null],
]));
$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));

$share = $this->getMock('OCP\Share\IShare');
$share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_GROUP);
$share->method('getSharedWith')->willReturn('group2');
$this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think some adjustments are needed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed, forgot to use "groupnull"


$this->groupManager->method('get')->with('group2')->willReturn($group);
// null group
$share = $this->getMock('OCP\Share\IShare');
$share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_GROUP);
$share->method('getSharedWith')->willReturn('groupnull');
$this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));

$share = $this->getMock('OCP\Share\IShare');
Expand Down
22 changes: 21 additions & 1 deletion apps/files_sharing/tests/MountProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,20 @@ public function mergeSharesDataProvider() {
['1', 100, 'user2', '/share2-renamed', 31],
],
],
// #9: share as outsider with "nullgroup" and "user1" where recipient renamed in between
[
[
[2, 100, 'user2', '/share2', 31],
],
[
[1, 100, 'nullgroup', '/share2-renamed', 31],
],
[
// use target of least recent share
['1', 100, 'nullgroup', '/share2-renamed', 31],
],
true
],
];
}

Expand All @@ -282,7 +296,7 @@ public function mergeSharesDataProvider() {
* @param array $groupShares array of group share specs
* @param array $expectedShares array of expected supershare specs
*/
public function testMergeShares($userShares, $groupShares, $expectedShares) {
public function testMergeShares($userShares, $groupShares, $expectedShares, $moveFails = false) {
$rootFolder = $this->getMock('\OCP\Files\IRootFolder');
$userManager = $this->getMock('\OCP\IUserManager');

Expand Down Expand Up @@ -311,6 +325,12 @@ public function testMergeShares($userShares, $groupShares, $expectedShares) {
return new \OC\Share20\Share($rootFolder, $userManager);
}));

if ($moveFails) {
$this->shareManager->expects($this->any())
->method('moveShare')
->will($this->throwException(new \InvalidArgumentException()));
}

$mounts = $this->provider->getMountsForUser($this->user, $this->loader);

$this->assertCount(count($expectedShares), $mounts);
Expand Down
14 changes: 12 additions & 2 deletions lib/private/Group/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,12 @@ public function search($search, $limit = null, $offset = null) {
foreach ($this->backends as $backend) {
$groupIds = $backend->getGroups($search, $limit, $offset);
foreach ($groupIds as $groupId) {
$groups[$groupId] = $this->get($groupId);
$aGroup = $this->get($groupId);
if (!is_null($aGroup)) {
$groups[$groupId] = $aGroup;
} else {
\OC::$server->getLogger()->debug('Group "' . $groupId . '" was returned by search but not found through direct access', array('app' => 'core'));
}
}
if (!is_null($limit) and $limit <= 0) {
return array_values($groups);
Expand Down Expand Up @@ -245,7 +250,12 @@ public function getUserIdGroups($uid) {
$groupIds = $backend->getUserGroups($uid);
if (is_array($groupIds)) {
foreach ($groupIds as $groupId) {
$groups[$groupId] = $this->get($groupId);
$aGroup = $this->get($groupId);
if (!is_null($aGroup)) {
$groups[$groupId] = $aGroup;
} else {
\OC::$server->getLogger()->debug('User "' . $uid . '" belongs to deleted group: "' . $groupId . '"', array('app' => 'core'));
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions lib/private/Share20/DefaultShareProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ public function deleteFromSelf(\OCP\Share\IShare $share, $recipient) {
$group = $this->groupManager->get($share->getSharedWith());
$user = $this->userManager->get($recipient);

if (is_null($group)) {
throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
}

if (!$group->inGroup($user)) {
throw new ProviderException('Recipient not in receiving group');
}
Expand Down
13 changes: 9 additions & 4 deletions lib/private/Share20/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -377,10 +377,12 @@ protected function userCreateChecks(\OCP\Share\IShare $share) {
// The share is already shared with this user via a group share
if ($existingShare->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
$group = $this->groupManager->get($existingShare->getSharedWith());
$user = $this->userManager->get($share->getSharedWith());
if (!is_null($group)) {
$user = $this->userManager->get($share->getSharedWith());

if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
throw new \Exception('Path already shared with this user');
if ($group->inGroup($user) && $existingShare->getShareOwner() !== $share->getShareOwner()) {
throw new \Exception('Path already shared with this user');
}
}
}
}
Expand All @@ -402,7 +404,7 @@ protected function groupCreateChecks(\OCP\Share\IShare $share) {
if ($this->shareWithGroupMembersOnly()) {
$sharedBy = $this->userManager->get($share->getSharedBy());
$sharedWith = $this->groupManager->get($share->getSharedWith());
if (!$sharedWith->inGroup($sharedBy)) {
if (is_null($sharedWith) || !$sharedWith->inGroup($sharedBy)) {
throw new \Exception('Only sharing within your own groups is allowed');
}
}
Expand Down Expand Up @@ -857,6 +859,9 @@ public function moveShare(\OCP\Share\IShare $share, $recipientId) {

if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
$sharedWith = $this->groupManager->get($share->getSharedWith());
if (is_null($sharedWith)) {
throw new \InvalidArgumentException('Group "' . $share->getSharedWith() . '" does not exist');
}
$recipient = $this->userManager->get($recipientId);
if (!$sharedWith->inGroup($recipient)) {
throw new \InvalidArgumentException('Invalid recipient');
Expand Down
52 changes: 52 additions & 0 deletions tests/lib/Group/ManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,32 @@ public function testSearchMultipleBackendsLimitAndOffset() {
$this->assertEquals('group12', $group12->getGID());
}

public function testSearchResultExistsButGroupDoesNot() {
/**
* @var \PHPUnit_Framework_MockObject_MockObject | \OC\Group\Backend $backend
*/
$backend = $this->getMock('\OC\Group\Database');
$backend->expects($this->once())
->method('getGroups')
->with('1')
->will($this->returnValue(['group1']));
$backend->expects($this->once())
->method('groupExists')
->with('group1')
->will($this->returnValue(false));

/**
* @var \OC\User\Manager $userManager
*/
$userManager = $this->getMock('\OC\User\Manager');

$manager = new \OC\Group\Manager($userManager);
$manager->addBackend($backend);

$groups = $manager->search('1');
$this->assertEmpty($groups);
}

public function testGetUserGroups() {
/**
* @var \PHPUnit_Framework_MockObject_MockObject | \OC\Group\Backend $backend
Expand Down Expand Up @@ -330,6 +356,32 @@ public function testGetUserGroupIds() {
}
}

public function testGetUserGroupsWithDeletedGroup() {
/**
* @var \PHPUnit_Framework_MockObject_MockObject | \OC\Group\Backend $backend
*/
$backend = $this->getMock('\OC\Group\Database');
$backend->expects($this->once())
->method('getUserGroups')
->with('user1')
->will($this->returnValue(array('group1')));
$backend->expects($this->any())
->method('groupExists')
->with('group1')
->will($this->returnValue(false));

/**
* @var \OC\User\Manager $userManager
*/
$userManager = $this->getMock('\OC\User\Manager');
$userBackend = $this->getMock('\OC_User_Backend');
$manager = new \OC\Group\Manager($userManager);
$manager->addBackend($backend);

$groups = $manager->getUserGroups(new User('user1', $userBackend));
$this->assertEmpty($groups);
}

public function testInGroup() {
/**
* @var \PHPUnit_Framework_MockObject_MockObject | \OC\Group\Backend $backend
Expand Down
42 changes: 42 additions & 0 deletions tests/lib/Share20/DefaultShareProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,48 @@ public function testDeleteFromSelfGroupUserNotInGroup() {
$this->provider->deleteFromSelf($share, 'user2');
}

/**
* @expectedException \OC\Share20\Exception\ProviderException
* @expectedExceptionMessage Group "group" does not exist
*/
public function testDeleteFromSelfGroupDoesNotExist() {
$qb = $this->dbConn->getQueryBuilder();
$stmt = $qb->insert('share')
->values([
'share_type' => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_GROUP),
'share_with' => $qb->expr()->literal('group'),
'uid_owner' => $qb->expr()->literal('user1'),
'uid_initiator' => $qb->expr()->literal('user1'),
'item_type' => $qb->expr()->literal('file'),
'file_source' => $qb->expr()->literal(1),
'file_target' => $qb->expr()->literal('myTarget1'),
'permissions' => $qb->expr()->literal(2)
])->execute();
$this->assertEquals(1, $stmt);
$id = $qb->getLastInsertId();

$user1 = $this->getMock('\OCP\IUser');
$user1->method('getUID')->willReturn('user1');
$user2 = $this->getMock('\OCP\IUser');
$user2->method('getUID')->willReturn('user2');
$this->userManager->method('get')->will($this->returnValueMap([
['user1', $user1],
['user2', $user2],
]));

$this->groupManager->method('get')->with('group')->willReturn(null);

$file = $this->getMock('\OCP\Files\File');
$file->method('getId')->willReturn(1);

$this->rootFolder->method('getUserFolder')->with('user1')->will($this->returnSelf());
$this->rootFolder->method('getById')->with(1)->willReturn([$file]);

$share = $this->provider->getShareById($id);

$this->provider->deleteFromSelf($share, 'user2');
}

public function testDeleteFromSelfUser() {
$qb = $this->dbConn->getQueryBuilder();
$stmt = $qb->insert('share')
Expand Down
73 changes: 73 additions & 0 deletions tests/lib/Share20/ManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,39 @@ public function testUserCreateChecksIdenticalPathSharedViaGroup() {
$this->invokePrivate($this->manager, 'userCreateChecks', [$share]);
}

public function testUserCreateChecksIdenticalPathSharedViaDeletedGroup() {
$share = $this->manager->newShare();

$sharedWith = $this->getMock('\OCP\IUser');
$sharedWith->method('getUID')->willReturn('sharedWith');

$this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);

$path = $this->getMock('\OCP\Files\Node');

$share->setSharedWith('sharedWith')
->setNode($path)
->setShareOwner('shareOwner')
->setProviderId('foo')
->setId('bar');

$share2 = $this->manager->newShare();
$share2->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
->setShareOwner('shareOwner2')
->setProviderId('foo')
->setId('baz')
->setSharedWith('group');

$this->groupManager->method('get')->with('group')->willReturn(null);

$this->defaultProvider
->method('getSharesByPath')
->with($path)
->willReturn([$share2]);

$this->assertNull($this->invokePrivate($this->manager, 'userCreateChecks', [$share]));
}

public function testUserCreateChecksIdenticalPathNotSharedWithUser() {
$share = $this->manager->newShare();
$sharedWith = $this->getMock('\OCP\IUser');
Expand Down Expand Up @@ -1200,6 +1233,29 @@ public function testGroupCreateChecksShareWithGroupMembersOnlyNotInGroup() {
$this->invokePrivate($this->manager, 'groupCreateChecks', [$share]);
}

/**
* @expectedException Exception
* @expectedExceptionMessage Only sharing within your own groups is allowed
*/
public function testGroupCreateChecksShareWithGroupMembersOnlyNullGroup() {
$share = $this->manager->newShare();

$user = $this->getMock('\OCP\IUser');
$share->setSharedBy('user')->setSharedWith('group');

$this->groupManager->method('get')->with('group')->willReturn(null);
$this->userManager->method('get')->with('user')->willReturn($user);

$this->config
->method('getAppValue')
->will($this->returnValueMap([
['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
]));

$this->assertNull($this->invokePrivate($this->manager, 'groupCreateChecks', [$share]));
}

public function testGroupCreateChecksShareWithGroupMembersOnlyInGroup() {
$share = $this->manager->newShare();

Expand Down Expand Up @@ -2493,6 +2549,23 @@ public function testMoveShareGroupNotRecipient() {
$this->manager->moveShare($share, 'recipient');
}

/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage Group "shareWith" does not exist
*/
public function testMoveShareGroupNull() {
$share = $this->manager->newShare();
$share->setShareType(\OCP\Share::SHARE_TYPE_GROUP);
$share->setSharedWith('shareWith');

$recipient = $this->getMock('\OCP\IUser');

$this->groupManager->method('get')->with('shareWith')->willReturn(null);
$this->userManager->method('get')->with('recipient')->willReturn($recipient);

$this->manager->moveShare($share, 'recipient');
}

public function testMoveShareGroup() {
$share = $this->manager->newShare();
$share->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
Expand Down