From 87bf430307b13970f735403cdd192a98ef519165 Mon Sep 17 00:00:00 2001 From: Brad Rubenstein Date: Sat, 10 Nov 2018 02:35:42 -0800 Subject: [PATCH 1/7] Customize presentation of accept/decline buttons in iMip mail Fix Issue #11230 Only present accept/decline button links in iMip mail for REQUEST, not CANCEL or others. Fix Issue #12156 Implement config setting "dav.invitation_link_recipients", to control which invitation recipients see accept/decline button links. The default, for public internet facing servers, is to always include them. For a server on a private intranet, this setting can be set to the email addresses or email domains of users whose browsers can access the nextcloud server referenced by those accept/decline button links. It can also be set to "false" to exclude the links from all requests. Signed-off-by: Brad Rubenstein --- apps/dav/lib/CalDAV/Schedule/IMipPlugin.php | 42 +++++++++++++++++++-- config/config.sample.php | 27 +++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php index 3ff3ed0c5697a..4375c081d5572 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -144,11 +144,11 @@ public function schedule(Message $iTipMessage) { $summary = $iTipMessage->message->VEVENT->SUMMARY; - if (parse_url($iTipMessage->sender, PHP_URL_SCHEME) !== 'mailto') { + if (strcasecmp(parse_url($iTipMessage->sender, PHP_URL_SCHEME), 'mailto') !== 0) { return; } - if (parse_url($iTipMessage->recipient, PHP_URL_SCHEME) !== 'mailto') { + if (strcasecmp(parse_url($iTipMessage->recipient, PHP_URL_SCHEME), 'mailto') !== 0) { return; } @@ -239,9 +239,44 @@ public function schedule(Message $iTipMessage) { $meetingAttendeeName, $meetingInviteeName); $this->addBulletList($template, $l10n, $meetingWhen, $meetingLocation, $meetingDescription, $meetingUrl); - $this->addResponseButtons($template, $l10n, $iTipMessage, $lastOccurrence); + + + // Only add response buttons to invitation requests: Fix Issue #11230 + if ($method == self::METHOD_REQUEST) { + + /* + ** Only offer invitation accept/reject buttons, which link back to the + ** nextcloud server, to recipients who can access the nextcloud server via + ** their internet/intranet. Issue #12156 + ** + ** For nextcloud servers accessible to the public internet, the default + ** "dav.invitation_link_recipients" value "true" (all recipients) is appropriate. + ** + ** When the nextcloud server is restricted behind a firewall, accessible + ** only via an internal network or via vpn, you can set "dav.invitation_link_recipients" + ** to the email address or email domain, or array of addresses or domains, + ** of recipients who can access the server. + ** + ** To deliver URL's always, set invitation_link_recipients to boolean "true". + ** To suppress URL's entirely, set invitation_link_recipients to boolean "false". + */ + + $recipientDomain = substr(strrchr($recipient, "@"), 1); + $invitationLinkRecipients = $this->config->getSystemValue('dav.invitation_link_recipients', true); + if (is_array($invitationLinkRecipients)) { + $invitationLinkRecipients = array_map('strtolower', $invitationLinkRecipients); // for case insensitive in_array + } + if ($invitationLinkRecipients === true + || (is_string($invitationLinkRecipients) && strcasecmp($recipient, $invitationLinkRecipients) === 0) + || (is_string($invitationLinkRecipients) && strcasecmp($recipientDomain, $invitationLinkRecipients) === 0) + || (is_array($invitationLinkRecipients) && in_array(strtolower($recipient), $invitationLinkRecipients)) + || (is_array($invitationLinkRecipients) && in_array(strtolower($recipientDomain), $invitationLinkRecipients))) { + $this->addResponseButtons($template, $l10n, $iTipMessage, $lastOccurrence); + } + } $template->addFooter(); + $message->useTemplate($template); $attachment = $this->mailer->createAttachment( @@ -447,7 +482,6 @@ private function addSubjectAndHeading(IEMailTemplate $template, IL10N $l10n, $template->setSubject('Invitation: ' . $summary); $template->addHeading($l10n->t('%1$s invited you to »%2$s«', [$inviteeName, $summary]), $l10n->t('Hello %s,', [$attendeeName])); } - } /** diff --git a/config/config.sample.php b/config/config.sample.php index f939fc371b70f..20b0f37557173 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -1688,6 +1688,33 @@ '/^Microsoft-WebDAV-MiniRedir/', // Windows webdav drive ), +/** +* The caldav server sends invitation emails to invitees, attaching the ICS +* file for the invitation. It also may include, in the body of the e-mail, +* invitation accept/reject web links referencing URL's that point to the nextcloud server. +* +* Although any recipient can read and reply to the ICS file via the iMip protocol, +* we must only present the web links to recipients who can access the nextcloud +* web server via their internet/intranet. +* +* When your nextcloud server is restricted behind a firewall, accessible +* only via an internal network or via vpn, you can set "dav.invitation_link_recipients" +* to the email address or email domain, or array of addresses or domains, +* of recipients who can access the server. Only those recipients will get web links. External +* users can accept/reject invitations by emailing back ICS files containing appropriate +* messages, using the iMip protocol. Many mail clients support this functionality. +* +* To suppress iMip web links entirely, set dav.invitation_link_recipients to false. +* To deliver iMip web links always, set dav.invitation_link_recipients to true. +* +* Examples: +* 'dav.invitation_link_recipients' => 'internal.example.com', +* 'dav.invitation_link_recipients' => array( 'internal.example.com', 'pat@roadwarrior.example.com' ), +* 'dav.invitation_link_recipients' => false, +* +*/ +'dav.invitation_link_recipients' => '*', // always include accept/reject server links in iMip emails + /** * By default there is on public pages a link shown that allows users to * learn about the "simple sign up" - see https://nextcloud.com/signup/ From e334aab702c8eeed8dc255c51f42cd0f4f5f4996 Mon Sep 17 00:00:00 2001 From: Brad Rubenstein Date: Sat, 10 Nov 2018 08:53:15 -0800 Subject: [PATCH 2/7] corrected sample config Signed-off-by: Brad Rubenstein --- config/config.sample.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.sample.php b/config/config.sample.php index 20b0f37557173..869c24590b3b9 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -1713,7 +1713,7 @@ * 'dav.invitation_link_recipients' => false, * */ -'dav.invitation_link_recipients' => '*', // always include accept/reject server links in iMip emails +'dav.invitation_link_recipients' => true, // always include accept/reject server links in iMip emails /** * By default there is on public pages a link shown that allows users to From 2d756ace607b1a06e978a28b9b93a7258deceabd Mon Sep 17 00:00:00 2001 From: Brad Rubenstein Date: Mon, 12 Nov 2018 12:11:47 -0800 Subject: [PATCH 3/7] Respect RSVP parameter for attendees when adding accept/decline buttons. If RSVP=TRUE parameter is FALSE or absent for an ATTENDEE, then do no present accept/decline buttons. The organizer isn't asking for an RSVP. Signed-off-by: Brad Rubenstein --- apps/dav/lib/CalDAV/Schedule/IMipPlugin.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php index 4375c081d5572..987e6c86f5d40 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -242,7 +242,7 @@ public function schedule(Message $iTipMessage) { // Only add response buttons to invitation requests: Fix Issue #11230 - if ($method == self::METHOD_REQUEST) { + if (($method == self::METHOD_REQUEST) && $this->getAttendeeRSVP($attendee)) { /* ** Only offer invitation accept/reject buttons, which link back to the @@ -380,6 +380,21 @@ private function getAttendeeLangOrDefault($default, Property $attendee = null) { return $default; } + /** + * @param Property|null $attendee + * @return bool + */ + private function getAttendeeRSVP(Property $attendee = null) { + if ($attendee !== null) { + $rsvp = $attendee->offsetGet('RSVP'); + if (($rsvp instanceof Parameter) && (strcasecmp($rsvp->getValue(), 'TRUE') === 0)) { + return true; + } + } + // RFC 5545 3.2.17: default RSVP is false + return false; + } + /** * @param IL10N $l10n * @param Property $dtstart @@ -538,7 +553,7 @@ private function addResponseButtons(IEMailTemplate $template, IL10N $l10n, $moreOptionsURL, $l10n->t('More options …') ]); $text = $l10n->t('More options at %s', [$moreOptionsURL]); - + $template->addBodyText($html, $text); } From 3510fdc798a4749cf7e9b82e00a461387ea9742e Mon Sep 17 00:00:00 2001 From: Brad Rubenstein Date: Mon, 12 Nov 2018 12:59:12 -0800 Subject: [PATCH 4/7] Revert 3ff3ed0c56 case-insensitive compares. My oops. The comparisons, which are copied from the IMipPlugin shipped with sabre-io/dav, do not need to be case insensitive because the sender and recipient names are normalized by sabre, (see calls to getNormalizedValue in voboject/lib/ITip/Broker.php). Signed-off-by: Brad Rubenstein --- apps/dav/lib/CalDAV/Schedule/IMipPlugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php index 987e6c86f5d40..7035d3c780f5e 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -144,11 +144,11 @@ public function schedule(Message $iTipMessage) { $summary = $iTipMessage->message->VEVENT->SUMMARY; - if (strcasecmp(parse_url($iTipMessage->sender, PHP_URL_SCHEME), 'mailto') !== 0) { + if (parse_url($iTipMessage->sender, PHP_URL_SCHEME) !== 'mailto') { return; } - if (strcasecmp(parse_url($iTipMessage->recipient, PHP_URL_SCHEME), 'mailto') !== 0) { + if (parse_url($iTipMessage->recipient, PHP_URL_SCHEME) !== 'mailto') { return; } From e451905040817771ffc8ea76553ae00c7770f249 Mon Sep 17 00:00:00 2001 From: Brad Rubenstein Date: Thu, 28 Feb 2019 01:22:53 +0000 Subject: [PATCH 5/7] IMipPlugin: Added unit test for dav.invitation_link_recipients support Existing tests required modification to correctly mock up the new config parameter fetch, and to set the RSVP flag for attendees (since the test was detecting token generation, and we no longer generate tokens when no RSVP is requested by the client or sent by nextcloud). Signed-off-by: Brad Rubenstein --- .../unit/CalDAV/Schedule/IMipPluginTest.php | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php index c95b32041e042..0ba670879f1f6 100644 --- a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php +++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php @@ -67,6 +67,9 @@ public function testDelivery() { $timeFactory->method('getTime')->willReturn(1); /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject $config */ $config = $this->createMock(IConfig::class); + $config->method('getSystemValue') + ->with('dav.invitation_link_recipients', true) + ->willReturn(true); $l10n = $this->createMock(IL10N::class); /** @var IFactory | \PHPUnit_Framework_MockObject_MockObject $l10nFactory */ $l10nFactory = $this->createMock(IFactory::class); @@ -114,6 +117,10 @@ public function testDelivery() { 'SUMMARY' => 'Fellowship meeting', 'DTSTART' => new \DateTime('2017-01-01 00:00:00') // 1483228800 ]); + + $message->message->VEVENT->add( 'ORGANIZER', 'mailto:gandalf@wiz.ard' ); + $message->message->VEVENT->add( 'ATTENDEE', 'mailto:frodo@hobb.it', [ 'RSVP' => 'TRUE' ] ); + $message->sender = 'mailto:gandalf@wiz.ard'; $message->recipient = 'mailto:frodo@hobb.it'; @@ -150,6 +157,10 @@ public function testFailedDelivery() { $timeFactory->method('getTime')->willReturn(1); /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject $config */ $config = $this->createMock(IConfig::class); + $config->method('getSystemValue') + ->with('dav.invitation_link_recipients', true) + ->willReturn(true); + $l10n = $this->createMock(IL10N::class); /** @var IFactory | \PHPUnit_Framework_MockObject_MockObject $l10nFactory */ $l10nFactory = $this->createMock(IFactory::class); @@ -194,6 +205,8 @@ public function testFailedDelivery() { 'SUMMARY' => 'Fellowship meeting', 'DTSTART' => new \DateTime('2017-01-01 00:00:00') // 1483228800 ]); + $message->message->VEVENT->add( 'ORGANIZER', 'mailto:gandalf@wiz.ard' ); + $message->message->VEVENT->add( 'ATTENDEE', 'mailto:frodo@hobb.it', [ 'RSVP' => 'TRUE' ] ); $message->sender = 'mailto:gandalf@wiz.ard'; $message->recipient = 'mailto:frodo@hobb.it'; @@ -237,6 +250,9 @@ public function testNoMessageSendForPastEvents($veventParams, $expectsMail) { $timeFactory->method('getTime')->willReturn(1496912528); /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject $config */ $config = $this->createMock(IConfig::class); + $config->method('getSystemValue') + ->with('dav.invitation_link_recipients', true) + ->willReturn(true); $l10n = $this->createMock(IL10N::class); /** @var IFactory | \PHPUnit_Framework_MockObject_MockObject $l10nFactory */ $l10nFactory = $this->createMock(IFactory::class); @@ -282,6 +298,8 @@ public function testNoMessageSendForPastEvents($veventParams, $expectsMail) { 'SEQUENCE' => 42, 'SUMMARY' => 'Fellowship meeting', ], $veventParams)); + $message->message->VEVENT->add( 'ORGANIZER', 'mailto:gandalf@wiz.ard' ); + $message->message->VEVENT->add( 'ATTENDEE', 'mailto:frodo@hobb.it', [ 'RSVP' => 'TRUE' ] ); $message->sender = 'mailto:gandalf@wiz.ard'; $message->recipient = 'mailto:frodo@hobb.it'; @@ -308,4 +326,118 @@ public function dataNoMessageSendForPastEvents() { [['DTSTART' => new \DateTime('2017-01-01 00:00:00'), 'DTEND' => new \DateTime('2017-01-01 00:00:00'), 'RRULE' => 'FREQ=WEEKLY;UNTIL=20171001T000000Z'], true], ]; } + + /** + * @dataProvider dataIncludeResponseButtons + */ + public function testIncludeResponseButtons( $config_setting, $recipient, $has_buttons ) { + $mailMessage = $this->createMock(IMessage::class); + $mailMessage->method('setFrom')->willReturn($mailMessage); + $mailMessage->method('setReplyTo')->willReturn($mailMessage); + $mailMessage->method('setTo')->willReturn($mailMessage); + /** @var Mailer | \PHPUnit_Framework_MockObject_MockObject $mailer */ + $mailer = $this->getMockBuilder(IMailer::class)->disableOriginalConstructor()->getMock(); + $emailTemplate = $this->createMock(IEMailTemplate::class); + $emailAttachment = $this->createMock(IAttachment::class); + $mailer->method('createEMailTemplate')->willReturn($emailTemplate); + $mailer->method('createMessage')->willReturn($mailMessage); + $mailer->method('createAttachment')->willReturn($emailAttachment); + $mailer->expects($this->once())->method('send'); + /** @var ILogger | \PHPUnit_Framework_MockObject_MockObject $logger */ + $logger = $this->getMockBuilder(ILogger::class)->disableOriginalConstructor()->getMock(); + $timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock(); + $timeFactory->method('getTime')->willReturn(1); + /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject $config */ + $config = $this->createMock(IConfig::class); + $config->method('getSystemValue') + ->with('dav.invitation_link_recipients', true) + ->willReturn($config_setting); + $l10n = $this->createMock(IL10N::class); + /** @var IFactory | \PHPUnit_Framework_MockObject_MockObject $l10nFactory */ + $l10nFactory = $this->createMock(IFactory::class); + $l10nFactory->method('get')->willReturn($l10n); + /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject $urlGenerator */ + $urlGenerator = $this->createMock(IURLGenerator::class); + /** @var IDBConnection | \PHPUnit_Framework_MockObject_MockObject $db */ + $db = $this->createMock(IDBConnection::class); + /** @var ISecureRandom | \PHPUnit_Framework_MockObject_MockObject $random */ + $random = $this->createMock(ISecureRandom::class); + /** @var Defaults | \PHPUnit_Framework_MockObject_MockObject $defaults */ + $defaults = $this->createMock(Defaults::class); + $defaults->expects($this->once()) + ->method('getName') + ->will($this->returnValue('Instance Name 123')); + + if ($has_buttons) { + $random->expects($this->once()) + ->method('generate') + ->with(60, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') + ->will($this->returnValue('random_token')); + } + + $queryBuilder = $this->createMock(IQueryBuilder::class); + + if ($has_buttons) { + $db->expects($this->once()) + ->method('getQueryBuilder') + ->with() + ->will($this->returnValue($queryBuilder)); + $queryBuilder->expects($this->at(0)) + ->method('insert') + ->with('calendar_invitations') + ->will($this->returnValue($queryBuilder)); + $queryBuilder->expects($this->at(8)) + ->method('values') + ->will($this->returnValue($queryBuilder)); + $queryBuilder->expects($this->at(9)) + ->method('execute'); + } else { + $queryBuilder->expects($this->never()) + ->method('insert') + ->with('calendar_invitations'); + } + + $plugin = new IMipPlugin($config, $mailer, $logger, $timeFactory, $l10nFactory, $urlGenerator, $defaults, $random, $db, 'user123'); + $message = new Message(); + $message->method = 'REQUEST'; + $message->message = new VCalendar(); + $message->message->add('VEVENT', [ + 'UID' => $message->uid, + 'SEQUENCE' => $message->sequence, + 'SUMMARY' => 'Fellowship meeting', + 'DTSTART' => new \DateTime('2017-01-01 00:00:00') // 1483228800 + ]); + + $message->message->VEVENT->add( 'ORGANIZER', 'mailto:gandalf@wiz.ard' ); + $message->message->VEVENT->add( 'ATTENDEE', 'mailto:'.$recipient, [ 'RSVP' => 'TRUE' ] ); + + $message->sender = 'mailto:gandalf@wiz.ard'; + $message->recipient = 'mailto:'.$recipient; + + $emailTemplate->expects($this->once()) + ->method('setSubject') + ->with('Invitation: Fellowship meeting'); + $mailMessage->expects($this->once()) + ->method('setTo') + ->with([$recipient => null]); + $mailMessage->expects($this->once()) + ->method('setReplyTo') + ->with(['gandalf@wiz.ard' => null]); + + $plugin->schedule($message); + $this->assertEquals('1.1', $message->getScheduleStatus()); + } + + public function dataIncludeResponseButtons() { + return [ + // dav.invitation_link_recipients, recipient, $has_buttons + [ true, 'joe@internal.com', true], + [ 'joe@internal.com', 'joe@internal.com', true], + [ 'internal.com', 'joe@internal.com', true], + [ ['pete@otherinternal.com', 'internal.com'], 'joe@internal.com', true], + [ false, 'joe@internal.com', false], + [ 'internal.com', 'joe@external.com', false], + [ ['jane@otherinternal.com', 'internal.com'], 'joe@otherinternal.com', false], + ]; + } } From f0336890e9e68a43b14ed0547dc8bd02df3890e1 Mon Sep 17 00:00:00 2001 From: Brad Rubenstein Date: Thu, 28 Feb 2019 01:25:27 +0000 Subject: [PATCH 6/7] IMipPlugin: DRY up - move common test set-up into setUp function Signed-off-by: Brad Rubenstein --- .../unit/CalDAV/Schedule/IMipPluginTest.php | 428 +++++------------- 1 file changed, 117 insertions(+), 311 deletions(-) diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php index 0ba670879f1f6..84da1d2727c0f 100644 --- a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php +++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php @@ -48,179 +48,76 @@ class IMipPluginTest extends TestCase { - public function testDelivery() { - $mailMessage = $this->createMock(IMessage::class); - $mailMessage->method('setFrom')->willReturn($mailMessage); - $mailMessage->method('setReplyTo')->willReturn($mailMessage); - $mailMessage->method('setTo')->willReturn($mailMessage); - /** @var Mailer | \PHPUnit_Framework_MockObject_MockObject $mailer */ - $mailer = $this->getMockBuilder(IMailer::class)->disableOriginalConstructor()->getMock(); - $emailTemplate = $this->createMock(IEMailTemplate::class); - $emailAttachment = $this->createMock(IAttachment::class); - $mailer->method('createEMailTemplate')->willReturn($emailTemplate); - $mailer->method('createMessage')->willReturn($mailMessage); - $mailer->method('createAttachment')->willReturn($emailAttachment); - $mailer->expects($this->once())->method('send'); - /** @var ILogger | \PHPUnit_Framework_MockObject_MockObject $logger */ + public function setUp() { + $this->mailMessage = $this->createMock(IMessage::class); + $this->mailMessage->method('setFrom')->willReturn($this->mailMessage); + $this->mailMessage->method('setReplyTo')->willReturn($this->mailMessage); + $this->mailMessage->method('setTo')->willReturn($this->mailMessage); + + $this->mailer = $this->getMockBuilder(IMailer::class)->disableOriginalConstructor()->getMock(); + $this->mailer->method('createMessage')->willReturn($this->mailMessage); + + $this->emailTemplate = $this->createMock(IEMailTemplate::class); + $this->mailer->method('createEMailTemplate')->willReturn($this->emailTemplate); + + $this->emailAttachment = $this->createMock(IAttachment::class); + $this->mailer->method('createAttachment')->willReturn($this->emailAttachment); + $logger = $this->getMockBuilder(ILogger::class)->disableOriginalConstructor()->getMock(); - $timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock(); - $timeFactory->method('getTime')->willReturn(1); - /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject $config */ - $config = $this->createMock(IConfig::class); - $config->method('getSystemValue') - ->with('dav.invitation_link_recipients', true) - ->willReturn(true); + + $this->timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock(); + $this->timeFactory->method('getTime')->willReturn(1496912528); // 2017-01-01 + + $this->config = $this->createMock(IConfig::class); + $l10n = $this->createMock(IL10N::class); - /** @var IFactory | \PHPUnit_Framework_MockObject_MockObject $l10nFactory */ $l10nFactory = $this->createMock(IFactory::class); $l10nFactory->method('get')->willReturn($l10n); - /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject $urlGenerator */ + $urlGenerator = $this->createMock(IURLGenerator::class); - /** @var IDBConnection | \PHPUnit_Framework_MockObject_MockObject $db */ + + $this->queryBuilder = $this->createMock(IQueryBuilder::class); $db = $this->createMock(IDBConnection::class); - /** @var ISecureRandom | \PHPUnit_Framework_MockObject_MockObject $random */ - $random = $this->createMock(ISecureRandom::class); - /** @var Defaults | \PHPUnit_Framework_MockObject_MockObject $defaults */ - $defaults = $this->createMock(Defaults::class); - $defaults->expects($this->once()) - ->method('getName') - ->will($this->returnValue('Instance Name 123')); + $db->method('getQueryBuilder') + ->with() + ->will($this->returnValue($this->queryBuilder)); - $random->expects($this->once()) - ->method('generate') + $random = $this->createMock(ISecureRandom::class); + $random->method('generate') ->with(60, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') ->will($this->returnValue('random_token')); - $queryBuilder = $this->createMock(IQueryBuilder::class); - - $db->expects($this->once()) - ->method('getQueryBuilder') - ->with() - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(0)) - ->method('insert') - ->with('calendar_invitations') - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(8)) - ->method('values') - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(9)) - ->method('execute'); - - $plugin = new IMipPlugin($config, $mailer, $logger, $timeFactory, $l10nFactory, $urlGenerator, $defaults, $random, $db, 'user123'); - $message = new Message(); - $message->method = 'REQUEST'; - $message->message = new VCalendar(); - $message->message->add('VEVENT', [ - 'UID' => $message->uid, - 'SEQUENCE' => $message->sequence, - 'SUMMARY' => 'Fellowship meeting', - 'DTSTART' => new \DateTime('2017-01-01 00:00:00') // 1483228800 - ]); - - $message->message->VEVENT->add( 'ORGANIZER', 'mailto:gandalf@wiz.ard' ); - $message->message->VEVENT->add( 'ATTENDEE', 'mailto:frodo@hobb.it', [ 'RSVP' => 'TRUE' ] ); + $defaults = $this->createMock(Defaults::class); + $defaults->method('getName') + ->will($this->returnValue('Instance Name 123')); - $message->sender = 'mailto:gandalf@wiz.ard'; - $message->recipient = 'mailto:frodo@hobb.it'; + $this->plugin = new IMipPlugin($this->config, $this->mailer, $logger, $this->timeFactory, $l10nFactory, $urlGenerator, $defaults, $random, $db, 'user123'); + } - $emailTemplate->expects($this->once()) - ->method('setSubject') - ->with('Invitation: Fellowship meeting'); - $mailMessage->expects($this->once()) - ->method('setTo') - ->with(['frodo@hobb.it' => null]); - $mailMessage->expects($this->once()) - ->method('setReplyTo') - ->with(['gandalf@wiz.ard' => null]); + public function testDelivery() { + $this->config + ->method('getSystemValue') + ->with('dav.invitation_link_recipients', true) + ->willReturn(true); - $plugin->schedule($message); + $message = $this->_testMessage(); + $this->_expectSend(); + $this->plugin->schedule($message); $this->assertEquals('1.1', $message->getScheduleStatus()); } public function testFailedDelivery() { - $mailMessage = $this->createMock(IMessage::class); - $mailMessage->method('setFrom')->willReturn($mailMessage); - $mailMessage->method('setReplyTo')->willReturn($mailMessage); - $mailMessage->method('setTo')->willReturn($mailMessage); - /** @var Mailer | \PHPUnit_Framework_MockObject_MockObject $mailer */ - $mailer = $this->getMockBuilder(IMailer::class)->disableOriginalConstructor()->getMock(); - $emailTemplate = $this->createMock(IEMailTemplate::class); - $emailAttachment = $this->createMock(IAttachment::class); - $mailer->method('createEMailTemplate')->willReturn($emailTemplate); - $mailer->method('createMessage')->willReturn($mailMessage); - $mailer->method('createAttachment')->willReturn($emailAttachment); - $mailer->method('send')->willThrowException(new \Exception()); - /** @var ILogger | \PHPUnit_Framework_MockObject_MockObject $logger */ - $logger = $this->getMockBuilder(ILogger::class)->disableOriginalConstructor()->getMock(); - $timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock(); - $timeFactory->method('getTime')->willReturn(1); - /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject $config */ - $config = $this->createMock(IConfig::class); - $config->method('getSystemValue') + $this->config + ->method('getSystemValue') ->with('dav.invitation_link_recipients', true) ->willReturn(true); - $l10n = $this->createMock(IL10N::class); - /** @var IFactory | \PHPUnit_Framework_MockObject_MockObject $l10nFactory */ - $l10nFactory = $this->createMock(IFactory::class); - $l10nFactory->method('get')->willReturn($l10n); - /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject $urlGenerator */ - $urlGenerator = $this->createMock(IURLGenerator::class); - /** @var IDBConnection | \PHPUnit_Framework_MockObject_MockObject $db */ - $db = $this->createMock(IDBConnection::class); - /** @var ISecureRandom | \PHPUnit_Framework_MockObject_MockObject $random */ - $random = $this->createMock(ISecureRandom::class); - /** @var Defaults | \PHPUnit_Framework_MockObject_MockObject $defaults */ - $defaults = $this->createMock(Defaults::class); - - $random->expects($this->once()) - ->method('generate') - ->with(60, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') - ->will($this->returnValue('random_token')); - - $queryBuilder = $this->createMock(IQueryBuilder::class); - - $db->expects($this->once()) - ->method('getQueryBuilder') - ->with() - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(0)) - ->method('insert') - ->with('calendar_invitations') - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(8)) - ->method('values') - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(9)) - ->method('execute'); - - $plugin = new IMipPlugin($config, $mailer, $logger, $timeFactory, $l10nFactory, $urlGenerator, $defaults, $random, $db, 'user123'); - $message = new Message(); - $message->method = 'REQUEST'; - $message->message = new VCalendar(); - $message->message->add('VEVENT', [ - 'UID' => $message->uid, - 'SEQUENCE' => $message->sequence, - 'SUMMARY' => 'Fellowship meeting', - 'DTSTART' => new \DateTime('2017-01-01 00:00:00') // 1483228800 - ]); - $message->message->VEVENT->add( 'ORGANIZER', 'mailto:gandalf@wiz.ard' ); - $message->message->VEVENT->add( 'ATTENDEE', 'mailto:frodo@hobb.it', [ 'RSVP' => 'TRUE' ] ); - $message->sender = 'mailto:gandalf@wiz.ard'; - $message->recipient = 'mailto:frodo@hobb.it'; - - $emailTemplate->expects($this->once()) - ->method('setSubject') - ->with('Invitation: Fellowship meeting'); - $mailMessage->expects($this->once()) - ->method('setTo') - ->with(['frodo@hobb.it' => null]); - $mailMessage->expects($this->once()) - ->method('setReplyTo') - ->with(['gandalf@wiz.ard' => null]); - - $plugin->schedule($message); + $message = $this->_testMessage(); + $this->mailer + ->method('send') + ->willThrowException(new \Exception()); + $this->_expectSend(); + $this->plugin->schedule($message); $this->assertEquals('5.0', $message->getScheduleStatus()); } @@ -228,82 +125,17 @@ public function testFailedDelivery() { * @dataProvider dataNoMessageSendForPastEvents */ public function testNoMessageSendForPastEvents($veventParams, $expectsMail) { - $mailMessage = $this->createMock(IMessage::class); - $mailMessage->method('setFrom')->willReturn($mailMessage); - $mailMessage->method('setReplyTo')->willReturn($mailMessage); - $mailMessage->method('setTo')->willReturn($mailMessage); - /** @var Mailer | \PHPUnit_Framework_MockObject_MockObject $mailer */ - $mailer = $this->getMockBuilder(IMailer::class)->disableOriginalConstructor()->getMock(); - $emailTemplate = $this->createMock(IEMailTemplate::class); - $emailAttachment = $this->createMock(IAttachment::class); - $mailer->method('createEMailTemplate')->willReturn($emailTemplate); - $mailer->method('createMessage')->willReturn($mailMessage); - $mailer->method('createAttachment')->willReturn($emailAttachment); - 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(ILogger::class)->disableOriginalConstructor()->getMock(); - $timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock(); - $timeFactory->method('getTime')->willReturn(1496912528); - /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject $config */ - $config = $this->createMock(IConfig::class); - $config->method('getSystemValue') + + $this->config + ->method('getSystemValue') ->with('dav.invitation_link_recipients', true) ->willReturn(true); - $l10n = $this->createMock(IL10N::class); - /** @var IFactory | \PHPUnit_Framework_MockObject_MockObject $l10nFactory */ - $l10nFactory = $this->createMock(IFactory::class); - $l10nFactory->method('get')->willReturn($l10n); - /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject $urlGenerator */ - $urlGenerator = $this->createMock(IURLGenerator::class); - /** @var IDBConnection | \PHPUnit_Framework_MockObject_MockObject $db */ - $db = $this->createMock(IDBConnection::class); - /** @var ISecureRandom | \PHPUnit_Framework_MockObject_MockObject $random */ - $random = $this->createMock(ISecureRandom::class); - /** @var Defaults | \PHPUnit_Framework_MockObject_MockObject $defaults */ - $defaults = $this->createMock(Defaults::class); - if ($expectsMail) { - $random->expects($this->once()) - ->method('generate') - ->with(60, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') - ->will($this->returnValue('random_token')); - - $queryBuilder = $this->createMock(IQueryBuilder::class); - - $db->expects($this->once()) - ->method('getQueryBuilder') - ->with() - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(0)) - ->method('insert') - ->with('calendar_invitations') - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(8)) - ->method('values') - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(9)) - ->method('execute'); - } + $message = $this->_testMessage( $veventParams ); - $plugin = new IMipPlugin($config, $mailer, $logger, $timeFactory, $l10nFactory, $urlGenerator, $defaults, $random, $db, 'user123'); - $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->message->VEVENT->add( 'ORGANIZER', 'mailto:gandalf@wiz.ard' ); - $message->message->VEVENT->add( 'ATTENDEE', 'mailto:frodo@hobb.it', [ 'RSVP' => 'TRUE' ] ); - $message->sender = 'mailto:gandalf@wiz.ard'; - $message->recipient = 'mailto:frodo@hobb.it'; + $this->_expectSend('frodo@hobb.it', $expectsMail, $expectsMail); - $plugin->schedule($message); + $this->plugin->schedule($message); if ($expectsMail) { $this->assertEquals('1.1', $message->getScheduleStatus()); @@ -331,113 +163,87 @@ public function dataNoMessageSendForPastEvents() { * @dataProvider dataIncludeResponseButtons */ public function testIncludeResponseButtons( $config_setting, $recipient, $has_buttons ) { - $mailMessage = $this->createMock(IMessage::class); - $mailMessage->method('setFrom')->willReturn($mailMessage); - $mailMessage->method('setReplyTo')->willReturn($mailMessage); - $mailMessage->method('setTo')->willReturn($mailMessage); - /** @var Mailer | \PHPUnit_Framework_MockObject_MockObject $mailer */ - $mailer = $this->getMockBuilder(IMailer::class)->disableOriginalConstructor()->getMock(); - $emailTemplate = $this->createMock(IEMailTemplate::class); - $emailAttachment = $this->createMock(IAttachment::class); - $mailer->method('createEMailTemplate')->willReturn($emailTemplate); - $mailer->method('createMessage')->willReturn($mailMessage); - $mailer->method('createAttachment')->willReturn($emailAttachment); - $mailer->expects($this->once())->method('send'); - /** @var ILogger | \PHPUnit_Framework_MockObject_MockObject $logger */ - $logger = $this->getMockBuilder(ILogger::class)->disableOriginalConstructor()->getMock(); - $timeFactory = $this->getMockBuilder(ITimeFactory::class)->disableOriginalConstructor()->getMock(); - $timeFactory->method('getTime')->willReturn(1); - /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject $config */ - $config = $this->createMock(IConfig::class); - $config->method('getSystemValue') + $message = $this->_testMessage([],$recipient); + + $this->_expectSend($recipient, true, $has_buttons); + $this->config + ->method('getSystemValue') ->with('dav.invitation_link_recipients', true) ->willReturn($config_setting); - $l10n = $this->createMock(IL10N::class); - /** @var IFactory | \PHPUnit_Framework_MockObject_MockObject $l10nFactory */ - $l10nFactory = $this->createMock(IFactory::class); - $l10nFactory->method('get')->willReturn($l10n); - /** @var IURLGenerator | \PHPUnit_Framework_MockObject_MockObject $urlGenerator */ - $urlGenerator = $this->createMock(IURLGenerator::class); - /** @var IDBConnection | \PHPUnit_Framework_MockObject_MockObject $db */ - $db = $this->createMock(IDBConnection::class); - /** @var ISecureRandom | \PHPUnit_Framework_MockObject_MockObject $random */ - $random = $this->createMock(ISecureRandom::class); - /** @var Defaults | \PHPUnit_Framework_MockObject_MockObject $defaults */ - $defaults = $this->createMock(Defaults::class); - $defaults->expects($this->once()) - ->method('getName') - ->will($this->returnValue('Instance Name 123')); - - if ($has_buttons) { - $random->expects($this->once()) - ->method('generate') - ->with(60, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') - ->will($this->returnValue('random_token')); - } - $queryBuilder = $this->createMock(IQueryBuilder::class); + $this->plugin->schedule($message); + $this->assertEquals('1.1', $message->getScheduleStatus()); + } - if ($has_buttons) { - $db->expects($this->once()) - ->method('getQueryBuilder') - ->with() - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(0)) - ->method('insert') - ->with('calendar_invitations') - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(8)) - ->method('values') - ->will($this->returnValue($queryBuilder)); - $queryBuilder->expects($this->at(9)) - ->method('execute'); - } else { - $queryBuilder->expects($this->never()) - ->method('insert') - ->with('calendar_invitations'); - } + public function dataIncludeResponseButtons() { + return [ + // dav.invitation_link_recipients, recipient, $has_buttons + [ true, 'joe@internal.com', true], + [ 'joe@internal.com', 'joe@internal.com', true], + [ 'internal.com', 'joe@internal.com', true], + [ ['pete@otherinternal.com', 'internal.com'], 'joe@internal.com', true], + [ false, 'joe@internal.com', false], + [ 'internal.com', 'joe@external.com', false], + [ ['jane@otherinternal.com', 'internal.com'], 'joe@otherinternal.com', false], + ]; + } - $plugin = new IMipPlugin($config, $mailer, $logger, $timeFactory, $l10nFactory, $urlGenerator, $defaults, $random, $db, 'user123'); + private function _testMessage($attrs = [], $recipient = 'frodo@hobb.it' ) { $message = new Message(); $message->method = 'REQUEST'; $message->message = new VCalendar(); - $message->message->add('VEVENT', [ - 'UID' => $message->uid, - 'SEQUENCE' => $message->sequence, + $message->message->add('VEVENT', array_merge([ + 'UID' => 'uid-1234', + 'SEQUENCE' => 0, 'SUMMARY' => 'Fellowship meeting', - 'DTSTART' => new \DateTime('2017-01-01 00:00:00') // 1483228800 - ]); - + 'DTSTART' => new \DateTime('2018-01-01 00:00:00') + ], $attrs)); $message->message->VEVENT->add( 'ORGANIZER', 'mailto:gandalf@wiz.ard' ); $message->message->VEVENT->add( 'ATTENDEE', 'mailto:'.$recipient, [ 'RSVP' => 'TRUE' ] ); - $message->sender = 'mailto:gandalf@wiz.ard'; $message->recipient = 'mailto:'.$recipient; + return $message; + } + - $emailTemplate->expects($this->once()) + private function _expectSend( $recipient = 'frodo@hobb.it', $expectSend = true, $expectButtons = true ) { + + // if the event is in the past, we skip out + if (!$expectSend) { + $this->mailer + ->expects($this->never()) + ->method('send'); + return; + } + + $this->emailTemplate->expects($this->once()) ->method('setSubject') ->with('Invitation: Fellowship meeting'); - $mailMessage->expects($this->once()) + $this->mailMessage->expects($this->once()) ->method('setTo') ->with([$recipient => null]); - $mailMessage->expects($this->once()) + $this->mailMessage->expects($this->once()) ->method('setReplyTo') ->with(['gandalf@wiz.ard' => null]); + $this->mailer + ->expects($this->once()) + ->method('send'); - $plugin->schedule($message); - $this->assertEquals('1.1', $message->getScheduleStatus()); - } - - public function dataIncludeResponseButtons() { - return [ - // dav.invitation_link_recipients, recipient, $has_buttons - [ true, 'joe@internal.com', true], - [ 'joe@internal.com', 'joe@internal.com', true], - [ 'internal.com', 'joe@internal.com', true], - [ ['pete@otherinternal.com', 'internal.com'], 'joe@internal.com', true], - [ false, 'joe@internal.com', false], - [ 'internal.com', 'joe@external.com', false], - [ ['jane@otherinternal.com', 'internal.com'], 'joe@otherinternal.com', false], - ]; + if ($expectButtons) { + $this->queryBuilder->expects($this->at(0)) + ->method('insert') + ->with('calendar_invitations') + ->will($this->returnValue($this->queryBuilder)); + $this->queryBuilder->expects($this->at(8)) + ->method('values') + ->will($this->returnValue($this->queryBuilder)); + $this->queryBuilder->expects($this->at(9)) + ->method('execute'); + } + else { + $this->queryBuilder->expects($this->never()) + ->method('insert') + ->with('calendar_invitations'); + } } } From a16c91952d3968f89b5f4119f25bc2d2119dc1cf Mon Sep 17 00:00:00 2001 From: brad2014 Date: Wed, 17 Jul 2019 16:47:15 -0700 Subject: [PATCH 7/7] Move dav.invitation_link_recipients from getSystemValue to getAppValue Per @georgehrke change request for PR #12392, instead of setting dav.invitation_link_recipients in the system config.php file, we set it in the database table oc_appconfig. Furthermore, the value of the config variable is always a string: 'yes' to include links in imip mail, 'no' to exclude them, or a comma-separated list of email addresses and/or domains for which they should be included. If not specified in oc_appconfig, the default is 'yes'. Signed-off-by: brad2014 --- apps/dav/lib/CalDAV/Schedule/IMipPlugin.php | 24 +++++++-------- .../unit/CalDAV/Schedule/IMipPluginTest.php | 30 +++++++++---------- config/config.sample.php | 27 ----------------- 3 files changed, 26 insertions(+), 55 deletions(-) diff --git a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php index 7035d3c780f5e..56b3ab04ddc59 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -249,28 +249,26 @@ public function schedule(Message $iTipMessage) { ** nextcloud server, to recipients who can access the nextcloud server via ** their internet/intranet. Issue #12156 ** + ** The app setting is stored in the appconfig database table. + ** ** For nextcloud servers accessible to the public internet, the default - ** "dav.invitation_link_recipients" value "true" (all recipients) is appropriate. + ** "invitation_link_recipients" value "yes" (all recipients) is appropriate. ** ** When the nextcloud server is restricted behind a firewall, accessible ** only via an internal network or via vpn, you can set "dav.invitation_link_recipients" - ** to the email address or email domain, or array of addresses or domains, + ** to the email address or email domain, or comma separated list of addresses or domains, ** of recipients who can access the server. ** - ** To deliver URL's always, set invitation_link_recipients to boolean "true". - ** To suppress URL's entirely, set invitation_link_recipients to boolean "false". + ** To always deliver URLs, set invitation_link_recipients to "yes". + ** To suppress URLs entirely, set invitation_link_recipients to boolean "no". */ $recipientDomain = substr(strrchr($recipient, "@"), 1); - $invitationLinkRecipients = $this->config->getSystemValue('dav.invitation_link_recipients', true); - if (is_array($invitationLinkRecipients)) { - $invitationLinkRecipients = array_map('strtolower', $invitationLinkRecipients); // for case insensitive in_array - } - if ($invitationLinkRecipients === true - || (is_string($invitationLinkRecipients) && strcasecmp($recipient, $invitationLinkRecipients) === 0) - || (is_string($invitationLinkRecipients) && strcasecmp($recipientDomain, $invitationLinkRecipients) === 0) - || (is_array($invitationLinkRecipients) && in_array(strtolower($recipient), $invitationLinkRecipients)) - || (is_array($invitationLinkRecipients) && in_array(strtolower($recipientDomain), $invitationLinkRecipients))) { + $invitationLinkRecipients = explode(',', preg_replace('/\s+/', '', strtolower($this->config->getAppValue('dav', 'invitation_link_recipients', 'yes')))); + + if (strcmp('yes', $invitationLinkRecipients[0]) === 0 + || in_array(strtolower($recipient), $invitationLinkRecipients) + || in_array(strtolower($recipientDomain), $invitationLinkRecipients)) { $this->addResponseButtons($template, $l10n, $iTipMessage, $lastOccurrence); } } diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php index 84da1d2727c0f..967f3a514816f 100644 --- a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php +++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php @@ -96,9 +96,9 @@ public function setUp() { public function testDelivery() { $this->config - ->method('getSystemValue') - ->with('dav.invitation_link_recipients', true) - ->willReturn(true); + ->method('getAppValue') + ->with('dav', 'invitation_link_recipients', 'yes') + ->willReturn('yes'); $message = $this->_testMessage(); $this->_expectSend(); @@ -108,9 +108,9 @@ public function testDelivery() { public function testFailedDelivery() { $this->config - ->method('getSystemValue') - ->with('dav.invitation_link_recipients', true) - ->willReturn(true); + ->method('getAppValue') + ->with('dav', 'invitation_link_recipients', 'yes') + ->willReturn('yes'); $message = $this->_testMessage(); $this->mailer @@ -127,9 +127,9 @@ public function testFailedDelivery() { public function testNoMessageSendForPastEvents($veventParams, $expectsMail) { $this->config - ->method('getSystemValue') - ->with('dav.invitation_link_recipients', true) - ->willReturn(true); + ->method('getAppValue') + ->with('dav', 'invitation_link_recipients', 'yes') + ->willReturn('yes'); $message = $this->_testMessage( $veventParams ); @@ -167,8 +167,8 @@ public function testIncludeResponseButtons( $config_setting, $recipient, $has_bu $this->_expectSend($recipient, true, $has_buttons); $this->config - ->method('getSystemValue') - ->with('dav.invitation_link_recipients', true) + ->method('getAppValue') + ->with('dav', 'invitation_link_recipients', 'yes') ->willReturn($config_setting); $this->plugin->schedule($message); @@ -178,13 +178,13 @@ public function testIncludeResponseButtons( $config_setting, $recipient, $has_bu public function dataIncludeResponseButtons() { return [ // dav.invitation_link_recipients, recipient, $has_buttons - [ true, 'joe@internal.com', true], + [ 'yes', 'joe@internal.com', true], [ 'joe@internal.com', 'joe@internal.com', true], [ 'internal.com', 'joe@internal.com', true], - [ ['pete@otherinternal.com', 'internal.com'], 'joe@internal.com', true], - [ false, 'joe@internal.com', false], + [ 'pete@otherinternal.com,internal.com', 'joe@internal.com', true], + [ 'no', 'joe@internal.com', false], [ 'internal.com', 'joe@external.com', false], - [ ['jane@otherinternal.com', 'internal.com'], 'joe@otherinternal.com', false], + [ 'jane@otherinternal.com,internal.com', 'joe@otherinternal.com', false], ]; } diff --git a/config/config.sample.php b/config/config.sample.php index 869c24590b3b9..f939fc371b70f 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -1688,33 +1688,6 @@ '/^Microsoft-WebDAV-MiniRedir/', // Windows webdav drive ), -/** -* The caldav server sends invitation emails to invitees, attaching the ICS -* file for the invitation. It also may include, in the body of the e-mail, -* invitation accept/reject web links referencing URL's that point to the nextcloud server. -* -* Although any recipient can read and reply to the ICS file via the iMip protocol, -* we must only present the web links to recipients who can access the nextcloud -* web server via their internet/intranet. -* -* When your nextcloud server is restricted behind a firewall, accessible -* only via an internal network or via vpn, you can set "dav.invitation_link_recipients" -* to the email address or email domain, or array of addresses or domains, -* of recipients who can access the server. Only those recipients will get web links. External -* users can accept/reject invitations by emailing back ICS files containing appropriate -* messages, using the iMip protocol. Many mail clients support this functionality. -* -* To suppress iMip web links entirely, set dav.invitation_link_recipients to false. -* To deliver iMip web links always, set dav.invitation_link_recipients to true. -* -* Examples: -* 'dav.invitation_link_recipients' => 'internal.example.com', -* 'dav.invitation_link_recipients' => array( 'internal.example.com', 'pat@roadwarrior.example.com' ), -* 'dav.invitation_link_recipients' => false, -* -*/ -'dav.invitation_link_recipients' => true, // always include accept/reject server links in iMip emails - /** * By default there is on public pages a link shown that allows users to * learn about the "simple sign up" - see https://nextcloud.com/signup/