MoveCalendarTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016 Thomas Citharel <nextcloud@tcit.fr>
  4. *
  5. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  6. * @author Georg Ehrke <oc.list@georgehrke.com>
  7. * @author Morris Jobke <hey@morrisjobke.de>
  8. * @author Roeland Jago Douma <roeland@famdouma.nl>
  9. * @author Thomas Citharel <nextcloud@tcit.fr>
  10. *
  11. * @license GNU AGPL version 3 or any later version
  12. *
  13. * This program is free software: you can redistribute it and/or modify
  14. * it under the terms of the GNU Affero General Public License as
  15. * published by the Free Software Foundation, either version 3 of the
  16. * License, or (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU Affero General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Affero General Public License
  24. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  25. *
  26. */
  27. namespace OCA\DAV\Tests\Command;
  28. use InvalidArgumentException;
  29. use OCA\DAV\CalDAV\CalDavBackend;
  30. use OCA\DAV\Command\MoveCalendar;
  31. use OCP\IConfig;
  32. use OCP\IGroupManager;
  33. use OCP\IL10N;
  34. use OCP\IUserManager;
  35. use OCP\Share\IManager;
  36. use PHPUnit\Framework\MockObject\MockObject;
  37. use Psr\Log\LoggerInterface;
  38. use Symfony\Component\Console\Tester\CommandTester;
  39. use Test\TestCase;
  40. /**
  41. * Class MoveCalendarTest
  42. *
  43. * @package OCA\DAV\Tests\Command
  44. */
  45. class MoveCalendarTest extends TestCase {
  46. /** @var \OCP\IUserManager|MockObject $userManager */
  47. private $userManager;
  48. /** @var \OCP\IGroupManager|MockObject $groupManager */
  49. private $groupManager;
  50. /** @var \OCP\Share\IManager|MockObject $shareManager */
  51. private $shareManager;
  52. /** @var IConfig|MockObject $l10n */
  53. private $config;
  54. /** @var IL10N|MockObject $l10n */
  55. private $l10n;
  56. /** @var CalDavBackend|MockObject $l10n */
  57. private $calDav;
  58. /** @var MoveCalendar */
  59. private $command;
  60. /** @var LoggerInterface|MockObject */
  61. private $logger;
  62. protected function setUp(): void {
  63. parent::setUp();
  64. $this->userManager = $this->createMock(IUserManager::class);
  65. $this->groupManager = $this->createMock(IGroupManager::class);
  66. $this->shareManager = $this->createMock(IManager::class);
  67. $this->config = $this->createMock(IConfig::class);
  68. $this->l10n = $this->createMock(IL10N::class);
  69. $this->calDav = $this->createMock(CalDavBackend::class);
  70. $this->logger = $this->createMock(LoggerInterface::class);
  71. $this->command = new MoveCalendar(
  72. $this->userManager,
  73. $this->groupManager,
  74. $this->shareManager,
  75. $this->config,
  76. $this->l10n,
  77. $this->calDav,
  78. $this->logger
  79. );
  80. }
  81. public function dataExecute() {
  82. return [
  83. [false, true],
  84. [true, false]
  85. ];
  86. }
  87. /**
  88. * @dataProvider dataExecute
  89. *
  90. * @param $userOriginExists
  91. * @param $userDestinationExists
  92. */
  93. public function testWithBadUserOrigin($userOriginExists, $userDestinationExists) {
  94. $this->expectException(\InvalidArgumentException::class);
  95. $this->userManager->expects($this->at(0))
  96. ->method('userExists')
  97. ->with('user')
  98. ->willReturn($userOriginExists);
  99. if (!$userDestinationExists) {
  100. $this->userManager->expects($this->at(1))
  101. ->method('userExists')
  102. ->with('user2')
  103. ->willReturn($userDestinationExists);
  104. }
  105. $commandTester = new CommandTester($this->command);
  106. $commandTester->execute([
  107. 'name' => $this->command->getName(),
  108. 'sourceuid' => 'user',
  109. 'destinationuid' => 'user2',
  110. ]);
  111. }
  112. public function testMoveWithInexistantCalendar() {
  113. $this->expectException(\InvalidArgumentException::class);
  114. $this->expectExceptionMessage('User <user> has no calendar named <personal>. You can run occ dav:list-calendars to list calendars URIs for this user.');
  115. $this->userManager->expects($this->at(0))
  116. ->method('userExists')
  117. ->with('user')
  118. ->willReturn(true);
  119. $this->userManager->expects($this->at(1))
  120. ->method('userExists')
  121. ->with('user2')
  122. ->willReturn(true);
  123. $this->calDav->expects($this->once())->method('getCalendarByUri')
  124. ->with('principals/users/user', 'personal')
  125. ->willReturn(null);
  126. $commandTester = new CommandTester($this->command);
  127. $commandTester->execute([
  128. 'name' => 'personal',
  129. 'sourceuid' => 'user',
  130. 'destinationuid' => 'user2',
  131. ]);
  132. }
  133. public function testMoveWithExistingDestinationCalendar() {
  134. $this->expectException(\InvalidArgumentException::class);
  135. $this->expectExceptionMessage('User <user2> already has a calendar named <personal>.');
  136. $this->userManager->expects($this->at(0))
  137. ->method('userExists')
  138. ->with('user')
  139. ->willReturn(true);
  140. $this->userManager->expects($this->at(1))
  141. ->method('userExists')
  142. ->with('user2')
  143. ->willReturn(true);
  144. $this->calDav->expects($this->at(0))->method('getCalendarByUri')
  145. ->with('principals/users/user', 'personal')
  146. ->willReturn([
  147. 'id' => 1234,
  148. ]);
  149. $this->calDav->expects($this->at(1))->method('getCalendarByUri')
  150. ->with('principals/users/user2', 'personal')
  151. ->willReturn([
  152. 'id' => 1234,
  153. ]);
  154. $commandTester = new CommandTester($this->command);
  155. $commandTester->execute([
  156. 'name' => 'personal',
  157. 'sourceuid' => 'user',
  158. 'destinationuid' => 'user2',
  159. ]);
  160. }
  161. public function testMove() {
  162. $this->userManager->expects($this->at(0))
  163. ->method('userExists')
  164. ->with('user')
  165. ->willReturn(true);
  166. $this->userManager->expects($this->at(1))
  167. ->method('userExists')
  168. ->with('user2')
  169. ->willReturn(true);
  170. $this->calDav->expects($this->at(0))->method('getCalendarByUri')
  171. ->with('principals/users/user', 'personal')
  172. ->willReturn([
  173. 'id' => 1234,
  174. ]);
  175. $this->calDav->expects($this->at(1))->method('getCalendarByUri')
  176. ->with('principals/users/user2', 'personal')
  177. ->willReturn(null);
  178. $this->calDav->expects($this->once())->method('getShares')
  179. ->with(1234)
  180. ->willReturn([]);
  181. $commandTester = new CommandTester($this->command);
  182. $commandTester->execute([
  183. 'name' => 'personal',
  184. 'sourceuid' => 'user',
  185. 'destinationuid' => 'user2',
  186. ]);
  187. $this->assertStringContainsString("[OK] Calendar <personal> was moved from user <user> to <user2>", $commandTester->getDisplay());
  188. }
  189. public function dataTestMoveWithDestinationNotPartOfGroup(): array {
  190. return [
  191. [true],
  192. [false]
  193. ];
  194. }
  195. /**
  196. * @dataProvider dataTestMoveWithDestinationNotPartOfGroup
  197. */
  198. public function testMoveWithDestinationNotPartOfGroup(bool $shareWithGroupMembersOnly) {
  199. $this->userManager->expects($this->at(0))
  200. ->method('userExists')
  201. ->with('user')
  202. ->willReturn(true);
  203. $this->userManager->expects($this->at(1))
  204. ->method('userExists')
  205. ->with('user2')
  206. ->willReturn(true);
  207. $this->calDav->expects($this->at(0))->method('getCalendarByUri')
  208. ->with('principals/users/user', 'personal')
  209. ->willReturn([
  210. 'id' => 1234,
  211. 'uri' => 'personal'
  212. ]);
  213. $this->calDav->expects($this->at(1))->method('getCalendarByUri')
  214. ->with('principals/users/user2', 'personal')
  215. ->willReturn(null);
  216. $this->shareManager->expects($this->once())->method('shareWithGroupMembersOnly')
  217. ->willReturn($shareWithGroupMembersOnly);
  218. $this->calDav->expects($this->once())->method('getShares')
  219. ->with(1234)
  220. ->willReturn([
  221. ['href' => 'principal:principals/groups/nextclouders']
  222. ]);
  223. if ($shareWithGroupMembersOnly === true) {
  224. $this->expectException(InvalidArgumentException::class);
  225. $this->expectExceptionMessage("User <user2> is not part of the group <nextclouders> with whom the calendar <personal> was shared. You may use -f to move the calendar while deleting this share.");
  226. }
  227. $commandTester = new CommandTester($this->command);
  228. $commandTester->execute([
  229. 'name' => 'personal',
  230. 'sourceuid' => 'user',
  231. 'destinationuid' => 'user2',
  232. ]);
  233. }
  234. public function testMoveWithDestinationPartOfGroup() {
  235. $this->userManager->expects($this->at(0))
  236. ->method('userExists')
  237. ->with('user')
  238. ->willReturn(true);
  239. $this->userManager->expects($this->at(1))
  240. ->method('userExists')
  241. ->with('user2')
  242. ->willReturn(true);
  243. $this->calDav->expects($this->at(0))->method('getCalendarByUri')
  244. ->with('principals/users/user', 'personal')
  245. ->willReturn([
  246. 'id' => 1234,
  247. 'uri' => 'personal'
  248. ]);
  249. $this->calDav->expects($this->at(1))->method('getCalendarByUri')
  250. ->with('principals/users/user2', 'personal')
  251. ->willReturn(null);
  252. $this->shareManager->expects($this->once())->method('shareWithGroupMembersOnly')
  253. ->willReturn(true);
  254. $this->calDav->expects($this->once())->method('getShares')
  255. ->with(1234)
  256. ->willReturn([
  257. ['href' => 'principal:principals/groups/nextclouders']
  258. ]);
  259. $this->groupManager->expects($this->once())->method('isInGroup')
  260. ->with('user2', 'nextclouders')
  261. ->willReturn(true);
  262. $commandTester = new CommandTester($this->command);
  263. $commandTester->execute([
  264. 'name' => 'personal',
  265. 'sourceuid' => 'user',
  266. 'destinationuid' => 'user2',
  267. ]);
  268. $this->assertStringContainsString("[OK] Calendar <personal> was moved from user <user> to <user2>", $commandTester->getDisplay());
  269. }
  270. public function testMoveWithDestinationNotPartOfGroupAndForce() {
  271. $this->userManager->expects($this->at(0))
  272. ->method('userExists')
  273. ->with('user')
  274. ->willReturn(true);
  275. $this->userManager->expects($this->at(1))
  276. ->method('userExists')
  277. ->with('user2')
  278. ->willReturn(true);
  279. $this->calDav->expects($this->at(0))->method('getCalendarByUri')
  280. ->with('principals/users/user', 'personal')
  281. ->willReturn([
  282. 'id' => 1234,
  283. 'uri' => 'personal',
  284. '{DAV:}displayname' => 'Personal'
  285. ]);
  286. $this->calDav->expects($this->at(1))->method('getCalendarByUri')
  287. ->with('principals/users/user2', 'personal')
  288. ->willReturn(null);
  289. $this->shareManager->expects($this->once())->method('shareWithGroupMembersOnly')
  290. ->willReturn(true);
  291. $this->calDav->expects($this->once())->method('getShares')
  292. ->with(1234)
  293. ->willReturn([
  294. [
  295. 'href' => 'principal:principals/groups/nextclouders',
  296. '{DAV:}displayname' => 'Personal'
  297. ]
  298. ]);
  299. $this->calDav->expects($this->once())->method('updateShares');
  300. $commandTester = new CommandTester($this->command);
  301. $commandTester->execute([
  302. 'name' => 'personal',
  303. 'sourceuid' => 'user',
  304. 'destinationuid' => 'user2',
  305. '--force' => true
  306. ]);
  307. $this->assertStringContainsString("[OK] Calendar <personal> was moved from user <user> to <user2>", $commandTester->getDisplay());
  308. }
  309. public function dataTestMoveWithCalendarAlreadySharedToDestination(): array {
  310. return [
  311. [true],
  312. [false]
  313. ];
  314. }
  315. /**
  316. * @dataProvider dataTestMoveWithCalendarAlreadySharedToDestination
  317. */
  318. public function testMoveWithCalendarAlreadySharedToDestination(bool $force) {
  319. $this->userManager->expects($this->at(0))
  320. ->method('userExists')
  321. ->with('user')
  322. ->willReturn(true);
  323. $this->userManager->expects($this->at(1))
  324. ->method('userExists')
  325. ->with('user2')
  326. ->willReturn(true);
  327. $this->calDav->expects($this->at(0))->method('getCalendarByUri')
  328. ->with('principals/users/user', 'personal')
  329. ->willReturn([
  330. 'id' => 1234,
  331. 'uri' => 'personal',
  332. '{DAV:}displayname' => 'Personal',
  333. ]);
  334. $this->calDav->expects($this->at(1))->method('getCalendarByUri')
  335. ->with('principals/users/user2', 'personal')
  336. ->willReturn(null);
  337. $this->calDav->expects($this->once())->method('getShares')
  338. ->with(1234)
  339. ->willReturn([
  340. [
  341. 'href' => 'principal:principals/users/user2',
  342. '{DAV:}displayname' => 'Personal'
  343. ]
  344. ]);
  345. if ($force === false) {
  346. $this->expectException(InvalidArgumentException::class);
  347. $this->expectExceptionMessage("The calendar <personal> is already shared to user <user2>.You may use -f to move the calendar while deleting this share.");
  348. } else {
  349. $this->calDav->expects($this->once())->method('updateShares');
  350. }
  351. $commandTester = new CommandTester($this->command);
  352. $commandTester->execute([
  353. 'name' => 'personal',
  354. 'sourceuid' => 'user',
  355. 'destinationuid' => 'user2',
  356. '--force' => $force,
  357. ]);
  358. }
  359. }