diff options
author | Morris Jobke <hey@morrisjobke.de> | 2017-09-06 22:48:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-06 22:48:46 +0200 |
commit | 8e6d86a862576ab23d884700700580f44cc8cac3 (patch) | |
tree | ffd5d03dd60a2345ef7478ddcc56a84e85e78405 | |
parent | a10c4517cbb20625b5ee32c1809bee40ecbb5456 (diff) | |
parent | a1df91da9d1c2ea7e81601e2cf66ae747536d61f (diff) | |
download | nextcloud-server-8e6d86a862576ab23d884700700580f44cc8cac3.tar.gz nextcloud-server-8e6d86a862576ab23d884700700580f44cc8cac3.zip |
Merge pull request #5304 from nextcloud/bugfix/2855/dont_send_invitations_for_past_events
don't send invitation emails for past events
-rw-r--r-- | apps/dav/appinfo/v1/caldav.php | 2 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/Schedule/IMipPlugin.php | 67 | ||||
-rw-r--r-- | apps/dav/lib/Server.php | 4 | ||||
-rw-r--r-- | apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php | 66 |
4 files changed, 134 insertions, 5 deletions
diff --git a/apps/dav/appinfo/v1/caldav.php b/apps/dav/appinfo/v1/caldav.php index 301ea4b5486..bd9de775f44 100644 --- a/apps/dav/appinfo/v1/caldav.php +++ b/apps/dav/appinfo/v1/caldav.php @@ -84,7 +84,7 @@ if ($debugging) { $server->addPlugin(new \Sabre\DAV\Sync\Plugin()); $server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); $server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin()); -$server->addPlugin(new \OCA\DAV\CalDAV\Schedule\IMipPlugin( \OC::$server->getMailer(), \OC::$server->getLogger())); +$server->addPlugin(new \OCA\DAV\CalDAV\Schedule\IMipPlugin( \OC::$server->getMailer(), \OC::$server->getLogger(), new \OC\AppFramework\Utility\TimeFactory())); $server->addPlugin(new ExceptionLoggerPlugin('caldav', \OC::$server->getLogger())); // And off we go! diff --git a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php index c21edb45848..8e1d7e2563d 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -1,8 +1,10 @@ <?php /** * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2017, Georg Ehrke * * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Georg Ehrke <oc.list@georgehrke.com> * * @license AGPL-3.0 * @@ -21,10 +23,15 @@ */ namespace OCA\DAV\CalDAV\Schedule; +use OCP\AppFramework\Utility\ITimeFactory; use OCP\ILogger; use OCP\Mail\IMailer; +use Sabre\VObject\Component\VCalendar; +use Sabre\VObject\DateTimeParser; use Sabre\VObject\ITip; use Sabre\CalDAV\Schedule\IMipPlugin as SabreIMipPlugin; +use Sabre\VObject\Recur\EventIterator; + /** * iMIP handler. * @@ -47,15 +54,23 @@ class IMipPlugin extends SabreIMipPlugin { /** @var ILogger */ private $logger; + /** @var ITimeFactory */ + private $timeFactory; + + const MAX_DATE = '2038-01-01'; + /** * Creates the email handler. * * @param IMailer $mailer + * @param ILogger $logger + * @param ITimeFactory $timeFactory */ - function __construct(IMailer $mailer, ILogger $logger) { + function __construct(IMailer $mailer, ILogger $logger, ITimeFactory $timeFactory) { parent::__construct(''); $this->mailer = $mailer; $this->logger = $logger; + $this->timeFactory = $timeFactory; } /** @@ -85,6 +100,11 @@ class IMipPlugin extends SabreIMipPlugin { return; } + // don't send out mails for events that already took place + if ($this->isEventInThePast($iTipMessage->message)) { + return; + } + $sender = substr($iTipMessage->sender, 7); $recipient = substr($iTipMessage->recipient, 7); @@ -125,4 +145,49 @@ class IMipPlugin extends SabreIMipPlugin { } } + /** + * check if event took place in the past already + * @param VCalendar $vObject + * @return bool + */ + private function isEventInThePast(VCalendar $vObject) { + $component = $vObject->VEVENT; + + $firstOccurrence = $component->DTSTART->getDateTime()->getTimeStamp(); + // Finding the last occurrence is a bit harder + if (!isset($component->RRULE)) { + if (isset($component->DTEND)) { + $lastOccurrence = $component->DTEND->getDateTime()->getTimeStamp(); + } elseif (isset($component->DURATION)) { + $endDate = clone $component->DTSTART->getDateTime(); + // $component->DTEND->getDateTime() returns DateTimeImmutable + $endDate = $endDate->add(DateTimeParser::parse($component->DURATION->getValue())); + $lastOccurrence = $endDate->getTimeStamp(); + } elseif (!$component->DTSTART->hasTime()) { + $endDate = clone $component->DTSTART->getDateTime(); + // $component->DTSTART->getDateTime() returns DateTimeImmutable + $endDate = $endDate->modify('+1 day'); + $lastOccurrence = $endDate->getTimeStamp(); + } else { + $lastOccurrence = $firstOccurrence; + } + } else { + $it = new EventIterator($vObject, (string)$component->UID); + $maxDate = new \DateTime(self::MAX_DATE); + if ($it->isInfinite()) { + $lastOccurrence = $maxDate->getTimestamp(); + } else { + $end = $it->getDtEnd(); + while($it->valid() && $end < $maxDate) { + $end = $it->getDtEnd(); + $it->next(); + + } + $lastOccurrence = $end->getTimestamp(); + } + } + + $currentTime = $this->timeFactory->getTime(); + return $lastOccurrence < $currentTime; + } } diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index b93f3e6390a..ac0abc8b4eb 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -28,6 +28,7 @@ */ namespace OCA\DAV; +use OC\AppFramework\Utility\TimeFactory; use OCA\DAV\CalDAV\Schedule\IMipPlugin; use OCA\DAV\CardDAV\ImageExportPlugin; use OCA\DAV\CardDAV\PhotoCache; @@ -74,6 +75,7 @@ class Server { $logger = \OC::$server->getLogger(); $mailer = \OC::$server->getMailer(); $dispatcher = \OC::$server->getEventDispatcher(); + $timezone = new TimeFactory(); $root = new RootCollection(); $this->server = new \OCA\DAV\Connector\Sabre\Server(new CachingTree($root)); @@ -135,7 +137,7 @@ class Server { $this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin()); $this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); $this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin()); - $this->server->addPlugin(new IMipPlugin($mailer, $logger)); + $this->server->addPlugin(new IMipPlugin($mailer, $logger, $timezone)); $this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin()); $this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin()); $this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest())); diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php index 2b9d10c9e81..56eb00406da 100644 --- a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php +++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php @@ -1,9 +1,11 @@ <?php /** * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2017, Georg Ehrke * * @author Joas Schilling <coding@schilljs.com> * @author Thomas Müller <thomas.mueller@tmit.eu> + * @author Georg Ehrke <oc.list@georgehrke.com> * * @license AGPL-3.0 * @@ -25,6 +27,7 @@ namespace OCA\DAV\Tests\unit\CalDAV\Schedule; use OC\Mail\Mailer; use OCA\DAV\CalDAV\Schedule\IMipPlugin; +use OCP\AppFramework\Utility\ITimeFactory; use OCP\ILogger; use Sabre\VObject\Component\VCalendar; use Sabre\VObject\ITip\Message; @@ -40,8 +43,10 @@ class IMipPluginTest extends TestCase { $mailer->expects($this->once())->method('send'); /** @var ILogger | \PHPUnit_Framework_MockObject_MockObject $logger */ $logger = $this->getMockBuilder('OC\Log')->disableOriginalConstructor()->getMock(); + $timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock(); + $timeFactory->method('getTime')->willReturn(1); - $plugin = new IMipPlugin($mailer, $logger); + $plugin = new IMipPlugin($mailer, $logger, $timeFactory); $message = new Message(); $message->method = 'REQUEST'; $message->message = new VCalendar(); @@ -49,6 +54,7 @@ class IMipPluginTest extends TestCase { 'UID' => $message->uid, 'SEQUENCE' => $message->sequence, 'SUMMARY' => 'Fellowship meeting', + 'DTSTART' => new \DateTime('2017-01-01 00:00:00') // 1483228800 ]); $message->sender = 'mailto:gandalf@wiz.ard'; $message->recipient = 'mailto:frodo@hobb.it'; @@ -69,8 +75,10 @@ class IMipPluginTest extends TestCase { $mailer->method('send')->willThrowException(new \Exception()); /** @var ILogger | \PHPUnit_Framework_MockObject_MockObject $logger */ $logger = $this->getMockBuilder('OC\Log')->disableOriginalConstructor()->getMock(); + $timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock(); + $timeFactory->method('getTime')->willReturn(1); - $plugin = new IMipPlugin($mailer, $logger); + $plugin = new IMipPlugin($mailer, $logger, $timeFactory); $message = new Message(); $message->method = 'REQUEST'; $message->message = new VCalendar(); @@ -78,6 +86,7 @@ class IMipPluginTest extends TestCase { 'UID' => $message->uid, 'SEQUENCE' => $message->sequence, 'SUMMARY' => 'Fellowship meeting', + 'DTSTART' => new \DateTime('2017-01-01 00:00:00') // 1483228800 ]); $message->sender = 'mailto:gandalf@wiz.ard'; $message->recipient = 'mailto:frodo@hobb.it'; @@ -90,4 +99,57 @@ class IMipPluginTest extends TestCase { $this->assertEquals('text/calendar; charset=UTF-8; method=REQUEST', $mailMessage->getSwiftMessage()->getContentType()); } + /** + * @dataProvider dataNoMessageSendForPastEvents + */ + public function testNoMessageSendForPastEvents($veventParams, $expectsMail) { + $mailMessage = new \OC\Mail\Message(new \Swift_Message()); + /** @var Mailer | \PHPUnit_Framework_MockObject_MockObject $mailer */ + $mailer = $this->getMockBuilder('OC\Mail\Mailer')->disableOriginalConstructor()->getMock(); + $mailer->method('createMessage')->willReturn($mailMessage); + if ($expectsMail) { + $mailer->expects($this->once())->method('send'); + } else { + $mailer->expects($this->never())->method('send'); + } + /** @var ILogger | \PHPUnit_Framework_MockObject_MockObject $logger */ + $logger = $this->getMockBuilder('OC\Log')->disableOriginalConstructor()->getMock(); + $timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock(); + $timeFactory->method('getTime')->willReturn(1496912528); + + $plugin = new IMipPlugin($mailer, $logger, $timeFactory); + $message = new Message(); + $message->method = 'REQUEST'; + $message->message = new VCalendar(); + $message->message->add('VEVENT', array_merge([ + 'UID' => 'uid1337', + 'SEQUENCE' => 42, + 'SUMMARY' => 'Fellowship meeting', + ], $veventParams)); + $message->sender = 'mailto:gandalf@wiz.ard'; + $message->recipient = 'mailto:frodo@hobb.it'; + + $plugin->schedule($message); + + if ($expectsMail) { + $this->assertEquals('1.1', $message->getScheduleStatus()); + } else { + $this->assertEquals(false, $message->getScheduleStatus()); + } + } + + public function dataNoMessageSendForPastEvents() { + return [ + [['DTSTART' => new \DateTime('2017-01-01 00:00:00')], false], + [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00')], false], + [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-12-31 00:00:00')], true], + [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DURATION' => 'P1D'], false], + [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DURATION' => 'P52W'], true], + [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY'], true], + [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;COUNT=3'], false], + [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;UNTIL=20170301T000000Z'], false], + [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;COUNT=33'], true], + [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;UNTIL=20171001T000000Z'], true], + ]; + } } |