GroupsControllerTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\Provisioning_API\Tests\Controller;
  8. use OC\Group\Manager;
  9. use OC\SubAdmin;
  10. use OC\User\NoUserException;
  11. use OCA\Provisioning_API\Controller\GroupsController;
  12. use OCP\Accounts\IAccountManager;
  13. use OCP\IConfig;
  14. use OCP\IRequest;
  15. use OCP\IUser;
  16. use OCP\IUserManager;
  17. use OCP\IUserSession;
  18. use OCP\L10N\IFactory;
  19. use OCP\UserInterface;
  20. use Psr\Log\LoggerInterface;
  21. class GroupsControllerTest extends \Test\TestCase {
  22. /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
  23. protected $request;
  24. /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
  25. protected $userManager;
  26. /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
  27. protected $config;
  28. /** @var Manager|\PHPUnit\Framework\MockObject\MockObject */
  29. protected $groupManager;
  30. /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
  31. protected $userSession;
  32. /** @var IAccountManager|\PHPUnit\Framework\MockObject\MockObject */
  33. protected $accountManager;
  34. /** @var IFactory|\PHPUnit\Framework\MockObject\MockObject */
  35. protected $l10nFactory;
  36. /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
  37. protected $logger;
  38. /** @var SubAdmin|\PHPUnit\Framework\MockObject\MockObject */
  39. protected $subAdminManager;
  40. /** @var GroupsController|\PHPUnit\Framework\MockObject\MockObject */
  41. protected $api;
  42. protected function setUp(): void {
  43. parent::setUp();
  44. $this->request = $this->createMock(IRequest::class);
  45. $this->userManager = $this->createMock(IUserManager::class);
  46. $this->config = $this->createMock(IConfig::class);
  47. $this->groupManager = $this->createMock(Manager::class);
  48. $this->userSession = $this->createMock(IUserSession::class);
  49. $this->accountManager = $this->createMock(IAccountManager::class);
  50. $this->l10nFactory = $this->createMock(IFactory::class);
  51. $this->logger = $this->createMock(LoggerInterface::class);
  52. $this->subAdminManager = $this->createMock(SubAdmin::class);
  53. $this->groupManager
  54. ->method('getSubAdmin')
  55. ->willReturn($this->subAdminManager);
  56. $this->api = $this->getMockBuilder(GroupsController::class)
  57. ->setConstructorArgs([
  58. 'provisioning_api',
  59. $this->request,
  60. $this->userManager,
  61. $this->config,
  62. $this->groupManager,
  63. $this->userSession,
  64. $this->accountManager,
  65. $this->l10nFactory,
  66. $this->logger
  67. ])
  68. ->setMethods(['fillStorageInfo'])
  69. ->getMock();
  70. }
  71. /**
  72. * @param string $gid
  73. * @return \OCP\IGroup|\PHPUnit\Framework\MockObject\MockObject
  74. */
  75. private function createGroup($gid) {
  76. $group = $this->getMockBuilder('\OCP\IGroup')->disableOriginalConstructor()->getMock();
  77. $group
  78. ->method('getGID')
  79. ->willReturn($gid);
  80. $group
  81. ->method('getDisplayName')
  82. ->willReturn($gid.'-name');
  83. $group
  84. ->method('count')
  85. ->willReturn(123);
  86. $group
  87. ->method('countDisabled')
  88. ->willReturn(11);
  89. $group
  90. ->method('canAddUser')
  91. ->willReturn(true);
  92. $group
  93. ->method('canRemoveUser')
  94. ->willReturn(true);
  95. return $group;
  96. }
  97. /**
  98. * @param string $uid
  99. * @return \OCP\IUser|\PHPUnit\Framework\MockObject\MockObject
  100. */
  101. private function createUser($uid) {
  102. $user = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock();
  103. $user
  104. ->method('getUID')
  105. ->willReturn($uid);
  106. $backendMock = $this->createMock(UserInterface::class);
  107. $user
  108. ->method('getBackend')
  109. ->willReturn($backendMock);
  110. return $user;
  111. }
  112. private function asUser() {
  113. $user = $this->createUser('user');
  114. $this->userSession
  115. ->method('getUser')
  116. ->willReturn($user);
  117. }
  118. private function asAdmin() {
  119. $user = $this->createUser('admin');
  120. $this->userSession
  121. ->method('getUser')
  122. ->willReturn($user);
  123. $this->groupManager
  124. ->method('isAdmin')
  125. ->with('admin')
  126. ->willReturn(true);
  127. }
  128. private function asSubAdminOfGroup($group) {
  129. $user = $this->createUser('subAdmin');
  130. $this->userSession
  131. ->method('getUser')
  132. ->willReturn($user);
  133. $this->subAdminManager
  134. ->method('isSubAdminOfGroup')
  135. ->willReturnCallback(function ($_user, $_group) use ($user, $group) {
  136. if ($_user === $user && $_group === $group) {
  137. return true;
  138. }
  139. return false;
  140. });
  141. }
  142. public function dataGetGroups() {
  143. return [
  144. [null, 0, 0],
  145. ['foo', 0, 0],
  146. [null, 1, 0],
  147. [null, 0, 2],
  148. ['foo', 1, 2],
  149. ];
  150. }
  151. /**
  152. * @dataProvider dataGetGroups
  153. *
  154. * @param string|null $search
  155. * @param int|null $limit
  156. * @param int|null $offset
  157. */
  158. public function testGetGroups($search, $limit, $offset): void {
  159. $groups = [$this->createGroup('group1'), $this->createGroup('group2')];
  160. $search = $search === null ? '' : $search;
  161. $this->groupManager
  162. ->expects($this->once())
  163. ->method('search')
  164. ->with($search, $limit, $offset)
  165. ->willReturn($groups);
  166. $result = $this->api->getGroups($search, $limit, $offset);
  167. $this->assertEquals(['groups' => ['group1', 'group2']], $result->getData());
  168. }
  169. /**
  170. * @dataProvider dataGetGroups
  171. *
  172. * @param string|null $search
  173. * @param int|null $limit
  174. * @param int|null $offset
  175. */
  176. public function testGetGroupsDetails($search, $limit, $offset): void {
  177. $groups = [$this->createGroup('group1'), $this->createGroup('group2')];
  178. $search = $search === null ? '' : $search;
  179. $this->groupManager
  180. ->expects($this->once())
  181. ->method('search')
  182. ->with($search, $limit, $offset)
  183. ->willReturn($groups);
  184. $result = $this->api->getGroupsDetails($search, $limit, $offset);
  185. $this->assertEquals(['groups' => [
  186. [
  187. 'id' => 'group1',
  188. 'displayname' => 'group1-name',
  189. 'usercount' => 123,
  190. 'disabled' => 11,
  191. 'canAdd' => true,
  192. 'canRemove' => true
  193. ],
  194. [
  195. 'id' => 'group2',
  196. 'displayname' => 'group2-name',
  197. 'usercount' => 123,
  198. 'disabled' => 11,
  199. 'canAdd' => true,
  200. 'canRemove' => true
  201. ]
  202. ]], $result->getData());
  203. }
  204. public function testGetGroupAsSubadmin(): void {
  205. $group = $this->createGroup('group');
  206. $this->asSubAdminOfGroup($group);
  207. $this->groupManager
  208. ->method('get')
  209. ->with('group')
  210. ->willReturn($group);
  211. $this->groupManager
  212. ->method('groupExists')
  213. ->with('group')
  214. ->willReturn(true);
  215. $group
  216. ->method('getUsers')
  217. ->willReturn([
  218. $this->createUser('user1'),
  219. $this->createUser('user2')
  220. ]);
  221. $result = $this->api->getGroup('group');
  222. $this->assertEquals(['users' => ['user1', 'user2']], $result->getData());
  223. }
  224. public function testGetGroupAsIrrelevantSubadmin(): void {
  225. $this->expectException(\OCP\AppFramework\OCS\OCSException::class);
  226. $this->expectExceptionCode(403);
  227. $group = $this->createGroup('group');
  228. $otherGroup = $this->createGroup('otherGroup');
  229. $this->asSubAdminOfGroup($otherGroup);
  230. $this->groupManager
  231. ->method('get')
  232. ->with('group')
  233. ->willReturn($group);
  234. $this->groupManager
  235. ->method('groupExists')
  236. ->with('group')
  237. ->willReturn(true);
  238. $this->api->getGroup('group');
  239. }
  240. public function testGetGroupAsAdmin(): void {
  241. $group = $this->createGroup('group');
  242. $this->asAdmin();
  243. $this->groupManager
  244. ->method('get')
  245. ->with('group')
  246. ->willReturn($group);
  247. $this->groupManager
  248. ->method('groupExists')
  249. ->with('group')
  250. ->willReturn(true);
  251. $group
  252. ->method('getUsers')
  253. ->willReturn([
  254. $this->createUser('user1'),
  255. $this->createUser('user2')
  256. ]);
  257. $result = $this->api->getGroup('group');
  258. $this->assertEquals(['users' => ['user1', 'user2']], $result->getData());
  259. }
  260. public function testGetGroupNonExisting(): void {
  261. $this->expectException(\OCP\AppFramework\OCS\OCSException::class);
  262. $this->expectExceptionMessage('The requested group could not be found');
  263. $this->expectExceptionCode(404);
  264. $this->asUser();
  265. $this->api->getGroup($this->getUniqueID());
  266. }
  267. public function testGetSubAdminsOfGroupsNotExists(): void {
  268. $this->expectException(\OCP\AppFramework\OCS\OCSException::class);
  269. $this->expectExceptionMessage('Group does not exist');
  270. $this->expectExceptionCode(101);
  271. $this->api->getSubAdminsOfGroup('NonExistingGroup');
  272. }
  273. public function testGetSubAdminsOfGroup(): void {
  274. $group = $this->createGroup('GroupWithSubAdmins');
  275. $this->groupManager
  276. ->method('get')
  277. ->with('GroupWithSubAdmins')
  278. ->willReturn($group);
  279. $this->subAdminManager
  280. ->expects($this->once())
  281. ->method('getGroupsSubAdmins')
  282. ->with($group)
  283. ->willReturn([
  284. $this->createUser('SubAdmin1'),
  285. $this->createUser('SubAdmin2'),
  286. ]);
  287. $result = $this->api->getSubAdminsOfGroup('GroupWithSubAdmins');
  288. $this->assertEquals(['SubAdmin1', 'SubAdmin2'], $result->getData());
  289. }
  290. public function testGetSubAdminsOfGroupEmptyList(): void {
  291. $group = $this->createGroup('GroupWithOutSubAdmins');
  292. $this->groupManager
  293. ->method('get')
  294. ->with('GroupWithOutSubAdmins')
  295. ->willReturn($group);
  296. $this->subAdminManager
  297. ->expects($this->once())
  298. ->method('getGroupsSubAdmins')
  299. ->with($group)
  300. ->willReturn([
  301. ]);
  302. $result = $this->api->getSubAdminsOfGroup('GroupWithOutSubAdmins');
  303. $this->assertEquals([], $result->getData());
  304. }
  305. public function testAddGroupEmptyGroup(): void {
  306. $this->expectException(\OCP\AppFramework\OCS\OCSException::class);
  307. $this->expectExceptionMessage('Invalid group name');
  308. $this->expectExceptionCode(101);
  309. $this->api->addGroup('');
  310. }
  311. public function testAddGroupExistingGroup(): void {
  312. $this->expectException(\OCP\AppFramework\OCS\OCSException::class);
  313. $this->expectExceptionCode(102);
  314. $this->groupManager
  315. ->method('groupExists')
  316. ->with('ExistingGroup')
  317. ->willReturn(true);
  318. $this->api->addGroup('ExistingGroup');
  319. }
  320. public function testAddGroup(): void {
  321. $this->groupManager
  322. ->method('groupExists')
  323. ->with('NewGroup')
  324. ->willReturn(false);
  325. $group = $this->createGroup('NewGroup');
  326. $this->groupManager
  327. ->expects($this->once())
  328. ->method('createGroup')
  329. ->with('NewGroup')
  330. ->willReturn($group);
  331. $this->api->addGroup('NewGroup');
  332. }
  333. public function testAddGroupWithSpecialChar(): void {
  334. $this->groupManager
  335. ->method('groupExists')
  336. ->with('Iñtërnâtiônàlizætiøn')
  337. ->willReturn(false);
  338. $group = $this->createGroup('Iñtërnâtiônàlizætiøn');
  339. $this->groupManager
  340. ->expects($this->once())
  341. ->method('createGroup')
  342. ->with('Iñtërnâtiônàlizætiøn')
  343. ->willReturn($group);
  344. $this->api->addGroup('Iñtërnâtiônàlizætiøn');
  345. }
  346. public function testDeleteGroupNonExisting(): void {
  347. $this->expectException(\OCP\AppFramework\OCS\OCSException::class);
  348. $this->expectExceptionCode(101);
  349. $this->api->deleteGroup('NonExistingGroup');
  350. }
  351. public function testDeleteAdminGroup(): void {
  352. $this->expectException(\OCP\AppFramework\OCS\OCSException::class);
  353. $this->expectExceptionCode(102);
  354. $this->groupManager
  355. ->method('groupExists')
  356. ->with('admin')
  357. ->willReturn('true');
  358. $this->api->deleteGroup('admin');
  359. }
  360. public function testDeleteGroup(): void {
  361. $this->groupManager
  362. ->method('groupExists')
  363. ->with('ExistingGroup')
  364. ->willReturn('true');
  365. $group = $this->createGroup('ExistingGroup');
  366. $this->groupManager
  367. ->method('get')
  368. ->with('ExistingGroup')
  369. ->willReturn($group);
  370. $group
  371. ->expects($this->once())
  372. ->method('delete')
  373. ->willReturn(true);
  374. $this->api->deleteGroup('ExistingGroup');
  375. }
  376. public function testDeleteGroupEncoding(): void {
  377. $this->groupManager
  378. ->method('groupExists')
  379. ->with('ExistingGroup A/B')
  380. ->willReturn('true');
  381. $group = $this->createGroup('ExistingGroup');
  382. $this->groupManager
  383. ->method('get')
  384. ->with('ExistingGroup A/B')
  385. ->willReturn($group);
  386. $group
  387. ->expects($this->once())
  388. ->method('delete')
  389. ->willReturn(true);
  390. $this->api->deleteGroup(urlencode('ExistingGroup A/B'));
  391. }
  392. public function testGetGroupUsersDetails(): void {
  393. $gid = 'ncg1';
  394. $this->asAdmin();
  395. $users = [
  396. 'ncu1' => $this->createUser('ncu1'), # regular
  397. 'ncu2' => $this->createUser('ncu2'), # the zombie
  398. ];
  399. $users['ncu2']->expects($this->atLeastOnce())
  400. ->method('getHome')
  401. ->willThrowException(new NoUserException());
  402. $this->userManager->expects($this->any())
  403. ->method('get')
  404. ->willReturnCallback(function (string $uid) use ($users) {
  405. return $users[$uid] ?? null;
  406. });
  407. $group = $this->createGroup($gid);
  408. $group->expects($this->once())
  409. ->method('searchUsers')
  410. ->with('', null, 0)
  411. ->willReturn(array_values($users));
  412. $this->groupManager
  413. ->method('get')
  414. ->with($gid)
  415. ->willReturn($group);
  416. $this->groupManager->expects($this->any())
  417. ->method('getUserGroups')
  418. ->willReturn([$group]);
  419. /** @var \PHPUnit\Framework\MockObject\MockObject */
  420. $this->subAdminManager->expects($this->any())
  421. ->method('isSubAdminOfGroup')
  422. ->willReturn(false);
  423. $this->subAdminManager->expects($this->any())
  424. ->method('getSubAdminsGroups')
  425. ->willReturn([]);
  426. $this->api->getGroupUsersDetails($gid);
  427. }
  428. public function testGetGroupUsersDetailsEncoded(): void {
  429. $gid = 'Department A/B C/D';
  430. $this->asAdmin();
  431. $users = [
  432. 'ncu1' => $this->createUser('ncu1'), # regular
  433. 'ncu2' => $this->createUser('ncu2'), # the zombie
  434. ];
  435. $users['ncu2']->expects($this->atLeastOnce())
  436. ->method('getHome')
  437. ->willThrowException(new NoUserException());
  438. $this->userManager->expects($this->any())
  439. ->method('get')
  440. ->willReturnCallback(function (string $uid) use ($users) {
  441. return $users[$uid] ?? null;
  442. });
  443. $group = $this->createGroup($gid);
  444. $group->expects($this->once())
  445. ->method('searchUsers')
  446. ->with('', null, 0)
  447. ->willReturn(array_values($users));
  448. $this->groupManager
  449. ->method('get')
  450. ->with($gid)
  451. ->willReturn($group);
  452. $this->groupManager->expects($this->any())
  453. ->method('getUserGroups')
  454. ->willReturn([$group]);
  455. /** @var \PHPUnit\Framework\MockObject\MockObject */
  456. $this->subAdminManager->expects($this->any())
  457. ->method('isSubAdminOfGroup')
  458. ->willReturn(false);
  459. $this->subAdminManager->expects($this->any())
  460. ->method('getSubAdminsGroups')
  461. ->willReturn([]);
  462. $this->api->getGroupUsersDetails(urlencode($gid));
  463. }
  464. }