diff options
12 files changed, 428 insertions, 38 deletions
diff --git a/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php index dcd393b512e..d658c3433f2 100644 --- a/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php +++ b/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php @@ -50,6 +50,9 @@ abstract class AbstractPrincipalBackend implements BackendInterface { /** @var string */ private $dbTableName; + /** @var string */ + private $cuType; + /** * @param IDBConnection $dbConnection * @param IUserSession $userSession @@ -57,18 +60,22 @@ abstract class AbstractPrincipalBackend implements BackendInterface { * @param ILogger $logger * @param string $principalPrefix * @param string $dbPrefix + * @param string $cuType */ public function __construct(IDBConnection $dbConnection, IUserSession $userSession, IGroupManager $groupManager, ILogger $logger, - $principalPrefix, $dbPrefix) { + string $principalPrefix, + string $dbPrefix, + string $cuType) { $this->db = $dbConnection; $this->userSession = $userSession; $this->groupManager = $groupManager; $this->logger = $logger; $this->principalPrefix = $principalPrefix; $this->dbTableName = 'calendar_' . $dbPrefix; + $this->cuType = $cuType; } /** @@ -328,7 +335,8 @@ abstract class AbstractPrincipalBackend implements BackendInterface { return [ 'uri' => $this->principalPrefix . '/' . $row['backend_id'] . '-' . $row['resource_id'], '{DAV:}displayname' => $row['displayname'], - '{http://sabredav.org/ns}email-address' => $row['email'] + '{http://sabredav.org/ns}email-address' => $row['email'], + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->cuType, ]; } diff --git a/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php index a1030376c11..f8f10e78f94 100644 --- a/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php +++ b/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php @@ -40,6 +40,6 @@ class ResourcePrincipalBackend extends AbstractPrincipalBackend { IGroupManager $groupManager, ILogger $logger) { parent::__construct($dbConnection, $userSession, $groupManager, $logger, - 'principals/calendar-resources', 'resources'); + 'principals/calendar-resources', 'resources', 'RESOURCE'); } } diff --git a/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php index 1d22299515f..3059ed80ea6 100644 --- a/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php +++ b/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php @@ -40,6 +40,6 @@ class RoomPrincipalBackend extends AbstractPrincipalBackend { IGroupManager $groupManager, ILogger $logger) { parent::__construct($dbConnection, $userSession, $groupManager, $logger, - 'principals/calendar-rooms', 'rooms'); + 'principals/calendar-rooms', 'rooms', 'ROOM'); } } diff --git a/apps/dav/lib/CalDAV/Schedule/Plugin.php b/apps/dav/lib/CalDAV/Schedule/Plugin.php index b3f7232c2fe..227a1c11eda 100644 --- a/apps/dav/lib/CalDAV/Schedule/Plugin.php +++ b/apps/dav/lib/CalDAV/Schedule/Plugin.php @@ -50,6 +50,31 @@ class Plugin extends \Sabre\CalDAV\Schedule\Plugin { } /** + * This method handler is invoked during fetching of properties. + * + * We use this event to add calendar-auto-schedule-specific properties. + * + * @param PropFind $propFind + * @param INode $node + * @return void + */ + function propFind(PropFind $propFind, INode $node) { + // overwrite Sabre/Dav's implementation + $propFind->handle('{' . self::NS_CALDAV . '}calendar-user-type', function() use ($node) { + $calendarUserType = '{' . self::NS_CALDAV . '}calendar-user-type'; + $props = $node->getProperties([$calendarUserType]); + + if (isset($props[$calendarUserType])) { + return $props[$calendarUserType]; + } + + return 'INDIVIDUAL'; + }); + + parent::propFind($propFind, $node); + } + + /** * Returns a list of addresses that are associated with a principal. * * @param string $principal diff --git a/apps/dav/lib/Connector/Sabre/Principal.php b/apps/dav/lib/Connector/Sabre/Principal.php index cbfa1bc83e0..2574fbcd436 100644 --- a/apps/dav/lib/Connector/Sabre/Principal.php +++ b/apps/dav/lib/Connector/Sabre/Principal.php @@ -1,6 +1,7 @@ <?php /** * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2018, Georg Ehrke * * @author Bart Visscher <bartv@thisnet.nl> * @author Jakob Sack <mail@jakobsack.de> @@ -11,6 +12,7 @@ * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Thomas Tanghus <thomas@tanghus.net> * @author Vincent Petry <pvince81@owncloud.com> + * @author Georg Ehrke <oc.list@georgehrke.com> * * @license AGPL-3.0 * @@ -249,6 +251,23 @@ class Principal implements BackendInterface { }, []); break; + case '{DAV:}displayname': + $users = $this->userManager->searchDisplayName($value); + + $results[] = array_reduce($users, function(array $carry, IUser $user) use ($restrictGroups) { + // is sharing restricted to groups only? + if ($restrictGroups !== false) { + $userGroups = $this->groupManager->getUserGroupIds($user); + if (count(array_intersect($userGroups, $restrictGroups)) === 0) { + return $carry; + } + } + + $carry[] = $this->principalPrefix . '/' . $user->getUID(); + return $carry; + }, []); + break; + default: $results[] = []; break; @@ -263,11 +282,11 @@ class Principal implements BackendInterface { switch ($test) { case 'anyof': - return array_unique(array_merge(...$results)); + return array_values(array_unique(array_merge(...$results))); case 'allof': default: - return array_intersect(...$results); + return array_values(array_intersect(...$results)); } } @@ -354,6 +373,7 @@ class Principal implements BackendInterface { $principal = [ 'uri' => $this->principalPrefix . '/' . $userId, '{DAV:}displayname' => is_null($displayName) ? $userId : $displayName, + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL', ]; $email = $user->getEMailAddress(); diff --git a/apps/dav/lib/DAV/GroupPrincipalBackend.php b/apps/dav/lib/DAV/GroupPrincipalBackend.php index 1f182445dbd..166af7c6b27 100644 --- a/apps/dav/lib/DAV/GroupPrincipalBackend.php +++ b/apps/dav/lib/DAV/GroupPrincipalBackend.php @@ -1,9 +1,11 @@ <?php /** * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2018, Georg Ehrke * * @author Roeland Jago Douma <roeland@famdouma.nl> * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Georg Ehrke <oc.list@georgehrke.com> * * @license AGPL-3.0 * @@ -24,6 +26,9 @@ namespace OCA\DAV\DAV; use OCP\IGroup; use OCP\IGroupManager; +use OCP\IUserSession; +use OCP\Share\IManager as IShareManager; +use OCP\IL10N; use OCP\IUser; use Sabre\DAV\Exception; use \Sabre\DAV\PropPatch; @@ -36,11 +41,29 @@ class GroupPrincipalBackend implements BackendInterface { /** @var IGroupManager */ private $groupManager; + /** @var IUserSession */ + private $userSession; + + /** @var IShareManager */ + private $shareManager; + + /** @var IL10N */ + private $l10n; + /** * @param IGroupManager $IGroupManager + * @param IUserSession $userSession + * @param IShareManager $shareManager + * @param IL10N $l10n */ - public function __construct(IGroupManager $IGroupManager) { + public function __construct(IGroupManager $IGroupManager, + IUserSession $userSession, + IShareManager $shareManager, + IL10N $l10n) { $this->groupManager = $IGroupManager; + $this->userSession = $userSession; + $this->shareManager = $shareManager; + $this->l10n = $l10n; } /** @@ -161,7 +184,71 @@ class GroupPrincipalBackend implements BackendInterface { * @return array */ function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') { - return []; + $results = []; + + if (\count($searchProperties) === 0) { + return []; + } + if ($prefixPath !== self::PRINCIPAL_PREFIX) { + return []; + } + // If sharing is disabled, return the empty array + $shareAPIEnabled = $this->shareManager->shareApiEnabled(); + if (!$shareAPIEnabled) { + return []; + } + + // If sharing is restricted to group members only, + // return only members that have groups in common + $restrictGroups = false; + if ($this->shareManager->shareWithGroupMembersOnly()) { + $user = $this->userSession->getUser(); + if (!$user) { + return []; + } + + $restrictGroups = $this->groupManager->getUserGroupIds($user); + } + + foreach ($searchProperties as $prop => $value) { + switch ($prop) { + case '{DAV:}displayname': + $groups = $this->groupManager->search($value); + + $results[] = array_reduce($groups, function(array $carry, IGroup $group) use ($restrictGroups) { + $gid = $group->getGID(); + // is sharing restricted to groups only? + if ($restrictGroups !== false) { + if (!\in_array($gid, $restrictGroups, true)) { + return $carry; + } + } + + $carry[] = self::PRINCIPAL_PREFIX . '/' . $gid; + return $carry; + }, []); + break; + + default: + $results[] = []; + break; + } + } + + // results is an array of arrays, so this is not the first search result + // but the results of the first searchProperty + if (count($results) === 1) { + return $results[0]; + } + + switch ($test) { + case 'anyof': + return array_values(array_unique(array_merge(...$results))); + + case 'allof': + default: + return array_values(array_intersect(...$results)); + } } /** @@ -170,7 +257,34 @@ class GroupPrincipalBackend implements BackendInterface { * @return string */ function findByUri($uri, $principalPrefix) { - return ''; + // If sharing is disabled, return the empty array + $shareAPIEnabled = $this->shareManager->shareApiEnabled(); + if (!$shareAPIEnabled) { + return null; + } + + // If sharing is restricted to group members only, + // return only members that have groups in common + $restrictGroups = false; + if ($this->shareManager->shareWithGroupMembersOnly()) { + $user = $this->userSession->getUser(); + if (!$user) { + return null; + } + + $restrictGroups = $this->groupManager->getUserGroupIds($user); + } + + if (strpos($uri, 'principal:principals/groups/') === 0) { + $name = urlencode(substr($uri, 28)); + if ($restrictGroups !== false && !\in_array($name, $restrictGroups, true)) { + return null; + } + + return substr($uri, 10); + } + + return null; } /** @@ -179,12 +293,12 @@ class GroupPrincipalBackend implements BackendInterface { */ protected function groupToPrincipal($group) { $groupId = $group->getGID(); - $principal = [ + + return [ 'uri' => 'principals/groups/' . urlencode($groupId), - '{DAV:}displayname' => $groupId, + '{DAV:}displayname' => $this->l10n->t('%s (group)', [$groupId]), + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP', ]; - - return $principal; } /** @@ -192,11 +306,20 @@ class GroupPrincipalBackend implements BackendInterface { * @return array */ protected function userToPrincipal($user) { + $userId = $user->getUID(); + $displayName = $user->getDisplayName(); + $principal = [ - 'uri' => 'principals/users/' . $user->getUID(), - '{DAV:}displayname' => $user->getDisplayName(), + 'uri' => 'principals/users/' . $userId, + '{DAV:}displayname' => is_null($displayName) ? $userId : $displayName, + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL', ]; + $email = $user->getEMailAddress(); + if (!empty($email)) { + $principal['{http://sabredav.org/ns}email-address'] = $email; + } + return $principal; } } diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php index 9a3261c388c..a05781a7621 100644 --- a/apps/dav/lib/RootCollection.php +++ b/apps/dav/lib/RootCollection.php @@ -57,7 +57,7 @@ class RootCollection extends SimpleCollection { \OC::$server->getUserSession(), $config ); - $groupPrincipalBackend = new GroupPrincipalBackend($groupManager); + $groupPrincipalBackend = new GroupPrincipalBackend($groupManager, $userSession, $shareManager, $l10n); $calendarResourcePrincipalBackend = new ResourcePrincipalBackend($db, $userSession, $groupManager, $logger); $calendarRoomPrincipalBackend = new RoomPrincipalBackend($db, $userSession, $groupManager, $logger); // as soon as debug mode is enabled we allow listing of principals diff --git a/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTest.php b/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTest.php index 4dee0220fc8..aca36fb77ea 100644 --- a/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTest.php +++ b/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTest.php @@ -53,6 +53,9 @@ abstract class AbstractPrincipalBackendTest extends TestCase { /** @var string */ protected $principalPrefix; + /** @var string */ + protected $expectedCUType; + public function setUp() { parent::setUp(); @@ -127,16 +130,19 @@ abstract class AbstractPrincipalBackendTest extends TestCase { 'uri' => $this->principalPrefix . '/db-123', '{DAV:}displayname' => 'Resource 123', '{http://sabredav.org/ns}email-address' => 'foo@bar.com', + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->expectedCUType, ], [ 'uri' => $this->principalPrefix . '/ldap-123', '{DAV:}displayname' => 'Resource 123 ldap', '{http://sabredav.org/ns}email-address' => 'ldap@bar.com', + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->expectedCUType, ], [ 'uri' => $this->principalPrefix . '/db-456', '{DAV:}displayname' => 'Resource 456', '{http://sabredav.org/ns}email-address' => 'bli@bar.com', + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->expectedCUType, ], ], $actual); @@ -209,6 +215,7 @@ abstract class AbstractPrincipalBackendTest extends TestCase { 'uri' => $this->principalPrefix . '/db-123', '{DAV:}displayname' => 'Resource 123', '{http://sabredav.org/ns}email-address' => 'foo@bar.com', + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->expectedCUType, ], $actual); } diff --git a/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php b/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php index 90db4bb4b7b..d3c774417c0 100644 --- a/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php +++ b/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php @@ -31,5 +31,6 @@ Class ResourcePrincipalBackendTest extends AbstractPrincipalBackendTest { $this->userSession, $this->groupManager, $this->logger); $this->expectedDbTable = 'calendar_resources'; $this->principalPrefix = 'principals/calendar-resources'; + $this->expectedCUType = 'RESOURCE'; } } diff --git a/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php b/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php index b55c6ddceb6..a10aaa26b35 100644 --- a/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php +++ b/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php @@ -31,5 +31,6 @@ Class RoomPrincipalBackendTest extends AbstractPrincipalBackendTest { $this->userSession, $this->groupManager, $this->logger); $this->expectedDbTable = 'calendar_rooms'; $this->principalPrefix = 'principals/calendar-rooms'; + $this->expectedCUType = 'ROOM'; } } diff --git a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php index 01907c85836..b72ae0a743d 100644 --- a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php @@ -1,12 +1,14 @@ <?php /** * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2018, Georg Ehrke * * @author Joas Schilling <coding@schilljs.com> * @author Lukas Reschke <lukas@statuscode.ch> * @author Roeland Jago Douma <roeland@famdouma.nl> * @author Thomas Müller <thomas.mueller@tmit.eu> * @author Vincent Petry <pvince81@owncloud.com> + * @author Georg Ehrke <oc.list@georgehrke.com> * * @license AGPL-3.0 * @@ -38,16 +40,22 @@ use OCP\IUserManager; use Test\TestCase; class PrincipalTest extends TestCase { + /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */ private $userManager; + /** @var \OCA\DAV\Connector\Sabre\Principal */ private $connector; + /** @var IGroupManager | \PHPUnit_Framework_MockObject_MockObject */ private $groupManager; + /** @var IManager | \PHPUnit_Framework_MockObject_MockObject */ private $shareManager; + /** @var IUserSession | \PHPUnit_Framework_MockObject_MockObject */ private $userSession; + /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */ private $config; @@ -94,7 +102,7 @@ class PrincipalTest extends TestCase { $barUser ->expects($this->exactly(1)) ->method('getEMailAddress') - ->will($this->returnValue('bar@owncloud.org')); + ->will($this->returnValue('bar@nextcloud.com')); $this->userManager ->expects($this->once()) ->method('search') @@ -104,12 +112,14 @@ class PrincipalTest extends TestCase { $expectedResponse = [ 0 => [ 'uri' => 'principals/users/foo', - '{DAV:}displayname' => 'Dr. Foo-Bar' + '{DAV:}displayname' => 'Dr. Foo-Bar', + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL', ], 1 => [ 'uri' => 'principals/users/bar', '{DAV:}displayname' => 'bar', - '{http://sabredav.org/ns}email-address' => 'bar@owncloud.org' + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL', + '{http://sabredav.org/ns}email-address' => 'bar@nextcloud.com', ] ]; $response = $this->connector->getPrincipalsByPrefix('principals/users'); @@ -141,7 +151,8 @@ class PrincipalTest extends TestCase { $expectedResponse = [ 'uri' => 'principals/users/foo', - '{DAV:}displayname' => 'foo' + '{DAV:}displayname' => 'foo', + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL', ]; $response = $this->connector->getPrincipalByPath('principals/users/foo'); $this->assertSame($expectedResponse, $response); @@ -152,7 +163,7 @@ class PrincipalTest extends TestCase { $fooUser ->expects($this->exactly(1)) ->method('getEMailAddress') - ->will($this->returnValue('foo@owncloud.org')); + ->will($this->returnValue('foo@nextcloud.com')); $fooUser ->expects($this->exactly(1)) ->method('getUID') @@ -166,7 +177,8 @@ class PrincipalTest extends TestCase { $expectedResponse = [ 'uri' => 'principals/users/foo', '{DAV:}displayname' => 'foo', - '{http://sabredav.org/ns}email-address' => 'foo@owncloud.org' + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL', + '{http://sabredav.org/ns}email-address' => 'foo@nextcloud.com', ]; $response = $this->connector->getPrincipalByPath('principals/users/foo'); $this->assertSame($expectedResponse, $response); @@ -283,7 +295,7 @@ class PrincipalTest extends TestCase { /** * @dataProvider searchPrincipalsDataProvider */ - public function testSearchPrincipals($sharingEnabled, $groupsOnly, $result) { + public function testSearchPrincipals($sharingEnabled, $groupsOnly, $test, $result) { $this->shareManager->expects($this->once()) ->method('shareAPIEnabled') ->will($this->returnValue($sharingEnabled)); @@ -302,7 +314,7 @@ class PrincipalTest extends TestCase { $this->groupManager->expects($this->at(0)) ->method('getUserGroupIds') ->with($user) - ->will($this->returnValue(['group1', 'group2'])); + ->will($this->returnValue(['group1', 'group2', 'group5'])); } } else { $this->shareManager->expects($this->never()) @@ -315,15 +327,25 @@ class PrincipalTest extends TestCase { $user2->method('getUID')->will($this->returnValue('user2')); $user3 = $this->createMock(IUser::class); $user3->method('getUID')->will($this->returnValue('user3')); + $user4 = $this->createMock(IUser::class); + $user4->method('getUID')->will($this->returnValue('user4')); if ($sharingEnabled) { $this->userManager->expects($this->at(0)) ->method('getByEmail') - ->with('user') + ->with('user@example.com') ->will($this->returnValue([$user2, $user3])); + + $this->userManager->expects($this->at(1)) + ->method('searchDisplayName') + ->with('User 12') + ->will($this->returnValue([$user3, $user4])); } else { $this->userManager->expects($this->never()) ->method('getByEmail'); + + $this->userManager->expects($this->never()) + ->method('searchDisplayName'); } if ($sharingEnabled && $groupsOnly) { @@ -335,18 +357,30 @@ class PrincipalTest extends TestCase { ->method('getUserGroupIds') ->with($user3) ->will($this->returnValue(['group3', 'group4'])); + $this->groupManager->expects($this->at(3)) + ->method('getUserGroupIds') + ->with($user3) + ->will($this->returnValue(['group3', 'group4'])); + $this->groupManager->expects($this->at(4)) + ->method('getUserGroupIds') + ->with($user4) + ->will($this->returnValue(['group4', 'group5'])); } $this->assertEquals($result, $this->connector->searchPrincipals('principals/users', - ['{http://sabredav.org/ns}email-address' => 'user'])); + ['{http://sabredav.org/ns}email-address' => 'user@example.com', + '{DAV:}displayname' => 'User 12'], $test)); } public function searchPrincipalsDataProvider() { return [ - [true, false, ['principals/users/user2', 'principals/users/user3']], - [true, true, ['principals/users/user2']], - [false, false, []], + [true, false, 'allof', ['principals/users/user3']], + [true, false, 'anyof', ['principals/users/user2', 'principals/users/user3', 'principals/users/user4']], + [true, true, 'allof', []], + [true, true, 'anyof', ['principals/users/user2', 'principals/users/user4']], + [false, false, 'allof', []], + [false, false, 'anyof', []], ]; } diff --git a/apps/dav/tests/unit/DAV/GroupPrincipalTest.php b/apps/dav/tests/unit/DAV/GroupPrincipalTest.php index 214054176ae..af94df05254 100644 --- a/apps/dav/tests/unit/DAV/GroupPrincipalTest.php +++ b/apps/dav/tests/unit/DAV/GroupPrincipalTest.php @@ -1,10 +1,12 @@ <?php /** * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2018, Georg Ehrke * * @author Joas Schilling <coding@schilljs.com> * @author Roeland Jago Douma <roeland@famdouma.nl> * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Georg Ehrke <oc.list@georgehrke.com> * * @license AGPL-3.0 * @@ -26,22 +28,42 @@ namespace OCA\DAV\Tests\unit\DAV; use OC\Group\Group; use OCA\DAV\DAV\GroupPrincipalBackend; +use OCP\IGroup; use OCP\IGroupManager; -use PHPUnit_Framework_MockObject_MockObject; +use OCP\IL10N; +use OCP\IUser; +use OCP\IUserSession; +use OCP\Share\IManager; use \Sabre\DAV\PropPatch; class GroupPrincipalTest extends \Test\TestCase { - /** @var IGroupManager | PHPUnit_Framework_MockObject_MockObject */ + /** @var IGroupManager | \PHPUnit_Framework_MockObject_MockObject */ private $groupManager; + /** @var IUserSession | \PHPUnit_Framework_MockObject_MockObject */ + private $userSession; + + /** @var IManager | \PHPUnit_Framework_MockObject_MockObject */ + private $shareManager; + + /** @var IL10N | \PHPUnit_Framework_MockObject_MockObject */ + private $l10n; + /** @var GroupPrincipalBackend */ private $connector; public function setUp() { $this->groupManager = $this->createMock(IGroupManager::class); + $this->userSession = $this->createMock(IUserSession::class); + $this->shareManager = $this->createMock(IManager::class); + $this->l10n = $this->createMock(IL10N::class); - $this->connector = new GroupPrincipalBackend($this->groupManager); + $this->connector = new GroupPrincipalBackend( + $this->groupManager, + $this->userSession, + $this->shareManager, + $this->l10n); parent::setUp(); } @@ -59,14 +81,26 @@ class GroupPrincipalTest extends \Test\TestCase { ->with('') ->will($this->returnValue([$group1, $group2])); + $this->l10n->expects($this->at(0)) + ->method('t') + ->with('%s (group)', ['foo']) + ->will($this->returnValue('foo (Gruppe)')); + + $this->l10n->expects($this->at(1)) + ->method('t') + ->with('%s (group)', ['bar']) + ->will($this->returnValue('bar (Gruppe)')); + $expectedResponse = [ 0 => [ 'uri' => 'principals/groups/foo', - '{DAV:}displayname' => 'foo' + '{DAV:}displayname' => 'foo (Gruppe)', + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP', ], 1 => [ 'uri' => 'principals/groups/bar', - '{DAV:}displayname' => 'bar', + '{DAV:}displayname' => 'bar (Gruppe)', + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP', ] ]; $response = $this->connector->getPrincipalsByPrefix('principals/groups'); @@ -92,9 +126,15 @@ class GroupPrincipalTest extends \Test\TestCase { ->with('foo') ->will($this->returnValue($group1)); + $this->l10n->expects($this->at(0)) + ->method('t') + ->with('%s (group)', ['foo']) + ->will($this->returnValue('foo (Gruppe)')); + $expectedResponse = [ 'uri' => 'principals/groups/foo', - '{DAV:}displayname' => 'foo' + '{DAV:}displayname' => 'foo (Gruppe)', + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP', ]; $response = $this->connector->getPrincipalByPath('principals/groups/foo'); $this->assertSame($expectedResponse, $response); @@ -108,9 +148,15 @@ class GroupPrincipalTest extends \Test\TestCase { ->with('foo') ->will($this->returnValue($fooUser)); + $this->l10n->expects($this->at(0)) + ->method('t') + ->with('%s (group)', ['foo']) + ->will($this->returnValue('foo (Gruppe)')); + $expectedResponse = [ 'uri' => 'principals/groups/foo', - '{DAV:}displayname' => 'foo', + '{DAV:}displayname' => 'foo (Gruppe)', + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP', ]; $response = $this->connector->getPrincipalByPath('principals/groups/foo'); $this->assertSame($expectedResponse, $response); @@ -135,9 +181,15 @@ class GroupPrincipalTest extends \Test\TestCase { ->with('foo/bar') ->will($this->returnValue($group1)); + $this->l10n->expects($this->at(0)) + ->method('t') + ->with('%s (group)', ['foo/bar']) + ->will($this->returnValue('foo/bar (Gruppe)')); + $expectedResponse = [ 'uri' => 'principals/groups/foo%2Fbar', - '{DAV:}displayname' => 'foo/bar' + '{DAV:}displayname' => 'foo/bar (Gruppe)', + '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP', ]; $response = $this->connector->getPrincipalByPath('principals/groups/foo/bar'); $this->assertSame($expectedResponse, $response); @@ -165,10 +217,129 @@ class GroupPrincipalTest extends \Test\TestCase { $this->assertSame(0, $this->connector->updatePrincipal('foo', new PropPatch(array()))); } - public function testSearchPrincipals() { + public function testSearchPrincipalsWithEmptySearchProperties() { $this->assertSame([], $this->connector->searchPrincipals('principals/groups', [])); } + public function testSearchPrincipalsWithWrongPrefixPath() { + $this->assertSame([], $this->connector->searchPrincipals('principals/users', + ['{DAV:}displayname' => 'Foo'])); + } + + /** + * @dataProvider searchPrincipalsDataProvider + */ + public function testSearchPrincipals($sharingEnabled, $groupsOnly, $test, $result) { + $this->shareManager->expects($this->once()) + ->method('shareAPIEnabled') + ->will($this->returnValue($sharingEnabled)); + + if ($sharingEnabled) { + $this->shareManager->expects($this->once()) + ->method('shareWithGroupMembersOnly') + ->will($this->returnValue($groupsOnly)); + + if ($groupsOnly) { + $user = $this->createMock(IUser::class); + $this->userSession->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($user)); + + $this->groupManager->expects($this->once()) + ->method('getUserGroupIds') + ->with($user) + ->will($this->returnValue(['group1', 'group2', 'group5'])); + } + } else { + $this->shareManager->expects($this->never()) + ->method('shareWithGroupMembersOnly'); + $this->groupManager->expects($this->never()) + ->method($this->anything()); + } + + $group1 = $this->createMock(IGroup::class); + $group1->method('getGID')->will($this->returnValue('group1')); + $group2 = $this->createMock(IGroup::class); + $group2->method('getGID')->will($this->returnValue('group2')); + $group3 = $this->createMock(IGroup::class); + $group3->method('getGID')->will($this->returnValue('group3')); + $group4 = $this->createMock(IGroup::class); + $group4->method('getGID')->will($this->returnValue('group4')); + $group5 = $this->createMock(IGroup::class); + $group5->method('getGID')->will($this->returnValue('group5')); + + if ($sharingEnabled) { + $this->groupManager->expects($this->once()) + ->method('search') + ->with('Foo') + ->will($this->returnValue([$group1, $group2, $group3, $group4, $group5])); + } else { + $this->groupManager->expects($this->never()) + ->method('search'); + } + + $this->assertSame($result, $this->connector->searchPrincipals('principals/groups', + ['{DAV:}displayname' => 'Foo'], $test)); + } + + public function searchPrincipalsDataProvider() { + return [ + [true, false, 'allof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group3', 'principals/groups/group4', 'principals/groups/group5']], + [true, false, 'anyof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group3', 'principals/groups/group4', 'principals/groups/group5']], + [true, true, 'allof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group5']], + [true, true, 'anyof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group5']], + [false, false, 'allof', []], + [false, false, 'anyof', []], + ]; + } + + /** + * @dataProvider findByUriDataProvider + */ + public function testFindByUri($sharingEnabled, $groupsOnly, $findUri, $result) { + $this->shareManager->expects($this->once()) + ->method('shareAPIEnabled') + ->will($this->returnValue($sharingEnabled)); + + if ($sharingEnabled) { + $this->shareManager->expects($this->once()) + ->method('shareWithGroupMembersOnly') + ->will($this->returnValue($groupsOnly)); + + if ($groupsOnly) { + $user = $this->createMock(IUser::class); + $this->userSession->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($user)); + + $this->groupManager->expects($this->at(0)) + ->method('getUserGroupIds') + ->with($user) + ->will($this->returnValue(['group1', 'group2', 'group5'])); + } + } else { + $this->shareManager->expects($this->never()) + ->method('shareWithGroupMembersOnly'); + $this->groupManager->expects($this->never()) + ->method($this->anything()); + } + + $this->assertEquals($result, $this->connector->findByUri($findUri, 'principals/groups')); + } + + public function findByUriDataProvider() { + return [ + [false, false, 'principal:principals/groups/group1', null], + [false, false, 'principal:principals/groups/group3', null], + [false, true, 'principal:principals/groups/group1', null], + [false, true, 'principal:principals/groups/group3', null], + [true, true, 'principal:principals/groups/group1', 'principals/groups/group1'], + [true, true, 'principal:principals/groups/group3', null], + [true, false, 'principal:principals/groups/group1', 'principals/groups/group1'], + [true, false, 'principal:principals/groups/group3', 'principals/groups/group3'], + ]; + } + /** * @return Group|\PHPUnit_Framework_MockObject_MockObject */ |