ShareesAPIControllerTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Bjoern Schiessle <bjoern@schiessle.org>
  7. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  8. * @author Joas Schilling <coding@schilljs.com>
  9. * @author Julius Härtl <jus@bitgrid.net>
  10. * @author Lukas Reschke <lukas@statuscode.ch>
  11. * @author Robin Appelman <robin@icewind.nl>
  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\Files_Sharing\Tests\Controller;
  32. use OCA\Files_Sharing\Controller\ShareesAPIController;
  33. use OCA\Files_Sharing\Tests\TestCase;
  34. use OCP\AppFramework\Http;
  35. use OCP\AppFramework\OCS\OCSBadRequestException;
  36. use OCP\Collaboration\Collaborators\ISearch;
  37. use OCP\IConfig;
  38. use OCP\IRequest;
  39. use OCP\IURLGenerator;
  40. use OCP\Share\IManager;
  41. use OCP\Share\IShare;
  42. use PHPUnit\Framework\MockObject\MockObject;
  43. /**
  44. * Class ShareesTest
  45. *
  46. * @group DB
  47. *
  48. * @package OCA\Files_Sharing\Tests\API
  49. */
  50. class ShareesAPIControllerTest extends TestCase {
  51. /** @var ShareesAPIController */
  52. protected $sharees;
  53. /** @var string */
  54. protected $uid;
  55. /** @var IRequest|MockObject */
  56. protected $request;
  57. /** @var IManager|MockObject */
  58. protected $shareManager;
  59. /** @var ISearch|MockObject */
  60. protected $collaboratorSearch;
  61. protected function setUp(): void {
  62. parent::setUp();
  63. $this->uid = 'test123';
  64. $this->request = $this->createMock(IRequest::class);
  65. $this->shareManager = $this->createMock(IManager::class);
  66. /** @var IConfig|MockObject $configMock */
  67. $configMock = $this->createMock(IConfig::class);
  68. /** @var IURLGenerator|MockObject $urlGeneratorMock */
  69. $urlGeneratorMock = $this->createMock(IURLGenerator::class);
  70. $this->collaboratorSearch = $this->createMock(ISearch::class);
  71. $this->sharees = new ShareesAPIController(
  72. $this->uid,
  73. 'files_sharing',
  74. $this->request,
  75. $configMock,
  76. $urlGeneratorMock,
  77. $this->shareManager,
  78. $this->collaboratorSearch
  79. );
  80. }
  81. public function dataSearch(): array {
  82. $noRemote = [IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_EMAIL];
  83. $allTypes = [IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_REMOTE_GROUP, IShare::TYPE_EMAIL];
  84. return [
  85. [[], '', 'yes', true, true, true, $noRemote, false, true, true],
  86. // Test itemType
  87. [[
  88. 'search' => '',
  89. ], '', 'yes', true, true, true, $noRemote, false, true, true],
  90. [[
  91. 'search' => 'foobar',
  92. ], '', 'yes', true, true, true, $noRemote, false, true, true],
  93. [[
  94. 'search' => 0,
  95. ], '', 'yes', true, true, true, $noRemote, false, true, true],
  96. // Test itemType
  97. [[
  98. 'itemType' => '',
  99. ], '', 'yes', true, true, true, $noRemote, false, true, true],
  100. [[
  101. 'itemType' => 'folder',
  102. ], '', 'yes', true, true, true, $allTypes, false, true, true],
  103. [[
  104. 'itemType' => 0,
  105. ], '', 'yes', true, true , true, $noRemote, false, true, true],
  106. // Test shareType
  107. [[
  108. 'itemType' => 'call',
  109. ], '', 'yes', true, true, true, $noRemote, false, true, true],
  110. [[
  111. 'itemType' => 'call',
  112. ], '', 'yes', true, true, true, [0, 4], false, true, false],
  113. [[
  114. 'itemType' => 'folder',
  115. ], '', 'yes', true, true, true, $allTypes, false, true, true],
  116. [[
  117. 'itemType' => 'folder',
  118. 'shareType' => 0,
  119. ], '', 'yes', true, true, false, [0], false, true, true],
  120. [[
  121. 'itemType' => 'folder',
  122. 'shareType' => '0',
  123. ], '', 'yes', true, true, false, [0], false, true, true],
  124. [[
  125. 'itemType' => 'folder',
  126. 'shareType' => 1,
  127. ], '', 'yes', true, true, false, [1], false, true, true],
  128. [[
  129. 'itemType' => 'folder',
  130. 'shareType' => 12,
  131. ], '', 'yes', true, true, false, [], false, true, true],
  132. [[
  133. 'itemType' => 'folder',
  134. 'shareType' => 'foobar',
  135. ], '', 'yes', true, true, true, $allTypes, false, true, true],
  136. [[
  137. 'itemType' => 'folder',
  138. 'shareType' => [0, 1, 2],
  139. ], '', 'yes', false, false, false, [0, 1], false, true, true],
  140. [[
  141. 'itemType' => 'folder',
  142. 'shareType' => [0, 1],
  143. ], '', 'yes', false, false, false, [0, 1], false, true, true],
  144. [[
  145. 'itemType' => 'folder',
  146. 'shareType' => $allTypes,
  147. ], '', 'yes', true, true, true, $allTypes, false, true, true],
  148. [[
  149. 'itemType' => 'folder',
  150. 'shareType' => $allTypes,
  151. ], '', 'yes', false, false, false, [0, 1], false, true, true],
  152. [[
  153. 'itemType' => 'folder',
  154. 'shareType' => $allTypes,
  155. ], '', 'yes', true, false, false, [0, 6], false, true, false],
  156. [[
  157. 'itemType' => 'folder',
  158. 'shareType' => $allTypes,
  159. ], '', 'yes', false, false, true, [0, 4], false, true, false],
  160. [[
  161. 'itemType' => 'folder',
  162. 'shareType' => $allTypes,
  163. ], '', 'yes', true, true, false, [0, 6, 9], false, true, false],
  164. // Test pagination
  165. [[
  166. 'itemType' => 'folder',
  167. 'page' => 1,
  168. ], '', 'yes', true, true, true, $allTypes, false, true, true],
  169. [[
  170. 'itemType' => 'folder',
  171. 'page' => 10,
  172. ], '', 'yes', true, true, true, $allTypes, false, true, true],
  173. // Test perPage
  174. [[
  175. 'itemType' => 'folder',
  176. 'perPage' => 1,
  177. ], '', 'yes', true, true, true, $allTypes, false, true, true],
  178. [[
  179. 'itemType' => 'folder',
  180. 'perPage' => 10,
  181. ], '', 'yes', true, true, true, $allTypes, false, true, true],
  182. // Test $shareWithGroupOnly setting
  183. [[
  184. 'itemType' => 'folder',
  185. ], 'no', 'yes', true, true, true, $allTypes, false, true, true],
  186. [[
  187. 'itemType' => 'folder',
  188. ], 'yes', 'yes', true, true, true, $allTypes, true, true, true],
  189. // Test $shareeEnumeration setting
  190. [[
  191. 'itemType' => 'folder',
  192. ], 'no', 'yes', true, true, true, $allTypes, false, true, true],
  193. [[
  194. 'itemType' => 'folder',
  195. ], 'no', 'no', true, true, true, $allTypes, false, false, true],
  196. ];
  197. }
  198. /**
  199. * @dataProvider dataSearch
  200. *
  201. * @param array $getData
  202. * @param string $apiSetting
  203. * @param string $enumSetting
  204. * @param bool $remoteSharingEnabled
  205. * @param bool $isRemoteGroupSharingEnabled
  206. * @param bool $emailSharingEnabled
  207. * @param array $shareTypes
  208. * @param bool $shareWithGroupOnly
  209. * @param bool $shareeEnumeration
  210. * @param bool $allowGroupSharing
  211. * @throws OCSBadRequestException
  212. */
  213. public function testSearch(array $getData, string $apiSetting, string $enumSetting, bool $remoteSharingEnabled, bool $isRemoteGroupSharingEnabled, bool $emailSharingEnabled, array $shareTypes, bool $shareWithGroupOnly, bool $shareeEnumeration, bool $allowGroupSharing) {
  214. $search = $getData['search'] ?? '';
  215. $itemType = $getData['itemType'] ?? 'irrelevant';
  216. $page = $getData['page'] ?? 1;
  217. $perPage = $getData['perPage'] ?? 200;
  218. $shareType = $getData['shareType'] ?? null;
  219. /** @var IConfig|MockObject $config */
  220. $config = $this->createMock(IConfig::class);
  221. $config->expects($this->exactly(1))
  222. ->method('getAppValue')
  223. ->with($this->anything(), $this->anything(), $this->anything())
  224. ->willReturnMap([
  225. ['files_sharing', 'lookupServerEnabled', 'yes', 'yes'],
  226. ]);
  227. $this->shareManager->expects($this->once())
  228. ->method('allowGroupSharing')
  229. ->willReturn($allowGroupSharing);
  230. /** @var string */
  231. $uid = 'test123';
  232. /** @var IRequest|MockObject $request */
  233. $request = $this->createMock(IRequest::class);
  234. /** @var IURLGenerator|MockObject $urlGenerator */
  235. $urlGenerator = $this->createMock(IURLGenerator::class);
  236. /** @var MockObject|ShareesAPIController $sharees */
  237. $sharees = $this->getMockBuilder(ShareesAPIController::class)
  238. ->setConstructorArgs([
  239. $uid,
  240. 'files_sharing',
  241. $request,
  242. $config,
  243. $urlGenerator,
  244. $this->shareManager,
  245. $this->collaboratorSearch
  246. ])
  247. ->setMethods(['isRemoteSharingAllowed', 'shareProviderExists', 'isRemoteGroupSharingAllowed'])
  248. ->getMock();
  249. $expectedShareTypes = $shareTypes;
  250. sort($expectedShareTypes);
  251. $this->collaboratorSearch->expects($this->once())
  252. ->method('search')
  253. ->with($search, $expectedShareTypes, $this->anything(), $perPage, $perPage * ($page - 1))
  254. ->willReturn([[], false]);
  255. $sharees->expects($this->any())
  256. ->method('isRemoteSharingAllowed')
  257. ->with($itemType)
  258. ->willReturn($remoteSharingEnabled);
  259. $sharees->expects($this->any())
  260. ->method('isRemoteGroupSharingAllowed')
  261. ->with($itemType)
  262. ->willReturn($isRemoteGroupSharingEnabled);
  263. $this->shareManager->expects($this->any())
  264. ->method('shareProviderExists')
  265. ->willReturnCallback(function ($shareType) use ($emailSharingEnabled) {
  266. if ($shareType === IShare::TYPE_EMAIL) {
  267. return $emailSharingEnabled;
  268. } else {
  269. return false;
  270. }
  271. });
  272. $this->assertInstanceOf(Http\DataResponse::class, $sharees->search($search, $itemType, $page, $perPage, $shareType));
  273. }
  274. public function dataSearchInvalid(): array {
  275. return [
  276. // Test invalid pagination
  277. [[
  278. 'page' => 0,
  279. ], 'Invalid page'],
  280. [[
  281. 'page' => '0',
  282. ], 'Invalid page'],
  283. [[
  284. 'page' => -1,
  285. ], 'Invalid page'],
  286. // Test invalid perPage
  287. [[
  288. 'perPage' => 0,
  289. ], 'Invalid perPage argument'],
  290. [[
  291. 'perPage' => '0',
  292. ], 'Invalid perPage argument'],
  293. [[
  294. 'perPage' => -1,
  295. ], 'Invalid perPage argument'],
  296. ];
  297. }
  298. /**
  299. * @dataProvider dataSearchInvalid
  300. *
  301. * @param array $getData
  302. * @param string $message
  303. */
  304. public function testSearchInvalid($getData, $message) {
  305. $page = $getData['page'] ?? 1;
  306. $perPage = $getData['perPage'] ?? 200;
  307. /** @var IConfig|MockObject $config */
  308. $config = $this->createMock(IConfig::class);
  309. $config->expects($this->never())
  310. ->method('getAppValue');
  311. /** @var string */
  312. $uid = 'test123';
  313. /** @var IRequest|MockObject $request */
  314. $request = $this->createMock(IRequest::class);
  315. /** @var IURLGenerator|MockObject $urlGenerator */
  316. $urlGenerator = $this->createMock(IURLGenerator::class);
  317. /** @var MockObject|ShareesAPIController $sharees */
  318. $sharees = $this->getMockBuilder('\OCA\Files_Sharing\Controller\ShareesAPIController')
  319. ->setConstructorArgs([
  320. $uid,
  321. 'files_sharing',
  322. $request,
  323. $config,
  324. $urlGenerator,
  325. $this->shareManager,
  326. $this->collaboratorSearch
  327. ])
  328. ->setMethods(['isRemoteSharingAllowed'])
  329. ->getMock();
  330. $sharees->expects($this->never())
  331. ->method('isRemoteSharingAllowed');
  332. $this->collaboratorSearch->expects($this->never())
  333. ->method('search');
  334. try {
  335. $sharees->search('', null, $page, $perPage, null);
  336. $this->fail();
  337. } catch (OCSBadRequestException $e) {
  338. $this->assertEquals($message, $e->getMessage());
  339. }
  340. }
  341. public function dataIsRemoteSharingAllowed() {
  342. return [
  343. ['file', true],
  344. ['folder', true],
  345. ['', false],
  346. ['contacts', false],
  347. ];
  348. }
  349. /**
  350. * @dataProvider dataIsRemoteSharingAllowed
  351. *
  352. * @param string $itemType
  353. * @param bool $expected
  354. */
  355. public function testIsRemoteSharingAllowed($itemType, $expected) {
  356. $this->assertSame($expected, $this->invokePrivate($this->sharees, 'isRemoteSharingAllowed', [$itemType]));
  357. }
  358. public function testSearchNoItemType() {
  359. $this->expectException(\OCP\AppFramework\OCS\OCSBadRequestException::class);
  360. $this->expectExceptionMessage('Missing itemType');
  361. $this->sharees->search('', null, 1, 10, [], false);
  362. }
  363. public function dataGetPaginationLink() {
  364. return [
  365. [1, '/ocs/v1.php', ['perPage' => 2], '<?perPage=2&page=2>; rel="next"'],
  366. [10, '/ocs/v2.php', ['perPage' => 2], '<?perPage=2&page=11>; rel="next"'],
  367. ];
  368. }
  369. /**
  370. * @dataProvider dataGetPaginationLink
  371. *
  372. * @param int $page
  373. * @param string $scriptName
  374. * @param array $params
  375. * @param array $expected
  376. */
  377. public function testGetPaginationLink($page, $scriptName, $params, $expected) {
  378. $this->request->expects($this->once())
  379. ->method('getScriptName')
  380. ->willReturn($scriptName);
  381. $this->assertEquals($expected, $this->invokePrivate($this->sharees, 'getPaginationLink', [$page, $params]));
  382. }
  383. public function dataIsV2() {
  384. return [
  385. ['/ocs/v1.php', false],
  386. ['/ocs/v2.php', true],
  387. ];
  388. }
  389. /**
  390. * @dataProvider dataIsV2
  391. *
  392. * @param string $scriptName
  393. * @param bool $expected
  394. */
  395. public function testIsV2($scriptName, $expected) {
  396. $this->request->expects($this->once())
  397. ->method('getScriptName')
  398. ->willReturn($scriptName);
  399. $this->assertEquals($expected, $this->invokePrivate($this->sharees, 'isV2'));
  400. }
  401. }