GroupPrincipalTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. * @copyright Copyright (c) 2018, Georg Ehrke
  5. *
  6. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  7. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  8. * @author Georg Ehrke <oc.list@georgehrke.com>
  9. * @author Joas Schilling <coding@schilljs.com>
  10. * @author John Molakvoæ <skjnldsv@protonmail.com>
  11. * @author Morris Jobke <hey@morrisjobke.de>
  12. * @author Roeland Jago Douma <roeland@famdouma.nl>
  13. * @author Thomas Citharel <nextcloud@tcit.fr>
  14. * @author Thomas Müller <thomas.mueller@tmit.eu>
  15. *
  16. * @license AGPL-3.0
  17. *
  18. * This code is free software: you can redistribute it and/or modify
  19. * it under the terms of the GNU Affero General Public License, version 3,
  20. * as published by the Free Software Foundation.
  21. *
  22. * This program is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. * GNU Affero General Public License for more details.
  26. *
  27. * You should have received a copy of the GNU Affero General Public License, version 3,
  28. * along with this program. If not, see <http://www.gnu.org/licenses/>
  29. *
  30. */
  31. namespace OCA\DAV\Tests\unit\DAV;
  32. use OC\Group\Group;
  33. use OCA\DAV\DAV\GroupPrincipalBackend;
  34. use OCP\IConfig;
  35. use OCP\IGroup;
  36. use OCP\IGroupManager;
  37. use OCP\IUser;
  38. use OCP\IUserSession;
  39. use OCP\Share\IManager;
  40. use PHPUnit\Framework\MockObject\MockObject;
  41. use Sabre\DAV\PropPatch;
  42. class GroupPrincipalTest extends \Test\TestCase {
  43. /** @var IConfig|MockObject */
  44. private $config;
  45. /** @var IGroupManager | MockObject */
  46. private $groupManager;
  47. /** @var IUserSession | MockObject */
  48. private $userSession;
  49. /** @var IManager | MockObject */
  50. private $shareManager;
  51. /** @var GroupPrincipalBackend */
  52. private $connector;
  53. protected function setUp(): void {
  54. $this->groupManager = $this->createMock(IGroupManager::class);
  55. $this->userSession = $this->createMock(IUserSession::class);
  56. $this->shareManager = $this->createMock(IManager::class);
  57. $this->config = $this->createMock(IConfig::class);
  58. $this->connector = new GroupPrincipalBackend(
  59. $this->groupManager,
  60. $this->userSession,
  61. $this->shareManager,
  62. $this->config
  63. );
  64. parent::setUp();
  65. }
  66. public function testGetPrincipalsByPrefixWithoutPrefix(): void {
  67. $response = $this->connector->getPrincipalsByPrefix('');
  68. $this->assertSame([], $response);
  69. }
  70. public function testGetPrincipalsByPrefixWithUsers(): void {
  71. $group1 = $this->mockGroup('foo');
  72. $group2 = $this->mockGroup('bar');
  73. $this->groupManager
  74. ->expects($this->once())
  75. ->method('search')
  76. ->with('')
  77. ->willReturn([$group1, $group2]);
  78. $expectedResponse = [
  79. 0 => [
  80. 'uri' => 'principals/groups/foo',
  81. '{DAV:}displayname' => 'Group foo',
  82. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP',
  83. ],
  84. 1 => [
  85. 'uri' => 'principals/groups/bar',
  86. '{DAV:}displayname' => 'Group bar',
  87. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP',
  88. ]
  89. ];
  90. $response = $this->connector->getPrincipalsByPrefix('principals/groups');
  91. $this->assertSame($expectedResponse, $response);
  92. }
  93. public function testGetPrincipalsByPrefixEmpty(): void {
  94. $this->groupManager
  95. ->expects($this->once())
  96. ->method('search')
  97. ->with('')
  98. ->willReturn([]);
  99. $response = $this->connector->getPrincipalsByPrefix('principals/groups');
  100. $this->assertSame([], $response);
  101. }
  102. public function testGetPrincipalsByPathWithoutMail(): void {
  103. $group1 = $this->mockGroup('foo');
  104. $this->groupManager
  105. ->expects($this->once())
  106. ->method('get')
  107. ->with('foo')
  108. ->willReturn($group1);
  109. $expectedResponse = [
  110. 'uri' => 'principals/groups/foo',
  111. '{DAV:}displayname' => 'Group foo',
  112. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP',
  113. ];
  114. $response = $this->connector->getPrincipalByPath('principals/groups/foo');
  115. $this->assertSame($expectedResponse, $response);
  116. }
  117. public function testGetPrincipalsByPathWithMail(): void {
  118. $fooUser = $this->mockGroup('foo');
  119. $this->groupManager
  120. ->expects($this->once())
  121. ->method('get')
  122. ->with('foo')
  123. ->willReturn($fooUser);
  124. $expectedResponse = [
  125. 'uri' => 'principals/groups/foo',
  126. '{DAV:}displayname' => 'Group foo',
  127. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP',
  128. ];
  129. $response = $this->connector->getPrincipalByPath('principals/groups/foo');
  130. $this->assertSame($expectedResponse, $response);
  131. }
  132. public function testGetPrincipalsByPathEmpty(): void {
  133. $this->groupManager
  134. ->expects($this->once())
  135. ->method('get')
  136. ->with('foo')
  137. ->willReturn(null);
  138. $response = $this->connector->getPrincipalByPath('principals/groups/foo');
  139. $this->assertSame(null, $response);
  140. }
  141. public function testGetPrincipalsByPathGroupWithSlash(): void {
  142. $group1 = $this->mockGroup('foo/bar');
  143. $this->groupManager
  144. ->expects($this->once())
  145. ->method('get')
  146. ->with('foo/bar')
  147. ->willReturn($group1);
  148. $expectedResponse = [
  149. 'uri' => 'principals/groups/foo%2Fbar',
  150. '{DAV:}displayname' => 'Group foo/bar',
  151. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP',
  152. ];
  153. $response = $this->connector->getPrincipalByPath('principals/groups/foo/bar');
  154. $this->assertSame($expectedResponse, $response);
  155. }
  156. public function testGetPrincipalsByPathGroupWithHash(): void {
  157. $group1 = $this->mockGroup('foo#bar');
  158. $this->groupManager
  159. ->expects($this->once())
  160. ->method('get')
  161. ->with('foo#bar')
  162. ->willReturn($group1);
  163. $expectedResponse = [
  164. 'uri' => 'principals/groups/foo%23bar',
  165. '{DAV:}displayname' => 'Group foo#bar',
  166. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP',
  167. ];
  168. $response = $this->connector->getPrincipalByPath('principals/groups/foo#bar');
  169. $this->assertSame($expectedResponse, $response);
  170. }
  171. public function testGetGroupMemberSet(): void {
  172. $response = $this->connector->getGroupMemberSet('principals/groups/foo');
  173. $this->assertSame([], $response);
  174. }
  175. public function testGetGroupMembership(): void {
  176. $response = $this->connector->getGroupMembership('principals/groups/foo');
  177. $this->assertSame([], $response);
  178. }
  179. public function testSetGroupMembership(): void {
  180. $this->expectException(\Sabre\DAV\Exception::class);
  181. $this->expectExceptionMessage('Setting members of the group is not supported yet');
  182. $this->connector->setGroupMemberSet('principals/groups/foo', ['foo']);
  183. }
  184. public function testUpdatePrincipal(): void {
  185. $this->assertSame(0, $this->connector->updatePrincipal('foo', new PropPatch([])));
  186. }
  187. public function testSearchPrincipalsWithEmptySearchProperties(): void {
  188. $this->assertSame([], $this->connector->searchPrincipals('principals/groups', []));
  189. }
  190. public function testSearchPrincipalsWithWrongPrefixPath(): void {
  191. $this->assertSame([], $this->connector->searchPrincipals('principals/users',
  192. ['{DAV:}displayname' => 'Foo']));
  193. }
  194. /**
  195. * @dataProvider searchPrincipalsDataProvider
  196. * @param bool $sharingEnabled
  197. * @param bool $groupSharingEnabled
  198. * @param bool $groupsOnly
  199. * @param string $test
  200. * @param array $result
  201. */
  202. public function testSearchPrincipals(bool $sharingEnabled, bool $groupSharingEnabled, bool $groupsOnly, string $test, array $result): void {
  203. $this->shareManager->expects($this->once())
  204. ->method('shareAPIEnabled')
  205. ->willReturn($sharingEnabled);
  206. $this->shareManager->expects($sharingEnabled ? $this->once() : $this->never())
  207. ->method('allowGroupSharing')
  208. ->willReturn($groupSharingEnabled);
  209. if ($sharingEnabled && $groupSharingEnabled) {
  210. $this->shareManager->expects($this->once())
  211. ->method('shareWithGroupMembersOnly')
  212. ->willReturn($groupsOnly);
  213. if ($groupsOnly) {
  214. $user = $this->createMock(IUser::class);
  215. $this->userSession->expects($this->once())
  216. ->method('getUser')
  217. ->willReturn($user);
  218. $this->groupManager->expects($this->once())
  219. ->method('getUserGroupIds')
  220. ->with($user)
  221. ->willReturn(['group1', 'group2', 'group5']);
  222. }
  223. } else {
  224. $this->shareManager->expects($this->never())
  225. ->method('shareWithGroupMembersOnly');
  226. $this->groupManager->expects($this->never())
  227. ->method($this->anything());
  228. }
  229. $group1 = $this->createMock(IGroup::class);
  230. $group1->method('getGID')->willReturn('group1');
  231. $group2 = $this->createMock(IGroup::class);
  232. $group2->method('getGID')->willReturn('group2');
  233. $group3 = $this->createMock(IGroup::class);
  234. $group3->method('getGID')->willReturn('group3');
  235. $group4 = $this->createMock(IGroup::class);
  236. $group4->method('getGID')->willReturn('group4');
  237. $group5 = $this->createMock(IGroup::class);
  238. $group5->method('getGID')->willReturn('group5');
  239. if ($sharingEnabled && $groupSharingEnabled) {
  240. $this->groupManager->expects($this->once())
  241. ->method('search')
  242. ->with('Foo')
  243. ->willReturn([$group1, $group2, $group3, $group4, $group5]);
  244. } else {
  245. $this->groupManager->expects($this->never())
  246. ->method('search');
  247. }
  248. $this->assertSame($result, $this->connector->searchPrincipals('principals/groups',
  249. ['{DAV:}displayname' => 'Foo'], $test));
  250. }
  251. public function searchPrincipalsDataProvider() {
  252. return [
  253. [true, true, false, 'allof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group3', 'principals/groups/group4', 'principals/groups/group5']],
  254. [true, true, false, 'anyof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group3', 'principals/groups/group4', 'principals/groups/group5']],
  255. [true, true, true, 'allof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group5']],
  256. [true, true, true, 'anyof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group5']],
  257. [true, false, false, 'allof', []],
  258. [false, true, false, 'anyof', []],
  259. [false, false, false, 'allof', []],
  260. [false, false, false, 'anyof', []],
  261. ];
  262. }
  263. /**
  264. * @dataProvider findByUriDataProvider
  265. * @param bool $sharingEnabled
  266. * @param bool $groupSharingEnabled
  267. * @param bool $groupsOnly
  268. * @param string $findUri
  269. * @param string|null $result
  270. */
  271. public function testFindByUri(bool $sharingEnabled, bool $groupSharingEnabled, bool $groupsOnly, string $findUri, ?string $result): void {
  272. $this->shareManager->expects($this->once())
  273. ->method('shareAPIEnabled')
  274. ->willReturn($sharingEnabled);
  275. $this->shareManager->expects($sharingEnabled ? $this->once() : $this->never())
  276. ->method('allowGroupSharing')
  277. ->willReturn($groupSharingEnabled);
  278. if ($sharingEnabled && $groupSharingEnabled) {
  279. $this->shareManager->expects($this->once())
  280. ->method('shareWithGroupMembersOnly')
  281. ->willReturn($groupsOnly);
  282. if ($groupsOnly) {
  283. $user = $this->createMock(IUser::class);
  284. $this->userSession->expects($this->once())
  285. ->method('getUser')
  286. ->willReturn($user);
  287. $this->groupManager->expects($this->once())
  288. ->method('getUserGroupIds')
  289. ->with($user)
  290. ->willReturn(['group1', 'group2', 'group5']);
  291. }
  292. } else {
  293. $this->shareManager->expects($this->never())
  294. ->method('shareWithGroupMembersOnly');
  295. $this->groupManager->expects($this->never())
  296. ->method($this->anything());
  297. }
  298. $this->assertEquals($result, $this->connector->findByUri($findUri, 'principals/groups'));
  299. }
  300. public function findByUriDataProvider() {
  301. return [
  302. [false, false, false, 'principal:principals/groups/group1', null],
  303. [false, false, false, 'principal:principals/groups/group3', null],
  304. [false, true, false, 'principal:principals/groups/group1', null],
  305. [false, true, false, 'principal:principals/groups/group3', null],
  306. [false, false, true, 'principal:principals/groups/group1', null],
  307. [false, false, true, 'principal:principals/groups/group3', null],
  308. [true, false, true, 'principal:principals/groups/group1', null],
  309. [true, false, true, 'principal:principals/groups/group3', null],
  310. [true, true, true, 'principal:principals/groups/group1', 'principals/groups/group1'],
  311. [true, true, true, 'principal:principals/groups/group3', null],
  312. [true, true, false, 'principal:principals/groups/group1', 'principals/groups/group1'],
  313. [true, true, false, 'principal:principals/groups/group3', 'principals/groups/group3'],
  314. ];
  315. }
  316. /**
  317. * @return Group|MockObject
  318. */
  319. private function mockGroup($gid) {
  320. $fooGroup = $this->createMock(Group::class);
  321. $fooGroup
  322. ->expects($this->exactly(1))
  323. ->method('getGID')
  324. ->willReturn($gid);
  325. $fooGroup
  326. ->expects($this->exactly(1))
  327. ->method('getDisplayName')
  328. ->willReturn('Group '.$gid);
  329. return $fooGroup;
  330. }
  331. }