ManagerTest.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. namespace Test\Calendar;
  7. use OC\AppFramework\Bootstrap\Coordinator;
  8. use OC\Calendar\Manager;
  9. use OCP\AppFramework\Utility\ITimeFactory;
  10. use OCP\Calendar\ICalendar;
  11. use OCP\Calendar\ICalendarIsShared;
  12. use OCP\Calendar\ICalendarIsWritable;
  13. use OCP\Calendar\ICreateFromString;
  14. use OCP\Calendar\IHandleImipMessage;
  15. use PHPUnit\Framework\MockObject\MockObject;
  16. use Psr\Container\ContainerInterface;
  17. use Psr\Log\LoggerInterface;
  18. use Sabre\VObject\Component\VCalendar;
  19. use Sabre\VObject\Document;
  20. use Sabre\VObject\Reader;
  21. use Test\TestCase;
  22. /*
  23. * This allows us to create Mock object supporting both interfaces
  24. */
  25. interface ITestCalendar extends ICreateFromString, IHandleImipMessage, ICalendarIsShared, ICalendarIsWritable {
  26. }
  27. class ManagerTest extends TestCase {
  28. /** @var Coordinator&MockObject */
  29. private $coordinator;
  30. /** @var ContainerInterface&MockObject */
  31. private $container;
  32. /** @var LoggerInterface&MockObject */
  33. private $logger;
  34. /** @var Manager */
  35. private $manager;
  36. /** @var ITimeFactory&MockObject */
  37. private $time;
  38. private VCalendar $vCalendar1a;
  39. protected function setUp(): void {
  40. parent::setUp();
  41. $this->coordinator = $this->createMock(Coordinator::class);
  42. $this->container = $this->createMock(ContainerInterface::class);
  43. $this->logger = $this->createMock(LoggerInterface::class);
  44. $this->time = $this->createMock(ITimeFactory::class);
  45. $this->manager = new Manager(
  46. $this->coordinator,
  47. $this->container,
  48. $this->logger,
  49. $this->time,
  50. );
  51. // construct calendar with a 1 hour event and same start/end time zones
  52. $this->vCalendar1a = new VCalendar();
  53. /** @var VEvent $vEvent */
  54. $vEvent = $this->vCalendar1a->add('VEVENT', []);
  55. $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
  56. $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
  57. $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
  58. $vEvent->add('SUMMARY', 'Test Event');
  59. $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
  60. $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
  61. 'CN' => 'Attendee One',
  62. 'CUTYPE' => 'INDIVIDUAL',
  63. 'PARTSTAT' => 'NEEDS-ACTION',
  64. 'ROLE' => 'REQ-PARTICIPANT',
  65. 'RSVP' => 'TRUE'
  66. ]);
  67. }
  68. /**
  69. * @dataProvider searchProvider
  70. */
  71. public function testSearch($search1, $search2, $expected): void {
  72. /** @var ICalendar | MockObject $calendar1 */
  73. $calendar1 = $this->createMock(ICalendar::class);
  74. $calendar1->method('getKey')->willReturn('simple:1');
  75. $calendar1->expects($this->once())
  76. ->method('search')
  77. ->with('', [], [], null, null)
  78. ->willReturn($search1);
  79. /** @var ICalendar | MockObject $calendar2 */
  80. $calendar2 = $this->createMock(ICalendar::class);
  81. $calendar2->method('getKey')->willReturn('simple:2');
  82. $calendar2->expects($this->once())
  83. ->method('search')
  84. ->with('', [], [], null, null)
  85. ->willReturn($search2);
  86. $this->manager->registerCalendar($calendar1);
  87. $this->manager->registerCalendar($calendar2);
  88. $result = $this->manager->search('');
  89. $this->assertEquals($expected, $result);
  90. }
  91. /**
  92. * @dataProvider searchProvider
  93. */
  94. public function testSearchOptions($search1, $search2, $expected): void {
  95. /** @var ICalendar | MockObject $calendar1 */
  96. $calendar1 = $this->createMock(ICalendar::class);
  97. $calendar1->method('getKey')->willReturn('simple:1');
  98. $calendar1->expects($this->once())
  99. ->method('search')
  100. ->with('searchTerm', ['SUMMARY', 'DESCRIPTION'],
  101. ['timerange' => ['start' => null, 'end' => null]], 5, 20)
  102. ->willReturn($search1);
  103. /** @var ICalendar | MockObject $calendar2 */
  104. $calendar2 = $this->createMock(ICalendar::class);
  105. $calendar2->method('getKey')->willReturn('simple:2');
  106. $calendar2->expects($this->once())
  107. ->method('search')
  108. ->with('searchTerm', ['SUMMARY', 'DESCRIPTION'],
  109. ['timerange' => ['start' => null, 'end' => null]], 5, 20)
  110. ->willReturn($search2);
  111. $this->manager->registerCalendar($calendar1);
  112. $this->manager->registerCalendar($calendar2);
  113. $result = $this->manager->search('searchTerm', ['SUMMARY', 'DESCRIPTION'],
  114. ['timerange' => ['start' => null, 'end' => null]], 5, 20);
  115. $this->assertEquals($expected, $result);
  116. }
  117. public function searchProvider() {
  118. $search1 = [
  119. [
  120. 'id' => 1,
  121. 'data' => 'foobar',
  122. ],
  123. [
  124. 'id' => 2,
  125. 'data' => 'barfoo',
  126. ]
  127. ];
  128. $search2 = [
  129. [
  130. 'id' => 3,
  131. 'data' => 'blablub',
  132. ],
  133. [
  134. 'id' => 4,
  135. 'data' => 'blubbla',
  136. ]
  137. ];
  138. $expected = [
  139. [
  140. 'id' => 1,
  141. 'data' => 'foobar',
  142. 'calendar-key' => 'simple:1',
  143. ],
  144. [
  145. 'id' => 2,
  146. 'data' => 'barfoo',
  147. 'calendar-key' => 'simple:1',
  148. ],
  149. [
  150. 'id' => 3,
  151. 'data' => 'blablub',
  152. 'calendar-key' => 'simple:2',
  153. ],
  154. [
  155. 'id' => 4,
  156. 'data' => 'blubbla',
  157. 'calendar-key' => 'simple:2',
  158. ]
  159. ];
  160. return [
  161. [
  162. $search1,
  163. $search2,
  164. $expected
  165. ]
  166. ];
  167. }
  168. public function testRegisterUnregister(): void {
  169. /** @var ICalendar | MockObject $calendar1 */
  170. $calendar1 = $this->createMock(ICalendar::class);
  171. $calendar1->method('getKey')->willReturn('key1');
  172. /** @var ICalendar | MockObject $calendar2 */
  173. $calendar2 = $this->createMock(ICalendar::class);
  174. $calendar2->method('getKey')->willReturn('key2');
  175. $this->manager->registerCalendar($calendar1);
  176. $this->manager->registerCalendar($calendar2);
  177. $result = $this->manager->getCalendars();
  178. $this->assertCount(2, $result);
  179. $this->assertContains($calendar1, $result);
  180. $this->assertContains($calendar2, $result);
  181. $this->manager->unregisterCalendar($calendar1);
  182. $result = $this->manager->getCalendars();
  183. $this->assertCount(1, $result);
  184. $this->assertContains($calendar2, $result);
  185. }
  186. public function testGetCalendars(): void {
  187. /** @var ICalendar | MockObject $calendar1 */
  188. $calendar1 = $this->createMock(ICalendar::class);
  189. $calendar1->method('getKey')->willReturn('key1');
  190. /** @var ICalendar | MockObject $calendar2 */
  191. $calendar2 = $this->createMock(ICalendar::class);
  192. $calendar2->method('getKey')->willReturn('key2');
  193. $this->manager->registerCalendar($calendar1);
  194. $this->manager->registerCalendar($calendar2);
  195. $result = $this->manager->getCalendars();
  196. $this->assertCount(2, $result);
  197. $this->assertContains($calendar1, $result);
  198. $this->assertContains($calendar2, $result);
  199. $this->manager->clear();
  200. $result = $this->manager->getCalendars();
  201. $this->assertCount(0, $result);
  202. }
  203. public function testEnabledIfNot(): void {
  204. $isEnabled = $this->manager->isEnabled();
  205. $this->assertFalse($isEnabled);
  206. }
  207. public function testIfEnabledIfSo(): void {
  208. /** @var ICalendar | MockObject $calendar */
  209. $calendar = $this->createMock(ICalendar::class);
  210. $this->manager->registerCalendar($calendar);
  211. $isEnabled = $this->manager->isEnabled();
  212. $this->assertTrue($isEnabled);
  213. }
  214. public function testHandleImipRequestWithNoCalendars(): void {
  215. // construct calendar manager returns
  216. /** @var Manager&MockObject $manager */
  217. $manager = $this->getMockBuilder(Manager::class)
  218. ->setConstructorArgs([
  219. $this->coordinator,
  220. $this->container,
  221. $this->logger,
  222. $this->time
  223. ])
  224. ->onlyMethods(['getCalendarsForPrincipal'])
  225. ->getMock();
  226. $manager->expects(self::once())
  227. ->method('getCalendarsForPrincipal')
  228. ->willReturn([]);
  229. // construct logger returns
  230. $this->logger->expects(self::once())->method('warning')
  231. ->with('iMip message could not be processed because user has no calendars');
  232. // construct parameters
  233. $principalUri = 'principals/user/attendee1';
  234. $sender = 'organizer@testing.com';
  235. $recipient = 'attendee1@testing.com';
  236. $calendar = $this->vCalendar1a;
  237. $calendar->add('METHOD', 'REQUEST');
  238. // test method
  239. $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
  240. $this->assertFalse($result);
  241. }
  242. public function testHandleImipRequestWithNoMethod(): void {
  243. // construct mock user calendar
  244. $userCalendar = $this->createMock(ITestCalendar::class);
  245. // construct mock calendar manager and returns
  246. /** @var Manager&MockObject $manager */
  247. $manager = $this->getMockBuilder(Manager::class)
  248. ->setConstructorArgs([
  249. $this->coordinator,
  250. $this->container,
  251. $this->logger,
  252. $this->time
  253. ])
  254. ->onlyMethods(['getCalendarsForPrincipal'])
  255. ->getMock();
  256. $manager->expects(self::once())
  257. ->method('getCalendarsForPrincipal')
  258. ->willReturn([$userCalendar]);
  259. // construct logger returns
  260. $this->logger->expects(self::once())->method('warning')
  261. ->with('iMip message contains an incorrect or invalid method');
  262. // construct parameters
  263. $principalUri = 'principals/user/attendee1';
  264. $sender = 'organizer@testing.com';
  265. $recipient = 'attendee1@testing.com';
  266. $calendar = $this->vCalendar1a;
  267. // test method
  268. $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
  269. $this->assertFalse($result);
  270. }
  271. public function testHandleImipRequestWithInvalidMethod(): void {
  272. // construct mock user calendar
  273. $userCalendar = $this->createMock(ITestCalendar::class);
  274. // construct mock calendar manager and returns
  275. /** @var Manager&MockObject $manager */
  276. $manager = $this->getMockBuilder(Manager::class)
  277. ->setConstructorArgs([
  278. $this->coordinator,
  279. $this->container,
  280. $this->logger,
  281. $this->time
  282. ])
  283. ->onlyMethods(['getCalendarsForPrincipal'])
  284. ->getMock();
  285. $manager->expects(self::once())
  286. ->method('getCalendarsForPrincipal')
  287. ->willReturn([$userCalendar]);
  288. // construct logger returns
  289. $this->logger->expects(self::once())->method('warning')
  290. ->with('iMip message contains an incorrect or invalid method');
  291. // construct parameters
  292. $principalUri = 'principals/user/attendee1';
  293. $sender = 'organizer@testing.com';
  294. $recipient = 'attendee1@testing.com';
  295. $calendar = $this->vCalendar1a;
  296. $calendar->add('METHOD', 'CANCEL');
  297. // test method
  298. $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
  299. $this->assertFalse($result);
  300. }
  301. public function testHandleImipRequestWithNoEvent(): void {
  302. // construct mock user calendar
  303. $userCalendar = $this->createMock(ITestCalendar::class);
  304. // construct mock calendar manager and returns
  305. /** @var Manager&MockObject $manager */
  306. $manager = $this->getMockBuilder(Manager::class)
  307. ->setConstructorArgs([
  308. $this->coordinator,
  309. $this->container,
  310. $this->logger,
  311. $this->time
  312. ])
  313. ->onlyMethods(['getCalendarsForPrincipal'])
  314. ->getMock();
  315. $manager->expects(self::once())
  316. ->method('getCalendarsForPrincipal')
  317. ->willReturn([$userCalendar]);
  318. // construct logger returns
  319. $this->logger->expects(self::once())->method('warning')
  320. ->with('iMip message contains no event');
  321. // construct parameters
  322. $principalUri = 'principals/user/attendee1';
  323. $sender = 'organizer@testing.com';
  324. $recipient = 'attendee1@testing.com';
  325. $calendar = $this->vCalendar1a;
  326. $calendar->add('METHOD', 'REQUEST');
  327. $calendar->remove('VEVENT');
  328. // test method
  329. $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
  330. $this->assertFalse($result);
  331. }
  332. public function testHandleImipRequestWithNoUid(): void {
  333. // construct mock user calendar
  334. $userCalendar = $this->createMock(ITestCalendar::class);
  335. // construct mock calendar manager and returns
  336. /** @var Manager&MockObject $manager */
  337. $manager = $this->getMockBuilder(Manager::class)
  338. ->setConstructorArgs([
  339. $this->coordinator,
  340. $this->container,
  341. $this->logger,
  342. $this->time
  343. ])
  344. ->onlyMethods(['getCalendarsForPrincipal'])
  345. ->getMock();
  346. $manager->expects(self::once())
  347. ->method('getCalendarsForPrincipal')
  348. ->willReturn([$userCalendar]);
  349. // construct logger returns
  350. $this->logger->expects(self::once())->method('warning')
  351. ->with('iMip message event dose not contains a UID');
  352. // construct parameters
  353. $principalUri = 'principals/user/attendee1';
  354. $sender = 'organizer@testing.com';
  355. $recipient = 'attendee1@testing.com';
  356. $calendar = $this->vCalendar1a;
  357. $calendar->add('METHOD', 'REQUEST');
  358. $calendar->VEVENT->remove('UID');
  359. // test method
  360. $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
  361. $this->assertFalse($result);
  362. }
  363. public function testHandleImipRequestWithNoAttendee(): void {
  364. // construct mock user calendar
  365. $userCalendar = $this->createMock(ITestCalendar::class);
  366. // construct mock calendar manager and returns
  367. /** @var Manager&MockObject $manager */
  368. $manager = $this->getMockBuilder(Manager::class)
  369. ->setConstructorArgs([
  370. $this->coordinator,
  371. $this->container,
  372. $this->logger,
  373. $this->time
  374. ])
  375. ->onlyMethods(['getCalendarsForPrincipal'])
  376. ->getMock();
  377. $manager->expects(self::once())
  378. ->method('getCalendarsForPrincipal')
  379. ->willReturn([$userCalendar]);
  380. // construct logger returns
  381. $this->logger->expects(self::once())->method('warning')
  382. ->with('iMip message event dose not contains any attendees');
  383. // construct parameters
  384. $principalUri = 'principals/user/attendee1';
  385. $sender = 'organizer@testing.com';
  386. $recipient = 'attendee1@testing.com';
  387. $calendar = $this->vCalendar1a;
  388. $calendar->add('METHOD', 'REQUEST');
  389. $calendar->VEVENT->remove('ATTENDEE');
  390. // test method
  391. $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
  392. $this->assertFalse($result);
  393. }
  394. public function testHandleImipRequestWithInvalidAttendee(): void {
  395. // construct mock user calendar
  396. $userCalendar = $this->createMock(ITestCalendar::class);
  397. // construct mock calendar manager and returns
  398. /** @var Manager&MockObject $manager */
  399. $manager = $this->getMockBuilder(Manager::class)
  400. ->setConstructorArgs([
  401. $this->coordinator,
  402. $this->container,
  403. $this->logger,
  404. $this->time
  405. ])
  406. ->onlyMethods(['getCalendarsForPrincipal'])
  407. ->getMock();
  408. $manager->expects(self::once())
  409. ->method('getCalendarsForPrincipal')
  410. ->willReturn([$userCalendar]);
  411. // construct logger returns
  412. $this->logger->expects(self::once())->method('warning')
  413. ->with('iMip message event does not contain a attendee that matches the recipient');
  414. // construct parameters
  415. $principalUri = 'principals/user/attendee1';
  416. $sender = 'organizer@testing.com';
  417. $recipient = 'attendee2@testing.com';
  418. $calendar = $this->vCalendar1a;
  419. $calendar->add('METHOD', 'REQUEST');
  420. // test method
  421. $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
  422. $this->assertFalse($result);
  423. }
  424. public function testHandleImipRequestWithNoMatch(): void {
  425. // construct mock user calendar
  426. $userCalendar = $this->createMock(ITestCalendar::class);
  427. $userCalendar->expects(self::once())
  428. ->method('isDeleted')
  429. ->willReturn(false);
  430. $userCalendar->expects(self::once())
  431. ->method('isWritable')
  432. ->willReturn(true);
  433. $userCalendar->expects(self::once())
  434. ->method('isShared')
  435. ->willReturn(false);
  436. $userCalendar->expects(self::once())
  437. ->method('search')
  438. ->willReturn([]);
  439. // construct mock calendar manager and returns
  440. /** @var Manager&MockObject $manager */
  441. $manager = $this->getMockBuilder(Manager::class)
  442. ->setConstructorArgs([
  443. $this->coordinator,
  444. $this->container,
  445. $this->logger,
  446. $this->time
  447. ])
  448. ->onlyMethods(['getCalendarsForPrincipal'])
  449. ->getMock();
  450. $manager->expects(self::once())
  451. ->method('getCalendarsForPrincipal')
  452. ->willReturn([$userCalendar]);
  453. // construct logger returns
  454. $this->logger->expects(self::once())->method('warning')
  455. ->with('iMip message event could not be processed because the no corresponding event was found in any calendar');
  456. // construct parameters
  457. $principalUri = 'principals/user/attendee1';
  458. $sender = 'organizer@testing.com';
  459. $recipient = 'attendee1@testing.com';
  460. $calendar = $this->vCalendar1a;
  461. $calendar->add('METHOD', 'REQUEST');
  462. // test method
  463. $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
  464. $this->assertFalse($result);
  465. }
  466. public function testHandleImipRequest(): void {
  467. // construct mock user calendar
  468. $userCalendar = $this->createMock(ITestCalendar::class);
  469. $userCalendar->expects(self::once())
  470. ->method('isDeleted')
  471. ->willReturn(false);
  472. $userCalendar->expects(self::once())
  473. ->method('isWritable')
  474. ->willReturn(true);
  475. $userCalendar->expects(self::once())
  476. ->method('isShared')
  477. ->willReturn(false);
  478. $userCalendar->expects(self::once())
  479. ->method('search')
  480. ->willReturn([['uri' => 'principals/user/attendee1/personal']]);
  481. // construct mock calendar manager and returns
  482. /** @var Manager&MockObject $manager */
  483. $manager = $this->getMockBuilder(Manager::class)
  484. ->setConstructorArgs([
  485. $this->coordinator,
  486. $this->container,
  487. $this->logger,
  488. $this->time
  489. ])
  490. ->onlyMethods(['getCalendarsForPrincipal'])
  491. ->getMock();
  492. $manager->expects(self::once())
  493. ->method('getCalendarsForPrincipal')
  494. ->willReturn([$userCalendar]);
  495. // construct parameters
  496. $principalUri = 'principals/user/attendee1';
  497. $sender = 'organizer@testing.com';
  498. $recipient = 'attendee1@testing.com';
  499. $calendar = $this->vCalendar1a;
  500. $calendar->add('METHOD', 'REQUEST');
  501. // construct user calendar returns
  502. $userCalendar->expects(self::once())
  503. ->method('handleIMipMessage')
  504. ->with('', $calendar->serialize());
  505. // test method
  506. $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
  507. $this->assertTrue($result);
  508. }
  509. public function testHandleImipReplyWrongMethod(): void {
  510. $principalUri = 'principals/user/linus';
  511. $sender = 'pierre@general-store.com';
  512. $recipient = 'linus@stardew-tent-living.com';
  513. $calendarData = $this->getVCalendarReply();
  514. $calendarData->METHOD = 'REQUEST';
  515. $this->logger->expects(self::once())
  516. ->method('warning');
  517. $this->time->expects(self::never())
  518. ->method('getTime');
  519. $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
  520. $this->assertFalse($result);
  521. }
  522. public function testHandleImipReplyOrganizerNotRecipient(): void {
  523. $principalUri = 'principals/user/linus';
  524. $recipient = 'pierre@general-store.com';
  525. $sender = 'linus@stardew-tent-living.com';
  526. $calendarData = $this->getVCalendarReply();
  527. $this->logger->expects(self::once())
  528. ->method('warning');
  529. $this->time->expects(self::never())
  530. ->method('getTime');
  531. $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
  532. $this->assertFalse($result);
  533. }
  534. public function testHandleImipReplyDateInThePast(): void {
  535. $principalUri = 'principals/user/linus';
  536. $sender = 'pierre@general-store.com';
  537. $recipient = 'linus@stardew-tent-living.com';
  538. $calendarData = $this->getVCalendarReply();
  539. $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past
  540. $this->time->expects(self::once())
  541. ->method('getTime')
  542. ->willReturn(time());
  543. $this->logger->expects(self::once())
  544. ->method('warning');
  545. $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
  546. $this->assertFalse($result);
  547. }
  548. public function testHandleImipReplyNoCalendars(): void {
  549. /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
  550. $manager = $this->getMockBuilder(Manager::class)
  551. ->setConstructorArgs([
  552. $this->coordinator,
  553. $this->container,
  554. $this->logger,
  555. $this->time
  556. ])
  557. ->setMethods([
  558. 'getCalendarsForPrincipal'
  559. ])
  560. ->getMock();
  561. $principalUri = 'principals/user/linus';
  562. $sender = 'pierre@general-store.com';
  563. $recipient = 'linus@stardew-tent-living.com';
  564. $calendarData = $this->getVCalendarReply();
  565. $this->time->expects(self::once())
  566. ->method('getTime')
  567. ->willReturn(1628374233);
  568. $manager->expects(self::once())
  569. ->method('getCalendarsForPrincipal')
  570. ->willReturn([]);
  571. $this->logger->expects(self::once())
  572. ->method('warning');
  573. $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
  574. $this->assertFalse($result);
  575. }
  576. public function testHandleImipReplyEventNotFound(): void {
  577. /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
  578. $manager = $this->getMockBuilder(Manager::class)
  579. ->setConstructorArgs([
  580. $this->coordinator,
  581. $this->container,
  582. $this->logger,
  583. $this->time
  584. ])
  585. ->setMethods([
  586. 'getCalendarsForPrincipal'
  587. ])
  588. ->getMock();
  589. $calendar = $this->createMock(ITestCalendar::class);
  590. $principalUri = 'principals/user/linus';
  591. $sender = 'pierre@general-store.com';
  592. $recipient = 'linus@stardew-tent-living.com';
  593. $calendarData = $this->getVCalendarReply();
  594. $this->time->expects(self::once())
  595. ->method('getTime')
  596. ->willReturn(1628374233);
  597. $manager->expects(self::once())
  598. ->method('getCalendarsForPrincipal')
  599. ->willReturn([$calendar]);
  600. $calendar->expects(self::once())
  601. ->method('search')
  602. ->willReturn([]);
  603. $this->logger->expects(self::once())
  604. ->method('info');
  605. $calendar->expects(self::never())
  606. ->method('handleIMipMessage');
  607. $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
  608. $this->assertFalse($result);
  609. }
  610. public function testHandleImipReply(): void {
  611. /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
  612. $manager = $this->getMockBuilder(Manager::class)
  613. ->setConstructorArgs([
  614. $this->coordinator,
  615. $this->container,
  616. $this->logger,
  617. $this->time
  618. ])
  619. ->setMethods([
  620. 'getCalendarsForPrincipal'
  621. ])
  622. ->getMock();
  623. $calendar = $this->createMock(ITestCalendar::class);
  624. $principalUri = 'principals/user/linus';
  625. $sender = 'pierre@general-store.com';
  626. $recipient = 'linus@stardew-tent-living.com';
  627. $calendarData = $this->getVCalendarReply();
  628. $this->time->expects(self::once())
  629. ->method('getTime')
  630. ->willReturn(1628374233);
  631. $manager->expects(self::once())
  632. ->method('getCalendarsForPrincipal')
  633. ->willReturn([$calendar]);
  634. $calendar->expects(self::once())
  635. ->method('search')
  636. ->willReturn([['uri' => 'testname.ics']]);
  637. $calendar->expects(self::once())
  638. ->method('handleIMipMessage')
  639. ->with('testname.ics', $calendarData->serialize());
  640. $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
  641. $this->assertTrue($result);
  642. }
  643. public function testHandleImipCancelWrongMethod(): void {
  644. $principalUri = 'principals/user/pierre';
  645. $sender = 'linus@stardew-tent-living.com';
  646. $recipient = 'pierre@general-store.com';
  647. $replyTo = null;
  648. $calendarData = $this->getVCalendarCancel();
  649. $calendarData->METHOD = 'REQUEST';
  650. $this->logger->expects(self::once())
  651. ->method('warning');
  652. $this->time->expects(self::never())
  653. ->method('getTime');
  654. $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
  655. $this->assertFalse($result);
  656. }
  657. public function testHandleImipCancelAttendeeNotRecipient(): void {
  658. $principalUri = '/user/admin';
  659. $sender = 'linus@stardew-tent-living.com';
  660. $recipient = 'leah@general-store.com';
  661. $replyTo = null;
  662. $calendarData = $this->getVCalendarCancel();
  663. $this->logger->expects(self::once())
  664. ->method('warning');
  665. $this->time->expects(self::never())
  666. ->method('getTime');
  667. $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
  668. $this->assertFalse($result);
  669. }
  670. public function testHandleImipCancelDateInThePast(): void {
  671. $principalUri = 'principals/user/pierre';
  672. $sender = 'linus@stardew-tent-living.com';
  673. $recipient = 'pierre@general-store.com';
  674. $replyTo = null;
  675. $calendarData = $this->getVCalendarCancel();
  676. $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past
  677. $this->time->expects(self::once())
  678. ->method('getTime')
  679. ->willReturn(time());
  680. $this->logger->expects(self::once())
  681. ->method('warning');
  682. $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
  683. $this->assertFalse($result);
  684. }
  685. public function testHandleImipCancelNoCalendars(): void {
  686. /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
  687. $manager = $this->getMockBuilder(Manager::class)
  688. ->setConstructorArgs([
  689. $this->coordinator,
  690. $this->container,
  691. $this->logger,
  692. $this->time
  693. ])
  694. ->setMethods([
  695. 'getCalendarsForPrincipal'
  696. ])
  697. ->getMock();
  698. $principalUri = 'principals/user/pierre';
  699. $sender = 'linus@stardew-tent-living.com';
  700. $recipient = 'pierre@general-store.com';
  701. $replyTo = null;
  702. $calendarData = $this->getVCalendarCancel();
  703. $this->time->expects(self::once())
  704. ->method('getTime')
  705. ->willReturn(1628374233);
  706. $manager->expects(self::once())
  707. ->method('getCalendarsForPrincipal')
  708. ->with($principalUri)
  709. ->willReturn([]);
  710. $this->logger->expects(self::once())
  711. ->method('warning');
  712. $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
  713. $this->assertFalse($result);
  714. }
  715. public function testHandleImipCancelOrganiserInReplyTo(): void {
  716. /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
  717. $manager = $this->getMockBuilder(Manager::class)
  718. ->setConstructorArgs([
  719. $this->coordinator,
  720. $this->container,
  721. $this->logger,
  722. $this->time
  723. ])
  724. ->setMethods([
  725. 'getCalendarsForPrincipal'
  726. ])
  727. ->getMock();
  728. $principalUri = 'principals/user/pierre';
  729. $sender = 'clint@stardew-blacksmiths.com';
  730. $recipient = 'pierre@general-store.com';
  731. $replyTo = 'linus@stardew-tent-living.com';
  732. $calendar = $this->createMock(ITestCalendar::class);
  733. $calendarData = $this->getVCalendarCancel();
  734. $this->time->expects(self::once())
  735. ->method('getTime')
  736. ->willReturn(1628374233);
  737. $manager->expects(self::once())
  738. ->method('getCalendarsForPrincipal')
  739. ->with($principalUri)
  740. ->willReturn([$calendar]);
  741. $calendar->expects(self::once())
  742. ->method('search')
  743. ->willReturn([['uri' => 'testname.ics']]);
  744. $calendar->expects(self::once())
  745. ->method('handleIMipMessage')
  746. ->with('testname.ics', $calendarData->serialize());
  747. $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
  748. $this->assertTrue($result);
  749. }
  750. public function testHandleImipCancel(): void {
  751. /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
  752. $manager = $this->getMockBuilder(Manager::class)
  753. ->setConstructorArgs([
  754. $this->coordinator,
  755. $this->container,
  756. $this->logger,
  757. $this->time
  758. ])
  759. ->setMethods([
  760. 'getCalendarsForPrincipal'
  761. ])
  762. ->getMock();
  763. $principalUri = 'principals/user/pierre';
  764. $sender = 'linus@stardew-tent-living.com';
  765. $recipient = 'pierre@general-store.com';
  766. $replyTo = null;
  767. $calendar = $this->createMock(ITestCalendar::class);
  768. $calendarData = $this->getVCalendarCancel();
  769. $this->time->expects(self::once())
  770. ->method('getTime')
  771. ->willReturn(1628374233);
  772. $manager->expects(self::once())
  773. ->method('getCalendarsForPrincipal')
  774. ->with($principalUri)
  775. ->willReturn([$calendar]);
  776. $calendar->expects(self::once())
  777. ->method('search')
  778. ->willReturn([['uri' => 'testname.ics']]);
  779. $calendar->expects(self::once())
  780. ->method('handleIMipMessage')
  781. ->with('testname.ics', $calendarData->serialize());
  782. $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
  783. $this->assertTrue($result);
  784. }
  785. private function getVCalendarReply(): Document {
  786. $data = <<<EOF
  787. BEGIN:VCALENDAR
  788. PRODID:-//Nextcloud/Nextcloud CalDAV Server//EN
  789. VERSION:2.0
  790. CALSCALE:GREGORIAN
  791. METHOD:REPLY
  792. BEGIN:VEVENT
  793. DTSTART;VALUE=DATE:20210820
  794. DTEND;VALUE=DATE:20220821
  795. DTSTAMP:20210812T100040Z
  796. ORGANIZER;CN=admin:mailto:linus@stardew-tent-living.com
  797. UID:dcc733bf-b2b2-41f2-a8cf-550ae4b67aff
  798. ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=pierr
  799. e@general-store.com;X-NUM-GUESTS=0:mailto:pierre@general-store.com
  800. CREATED:20220812T100021Z
  801. DESCRIPTION:
  802. LAST-MODIFIED:20220812T100040Z
  803. LOCATION:
  804. SEQUENCE:3
  805. STATUS:CONFIRMED
  806. SUMMARY:berry basket
  807. TRANSP:OPAQUE
  808. END:VEVENT
  809. END:VCALENDAR
  810. EOF;
  811. return Reader::read($data);
  812. }
  813. private function getVCalendarCancel(): Document {
  814. $data = <<<EOF
  815. BEGIN:VCALENDAR
  816. PRODID:-//Nextcloud/Nextcloud CalDAV Server//EN
  817. VERSION:2.0
  818. CALSCALE:GREGORIAN
  819. METHOD:CANCEL
  820. BEGIN:VEVENT
  821. DTSTART;VALUE=DATE:20210820
  822. DTEND;VALUE=DATE:20220821
  823. DTSTAMP:20210812T100040Z
  824. ORGANIZER;CN=admin:mailto:linus@stardew-tent-living.com
  825. UID:dcc733bf-b2b2-41f2-a8cf-550ae4b67aff
  826. ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=pierr
  827. e@general-store.com;X-NUM-GUESTS=0:mailto:pierre@general-store.com
  828. CREATED:20220812T100021Z
  829. DESCRIPTION:
  830. LAST-MODIFIED:20220812T100040Z
  831. LOCATION:
  832. SEQUENCE:3
  833. STATUS:CANCELLED
  834. SUMMARY:berry basket
  835. TRANSP:OPAQUE
  836. END:VEVENT
  837. END:VCALENDAR
  838. EOF;
  839. return Reader::read($data);
  840. }
  841. }