From 31a25dc6b0545eb9bcb215990c8a71f1792f61f8 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 3ff3ed0c56..4375c081d5 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -144,11 +144,11 @@ class IMipPlugin extends SabreIMipPlugin { $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 @@ class IMipPlugin extends SabreIMipPlugin { $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 @@ class IMipPlugin extends SabreIMipPlugin { $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 9c3cc47099..5f1eee4e94 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -1696,6 +1696,33 @@ $CONFIG = array( '/^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 15400dd18f5346cdad749aef3c4617088b52c922 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 5f1eee4e94..d5f4bb5f43 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -1721,7 +1721,7 @@ $CONFIG = array( * '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 6421e30b2ccad91bb708d51609d7dd72cbfc0ebe 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 4375c081d5..987e6c86f5 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -242,7 +242,7 @@ class IMipPlugin extends SabreIMipPlugin { // 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 @@ class IMipPlugin extends SabreIMipPlugin { 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 @@ class IMipPlugin extends SabreIMipPlugin { $moreOptionsURL, $l10n->t('More options …') ]); $text = $l10n->t('More options at %s', [$moreOptionsURL]); - + $template->addBodyText($html, $text); } From 79d20e47581b0cae9809b025c7d2b922c0b29dea 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 987e6c86f5..7035d3c780 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -144,11 +144,11 @@ class IMipPlugin extends SabreIMipPlugin { $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 1dbda2604b1a9971739d72a3542a24c29c316bf6 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 c95b32041e..0ba670879f 100644 --- a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php +++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php @@ -67,6 +67,9 @@ class IMipPluginTest extends TestCase { $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 @@ class IMipPluginTest extends TestCase { '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 @@ class IMipPluginTest extends TestCase { $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 @@ class IMipPluginTest extends TestCase { '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 @@ class IMipPluginTest extends TestCase { $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 @@ class IMipPluginTest extends TestCase { '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 @@ class IMipPluginTest extends TestCase { [['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 1a2923996059aadbcd69000a85d51304ec9a9f8e 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 | 440 +++++------------- 1 file changed, 123 insertions(+), 317 deletions(-) diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php index 0ba670879f..84da1d2727 100644 --- a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php +++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php @@ -48,179 +48,76 @@ use Test\TestCase; 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 */ - $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')); - $random->expects($this->once()) - ->method('generate') + $urlGenerator = $this->createMock(IURLGenerator::class); + + $this->queryBuilder = $this->createMock(IQueryBuilder::class); + $db = $this->createMock(IDBConnection::class); + $db->method('getQueryBuilder') + ->with() + ->will($this->returnValue($this->queryBuilder)); + + $random = $this->createMock(ISecureRandom::class); + $random->method('generate') ->with(60, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') ->will($this->returnValue('random_token')); - $queryBuilder = $this->createMock(IQueryBuilder::class); + $defaults = $this->createMock(Defaults::class); + $defaults->method('getName') + ->will($this->returnValue('Instance Name 123')); - $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'); + $this->plugin = new IMipPlugin($this->config, $this->mailer, $logger, $this->timeFactory, $l10nFactory, $urlGenerator, $defaults, $random, $db, 'user123'); + } - $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 - ]); + public function testDelivery() { + $this->config + ->method('getSystemValue') + ->with('dav.invitation_link_recipients', true) + ->willReturn(true); - $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->_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 @@ class IMipPluginTest extends TestCase { * @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')); + $message = $this->_testMessage( $veventParams ); - $queryBuilder = $this->createMock(IQueryBuilder::class); + $this->_expectSend('frodo@hobb.it', $expectsMail, $expectsMail); - $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', 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'; - - $plugin->schedule($message); + $this->plugin->schedule($message); if ($expectsMail) { $this->assertEquals('1.1', $message->getScheduleStatus()); @@ -331,100 +163,15 @@ class IMipPluginTest extends TestCase { * @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); - - 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->plugin->schedule($message); $this->assertEquals('1.1', $message->getScheduleStatus()); } @@ -440,4 +187,63 @@ class IMipPluginTest extends TestCase { [ ['jane@otherinternal.com', 'internal.com'], 'joe@otherinternal.com', false], ]; } + + private function _testMessage($attrs = [], $recipient = 'frodo@hobb.it' ) { + $message = new Message(); + $message->method = 'REQUEST'; + $message->message = new VCalendar(); + $message->message->add('VEVENT', array_merge([ + 'UID' => 'uid-1234', + 'SEQUENCE' => 0, + 'SUMMARY' => 'Fellowship meeting', + '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; + } + + + 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'); + $this->mailMessage->expects($this->once()) + ->method('setTo') + ->with([$recipient => null]); + $this->mailMessage->expects($this->once()) + ->method('setReplyTo') + ->with(['gandalf@wiz.ard' => null]); + $this->mailer + ->expects($this->once()) + ->method('send'); + + 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 8d8bcea1d8cb7328e898654874348a64afc773e4 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 7035d3c780..56b3ab04dd 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -249,28 +249,26 @@ class IMipPlugin extends SabreIMipPlugin { ** 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 84da1d2727..967f3a5148 100644 --- a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php +++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php @@ -96,9 +96,9 @@ class IMipPluginTest extends TestCase { 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 @@ class IMipPluginTest extends TestCase { 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 @@ class IMipPluginTest extends TestCase { 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 @@ class IMipPluginTest extends TestCase { $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 @@ class IMipPluginTest extends TestCase { 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 d5f4bb5f43..9c3cc47099 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -1696,33 +1696,6 @@ $CONFIG = array( '/^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/