You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IMipPluginTest.php 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. * @copyright Copyright (c) 2017, Georg Ehrke
  5. *
  6. * @author brad2014 <brad2014@users.noreply.github.com>
  7. * @author Brad Rubenstein <brad@wbr.tech>
  8. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  9. * @author Georg Ehrke <oc.list@georgehrke.com>
  10. * @author Joas Schilling <coding@schilljs.com>
  11. * @author Morris Jobke <hey@morrisjobke.de>
  12. * @author Thomas Müller <thomas.mueller@tmit.eu>
  13. *
  14. * @license AGPL-3.0
  15. *
  16. * This code is free software: you can redistribute it and/or modify
  17. * it under the terms of the GNU Affero General Public License, version 3,
  18. * as published by the Free Software Foundation.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU Affero General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU Affero General Public License, version 3,
  26. * along with this program. If not, see <http://www.gnu.org/licenses/>
  27. *
  28. */
  29. namespace OCA\DAV\Tests\unit\CalDAV\Schedule;
  30. use OCA\DAV\CalDAV\Schedule\IMipPlugin;
  31. use OCP\AppFramework\Utility\ITimeFactory;
  32. use OCP\DB\QueryBuilder\IQueryBuilder;
  33. use OCP\Defaults;
  34. use OCP\IConfig;
  35. use OCP\IDBConnection;
  36. use OCP\IL10N;
  37. use OCP\ILogger;
  38. use OCP\IURLGenerator;
  39. use OCP\IUser;
  40. use OCP\IUserManager;
  41. use OCP\L10N\IFactory;
  42. use OCP\Mail\IAttachment;
  43. use OCP\Mail\IEMailTemplate;
  44. use OCP\Mail\IMailer;
  45. use OCP\Mail\IMessage;
  46. use OCP\Security\ISecureRandom;
  47. use Sabre\VObject\Component\VCalendar;
  48. use Sabre\VObject\ITip\Message;
  49. use Test\TestCase;
  50. class IMipPluginTest extends TestCase {
  51. protected function setUp(): void {
  52. $this->mailMessage = $this->createMock(IMessage::class);
  53. $this->mailMessage->method('setFrom')->willReturn($this->mailMessage);
  54. $this->mailMessage->method('setReplyTo')->willReturn($this->mailMessage);
  55. $this->mailMessage->method('setTo')->willReturn($this->mailMessage);
  56. $this->mailer = $this->getMockBuilder(IMailer::class)->disableOriginalConstructor()->getMock();
  57. $this->mailer->method('createMessage')->willReturn($this->mailMessage);
  58. $this->emailTemplate = $this->createMock(IEMailTemplate::class);
  59. $this->mailer->method('createEMailTemplate')->willReturn($this->emailTemplate);
  60. $this->emailAttachment = $this->createMock(IAttachment::class);
  61. $this->mailer->method('createAttachment')->willReturn($this->emailAttachment);
  62. $logger = $this->getMockBuilder(ILogger::class)->disableOriginalConstructor()->getMock();
  63. $this->timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock();
  64. $this->timeFactory->method('getTime')->willReturn(1496912528); // 2017-01-01
  65. $this->config = $this->createMock(IConfig::class);
  66. $this->userManager = $this->createMock(IUserManager::class);
  67. $l10n = $this->createMock(IL10N::class);
  68. $l10n->method('t')
  69. ->willReturnCallback(function($text, $parameters = []) {
  70. return vsprintf($text, $parameters);
  71. });
  72. $l10nFactory = $this->createMock(IFactory::class);
  73. $l10nFactory->method('get')->willReturn($l10n);
  74. $urlGenerator = $this->createMock(IURLGenerator::class);
  75. $this->queryBuilder = $this->createMock(IQueryBuilder::class);
  76. $db = $this->createMock(IDBConnection::class);
  77. $db->method('getQueryBuilder')
  78. ->with()
  79. ->willReturn($this->queryBuilder);
  80. $random = $this->createMock(ISecureRandom::class);
  81. $random->method('generate')
  82. ->with(60, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
  83. ->willReturn('random_token');
  84. $defaults = $this->createMock(Defaults::class);
  85. $defaults->method('getName')
  86. ->willReturn('Instance Name 123');
  87. $this->plugin = new IMipPlugin($this->config, $this->mailer, $logger, $this->timeFactory, $l10nFactory, $urlGenerator, $defaults, $random, $db, $this->userManager, 'user123');
  88. }
  89. public function testDelivery() {
  90. $this->config
  91. ->method('getAppValue')
  92. ->with('dav', 'invitation_link_recipients', 'yes')
  93. ->willReturn('yes');
  94. $message = $this->_testMessage();
  95. $this->_expectSend();
  96. $this->plugin->schedule($message);
  97. $this->assertEquals('1.1', $message->getScheduleStatus());
  98. }
  99. public function testFailedDelivery() {
  100. $this->config
  101. ->method('getAppValue')
  102. ->with('dav', 'invitation_link_recipients', 'yes')
  103. ->willReturn('yes');
  104. $message = $this->_testMessage();
  105. $this->mailer
  106. ->method('send')
  107. ->willThrowException(new \Exception());
  108. $this->_expectSend();
  109. $this->plugin->schedule($message);
  110. $this->assertEquals('5.0', $message->getScheduleStatus());
  111. }
  112. public function testDeliveryWithNoCommonName() {
  113. $this->config
  114. ->method('getAppValue')
  115. ->with('dav', 'invitation_link_recipients', 'yes')
  116. ->willReturn('yes');
  117. $message = $this->_testMessage();
  118. $message->senderName = null;
  119. $user = $this->createMock(IUser::class);
  120. $user->method('getDisplayName')->willReturn('Mr. Wizard');
  121. $this->userManager->expects($this->once())
  122. ->method('get')
  123. ->with('user123')
  124. ->willReturn($user);
  125. $this->_expectSend();
  126. $this->plugin->schedule($message);
  127. $this->assertEquals('1.1', $message->getScheduleStatus());
  128. }
  129. /**
  130. * @dataProvider dataNoMessageSendForPastEvents
  131. */
  132. public function testNoMessageSendForPastEvents($veventParams, $expectsMail) {
  133. $this->config
  134. ->method('getAppValue')
  135. ->with('dav', 'invitation_link_recipients', 'yes')
  136. ->willReturn('yes');
  137. $message = $this->_testMessage( $veventParams );
  138. $this->_expectSend('frodo@hobb.it', $expectsMail, $expectsMail);
  139. $this->plugin->schedule($message);
  140. if ($expectsMail) {
  141. $this->assertEquals('1.1', $message->getScheduleStatus());
  142. } else {
  143. $this->assertEquals(false, $message->getScheduleStatus());
  144. }
  145. }
  146. public function dataNoMessageSendForPastEvents() {
  147. return [
  148. [['DTSTART' => new \DateTime('2017-01-01 00:00:00')], false],
  149. [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00')], false],
  150. [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-12-31 00:00:00')], true],
  151. [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DURATION' => 'P1D'], false],
  152. [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DURATION' => 'P52W'], true],
  153. [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY'], true],
  154. [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;COUNT=3'], false],
  155. [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;UNTIL=20170301T000000Z'], false],
  156. [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;COUNT=33'], true],
  157. [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;UNTIL=20171001T000000Z'], true],
  158. ];
  159. }
  160. /**
  161. * @dataProvider dataIncludeResponseButtons
  162. */
  163. public function testIncludeResponseButtons( $config_setting, $recipient, $has_buttons ) {
  164. $message = $this->_testMessage([],$recipient);
  165. $this->_expectSend($recipient, true, $has_buttons);
  166. $this->config
  167. ->method('getAppValue')
  168. ->with('dav', 'invitation_link_recipients', 'yes')
  169. ->willReturn($config_setting);
  170. $this->plugin->schedule($message);
  171. $this->assertEquals('1.1', $message->getScheduleStatus());
  172. }
  173. public function dataIncludeResponseButtons() {
  174. return [
  175. // dav.invitation_link_recipients, recipient, $has_buttons
  176. [ 'yes', 'joe@internal.com', true],
  177. [ 'joe@internal.com', 'joe@internal.com', true],
  178. [ 'internal.com', 'joe@internal.com', true],
  179. [ 'pete@otherinternal.com,internal.com', 'joe@internal.com', true],
  180. [ 'no', 'joe@internal.com', false],
  181. [ 'internal.com', 'joe@external.com', false],
  182. [ 'jane@otherinternal.com,internal.com', 'joe@otherinternal.com', false],
  183. ];
  184. }
  185. private function _testMessage($attrs = [], $recipient = 'frodo@hobb.it' ) {
  186. $message = new Message();
  187. $message->method = 'REQUEST';
  188. $message->message = new VCalendar();
  189. $message->message->add('VEVENT', array_merge([
  190. 'UID' => 'uid-1234',
  191. 'SEQUENCE' => 0,
  192. 'SUMMARY' => 'Fellowship meeting',
  193. 'DTSTART' => new \DateTime('2018-01-01 00:00:00')
  194. ], $attrs));
  195. $message->message->VEVENT->add( 'ORGANIZER', 'mailto:gandalf@wiz.ard' );
  196. $message->message->VEVENT->add( 'ATTENDEE', 'mailto:'.$recipient, [ 'RSVP' => 'TRUE' ] );
  197. $message->sender = 'mailto:gandalf@wiz.ard';
  198. $message->senderName = 'Mr. Wizard';
  199. $message->recipient = 'mailto:'.$recipient;
  200. return $message;
  201. }
  202. private function _expectSend( $recipient = 'frodo@hobb.it', $expectSend = true, $expectButtons = true ) {
  203. // if the event is in the past, we skip out
  204. if (!$expectSend) {
  205. $this->mailer
  206. ->expects($this->never())
  207. ->method('send');
  208. return;
  209. }
  210. $this->emailTemplate->expects($this->once())
  211. ->method('setSubject')
  212. ->with('Invitation: Fellowship meeting');
  213. $this->mailMessage->expects($this->once())
  214. ->method('setTo')
  215. ->with([$recipient => null]);
  216. $this->mailMessage->expects($this->once())
  217. ->method('setReplyTo')
  218. ->with(['gandalf@wiz.ard' => 'Mr. Wizard']);
  219. $this->mailMessage->expects($this->once())
  220. ->method('setFrom')
  221. ->with(['invitations-noreply@localhost' => 'Mr. Wizard via Instance Name 123']);
  222. $this->mailer
  223. ->expects($this->once())
  224. ->method('send');
  225. if ($expectButtons) {
  226. $this->queryBuilder->expects($this->at(0))
  227. ->method('insert')
  228. ->with('calendar_invitations')
  229. ->willReturn($this->queryBuilder);
  230. $this->queryBuilder->expects($this->at(8))
  231. ->method('values')
  232. ->willReturn($this->queryBuilder);
  233. $this->queryBuilder->expects($this->at(9))
  234. ->method('execute');
  235. }
  236. else {
  237. $this->queryBuilder->expects($this->never())
  238. ->method('insert')
  239. ->with('calendar_invitations');
  240. }
  241. }
  242. }