aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastianKrupinski <krupinskis05@gmail.com>2025-05-12 14:43:35 -0400
committerSebastianKrupinski <krupinskis05@gmail.com>2025-05-12 15:44:07 -0400
commitebd80bc142f5f26032a88e461870dcaf14e18263 (patch)
tree92708211d54f7a8f4f0410f435737c7b9d7dbc3a
parent0eb530ecdedb3cd11e0eb3cb8c3de466ca3d74a3 (diff)
downloadnextcloud-server-fix/noid-check-for-properties-before-processing.tar.gz
nextcloud-server-fix/noid-check-for-properties-before-processing.zip
fix: check if properties exist before using themfix/noid-check-for-properties-before-processing
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
-rw-r--r--lib/private/Calendar/Manager.php137
-rw-r--r--tests/lib/Calendar/ManagerTest.php980
2 files changed, 899 insertions, 218 deletions
diff --git a/lib/private/Calendar/Manager.php b/lib/private/Calendar/Manager.php
index e86e0e1d410..21370e74d54 100644
--- a/lib/private/Calendar/Manager.php
+++ b/lib/private/Calendar/Manager.php
@@ -33,6 +33,7 @@ use Sabre\HTTP\Response;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\Component\VEvent;
use Sabre\VObject\Component\VFreeBusy;
+use Sabre\VObject\ParseException;
use Sabre\VObject\Property\VCard\DateTime;
use Sabre\VObject\Reader;
use Throwable;
@@ -235,9 +236,14 @@ class Manager implements IManager {
$this->logger->warning('iMip message could not be processed because user has no calendars');
return false;
}
-
- /** @var VCalendar $vObject|null */
- $calendarObject = Reader::read($calendarData);
+
+ try {
+ /** @var VCalendar $vObject|null */
+ $calendarObject = Reader::read($calendarData);
+ } catch (ParseException $e) {
+ $this->logger->error('iMip message could not be processed because an error occurred while parsing the iMip message', ['exception' => $e]);
+ return false;
+ }
if (!isset($calendarObject->METHOD) || $calendarObject->METHOD->getValue() !== 'REQUEST') {
$this->logger->warning('iMip message contains an incorrect or invalid method');
@@ -249,6 +255,7 @@ class Manager implements IManager {
return false;
}
+ /** @var VEvent|null $vEvent */
$eventObject = $calendarObject->VEVENT;
if (!isset($eventObject->UID)) {
@@ -256,6 +263,11 @@ class Manager implements IManager {
return false;
}
+ if (!isset($eventObject->ORGANIZER)) {
+ $this->logger->warning('iMip message event dose not contains an organizer');
+ return false;
+ }
+
if (!isset($eventObject->ATTENDEE)) {
$this->logger->warning('iMip message event dose not contains any attendees');
return false;
@@ -296,7 +308,7 @@ class Manager implements IManager {
}
}
- $this->logger->warning('iMip message event could not be processed because the no corresponding event was found in any calendar');
+ $this->logger->warning('iMip message event could not be processed because no corresponding event was found in any calendar');
return false;
}
@@ -309,23 +321,51 @@ class Manager implements IManager {
string $recipient,
string $calendarData,
): bool {
- /** @var VCalendar $vObject|null */
- $vObject = Reader::read($calendarData);
+
+ $calendars = $this->getCalendarsForPrincipal($principalUri);
+ if (empty($calendars)) {
+ $this->logger->warning('iMip message could not be processed because user has no calendars');
+ return false;
+ }
+
+ try {
+ /** @var VCalendar $vObject|null */
+ $vObject = Reader::read($calendarData);
+ } catch (ParseException $e) {
+ $this->logger->error('iMip message could not be processed because an error occurred while parsing the iMip message', ['exception' => $e]);
+ return false;
+ }
if ($vObject === null) {
+ $this->logger->warning('iMip message contains an invalid calendar object');
+ return false;
+ }
+
+ if (!isset($vObject->METHOD) || $vObject->METHOD->getValue() !== 'REPLY') {
+ $this->logger->warning('iMip message contains an incorrect or invalid method');
+ return false;
+ }
+
+ if (!isset($vObject->VEVENT)) {
+ $this->logger->warning('iMip message contains no event');
return false;
}
/** @var VEvent|null $vEvent */
- $vEvent = $vObject->{'VEVENT'};
+ $vEvent = $vObject->VEVENT;
+
+ if (!isset($vEvent->UID)) {
+ $this->logger->warning('iMip message event dose not contains a UID');
+ return false;
+ }
- if ($vEvent === null) {
+ if (!isset($vEvent->ORGANIZER)) {
+ $this->logger->warning('iMip message event dose not contains an organizer');
return false;
}
- // First, we check if the correct method is passed to us
- if (strcasecmp('REPLY', $vObject->{'METHOD'}->getValue()) !== 0) {
- $this->logger->warning('Wrong method provided for processing');
+ if (!isset($vEvent->ATTENDEE)) {
+ $this->logger->warning('iMip message event dose not contains any attendees');
return false;
}
@@ -333,7 +373,7 @@ class Manager implements IManager {
$organizer = substr($vEvent->{'ORGANIZER'}->getValue(), 7);
if (strcasecmp($recipient, $organizer) !== 0) {
- $this->logger->warning('Recipient and ORGANIZER must be identical');
+ $this->logger->warning('iMip message event could not be processed because recipient and ORGANIZER must be identical');
return false;
}
@@ -341,13 +381,7 @@ class Manager implements IManager {
/** @var DateTime $eventTime */
$eventTime = $vEvent->{'DTSTART'};
if ($eventTime->getDateTime()->getTimeStamp() < $this->timeFactory->getTime()) { // this might cause issues with recurrences
- $this->logger->warning('Only events in the future are processed');
- return false;
- }
-
- $calendars = $this->getCalendarsForPrincipal($principalUri);
- if (empty($calendars)) {
- $this->logger->warning('Could not find any calendars for principal ' . $principalUri);
+ $this->logger->warning('iMip message event could not be processed because the event is in the past');
return false;
}
@@ -369,14 +403,14 @@ class Manager implements IManager {
}
if (empty($found)) {
- $this->logger->info('Event not found in any calendar for principal ' . $principalUri . 'and UID' . $vEvent->{'UID'}->getValue());
+ $this->logger->warning('iMip message event could not be processed because no corresponding event was found in any calendar ' . $principalUri . 'and UID' . $vEvent->{'UID'}->getValue());
return false;
}
try {
$found->handleIMipMessage($name, $calendarData); // sabre will handle the scheduling behind the scenes
} catch (CalendarException $e) {
- $this->logger->error('Could not update calendar for iMIP processing', ['exception' => $e]);
+ $this->logger->error('An error occurred while processing the iMip message event', ['exception' => $e]);
return false;
}
return true;
@@ -393,29 +427,57 @@ class Manager implements IManager {
string $recipient,
string $calendarData,
): bool {
- /** @var VCalendar $vObject|null */
- $vObject = Reader::read($calendarData);
+
+ $calendars = $this->getCalendarsForPrincipal($principalUri);
+ if (empty($calendars)) {
+ $this->logger->warning('iMip message could not be processed because user has no calendars');
+ return false;
+ }
+
+ try {
+ /** @var VCalendar $vObject|null */
+ $vObject = Reader::read($calendarData);
+ } catch (ParseException $e) {
+ $this->logger->error('iMip message could not be processed because an error occurred while parsing the iMip message', ['exception' => $e]);
+ return false;
+ }
if ($vObject === null) {
+ $this->logger->warning('iMip message contains an invalid calendar object');
+ return false;
+ }
+
+ if (!isset($vObject->METHOD) || $vObject->METHOD->getValue() !== 'CANCEL') {
+ $this->logger->warning('iMip message contains an incorrect or invalid method');
+ return false;
+ }
+
+ if (!isset($vObject->VEVENT)) {
+ $this->logger->warning('iMip message contains no event');
return false;
}
/** @var VEvent|null $vEvent */
$vEvent = $vObject->{'VEVENT'};
- if ($vEvent === null) {
+ if (!isset($vEvent->UID)) {
+ $this->logger->warning('iMip message event dose not contains a UID');
+ return false;
+ }
+
+ if (!isset($vEvent->ORGANIZER)) {
+ $this->logger->warning('iMip message event dose not contains an organizer');
return false;
}
- // First, we check if the correct method is passed to us
- if (strcasecmp('CANCEL', $vObject->{'METHOD'}->getValue()) !== 0) {
- $this->logger->warning('Wrong method provided for processing');
+ if (!isset($vEvent->ATTENDEE)) {
+ $this->logger->warning('iMip message event dose not contains any attendees');
return false;
}
$attendee = substr($vEvent->{'ATTENDEE'}->getValue(), 7);
if (strcasecmp($recipient, $attendee) !== 0) {
- $this->logger->warning('Recipient must be an ATTENDEE of this event');
+ $this->logger->warning('iMip message event could not be processed because recipient must be an ATTENDEE of this event');
return false;
}
@@ -426,7 +488,7 @@ class Manager implements IManager {
$organizer = substr($vEvent->{'ORGANIZER'}->getValue(), 7);
$isNotOrganizer = ($replyTo !== null) ? (strcasecmp($sender, $organizer) !== 0 && strcasecmp($replyTo, $organizer) !== 0) : (strcasecmp($sender, $organizer) !== 0);
if ($isNotOrganizer) {
- $this->logger->warning('Sender must be the ORGANIZER of this event');
+ $this->logger->warning('iMip message event could not be processed because sender must be the ORGANIZER of this event');
return false;
}
@@ -434,14 +496,7 @@ class Manager implements IManager {
/** @var DateTime $eventTime */
$eventTime = $vEvent->{'DTSTART'};
if ($eventTime->getDateTime()->getTimeStamp() < $this->timeFactory->getTime()) { // this might cause issues with recurrences
- $this->logger->warning('Only events in the future are processed');
- return false;
- }
-
- // Check if we have a calendar to work with
- $calendars = $this->getCalendarsForPrincipal($principalUri);
- if (empty($calendars)) {
- $this->logger->warning('Could not find any calendars for principal ' . $principalUri);
+ $this->logger->warning('iMip message event could not be processed because the event is in the past');
return false;
}
@@ -463,17 +518,15 @@ class Manager implements IManager {
}
if (empty($found)) {
- $this->logger->info('Event not found in any calendar for principal ' . $principalUri . 'and UID' . $vEvent->{'UID'}->getValue());
- // this is a safe operation
- // we can ignore events that have been cancelled but were not in the calendar anyway
- return true;
+ $this->logger->warning('iMip message event could not be processed because no corresponding event was found in any calendar ' . $principalUri . 'and UID' . $vEvent->{'UID'}->getValue());
+ return false;
}
try {
$found->handleIMipMessage($name, $calendarData); // sabre will handle the scheduling behind the scenes
return true;
} catch (CalendarException $e) {
- $this->logger->error('Could not update calendar for iMIP processing', ['exception' => $e]);
+ $this->logger->error('An error occurred while processing the iMip message event', ['exception' => $e]);
return false;
}
}
diff --git a/tests/lib/Calendar/ManagerTest.php b/tests/lib/Calendar/ManagerTest.php
index 6c01cd90811..cecebcfc4cf 100644
--- a/tests/lib/Calendar/ManagerTest.php
+++ b/tests/lib/Calendar/ManagerTest.php
@@ -27,8 +27,6 @@ use Psr\Log\LoggerInterface;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
use Sabre\VObject\Component\VCalendar;
-use Sabre\VObject\Document;
-use Sabre\VObject\Reader;
use Test\TestCase;
/*
@@ -60,6 +58,8 @@ class ManagerTest extends TestCase {
private ServerFactory&MockObject $serverFactory;
private VCalendar $vCalendar1a;
+ private VCalendar $vCalendar2a;
+ private VCalendar $vCalendar3a;
protected function setUp(): void {
parent::setUp();
@@ -90,6 +90,9 @@ class ManagerTest extends TestCase {
$vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
$vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
$vEvent->add('SUMMARY', 'Test Event');
+ $vEvent->add('SEQUENCE', 3);
+ $vEvent->add('STATUS', 'CONFIRMED');
+ $vEvent->add('TRANSP', 'OPAQUE');
$vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
$vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
'CN' => 'Attendee One',
@@ -98,6 +101,45 @@ class ManagerTest extends TestCase {
'ROLE' => 'REQ-PARTICIPANT',
'RSVP' => 'TRUE'
]);
+
+ // construct calendar with a event for reply
+ $this->vCalendar2a = new VCalendar();
+ /** @var VEvent $vEvent */
+ $vEvent = $this->vCalendar2a->add('VEVENT', []);
+ $vEvent->UID->setValue('dcc733bf-b2b2-41f2-a8cf-550ae4b67aff');
+ $vEvent->add('DTSTART', '20210820');
+ $vEvent->add('DTEND', '20220821');
+ $vEvent->add('SUMMARY', 'berry basket');
+ $vEvent->add('SEQUENCE', 3);
+ $vEvent->add('STATUS', 'CONFIRMED');
+ $vEvent->add('TRANSP', 'OPAQUE');
+ $vEvent->add('ORGANIZER', 'mailto:linus@stardew-tent-living.com', ['CN' => 'admin']);
+ $vEvent->add('ATTENDEE', 'mailto:pierre@general-store.com', [
+ 'CN' => 'pierre@general-store.com',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'PARTSTAT' => 'ACCEPTED',
+ ]);
+
+ // construct calendar with a event for reply
+ $this->vCalendar3a = new VCalendar();
+ /** @var VEvent $vEvent */
+ $vEvent = $this->vCalendar3a->add('VEVENT', []);
+ $vEvent->UID->setValue('dcc733bf-b2b2-41f2-a8cf-550ae4b67aff');
+ $vEvent->add('DTSTART', '20210820');
+ $vEvent->add('DTEND', '20220821');
+ $vEvent->add('SUMMARY', 'berry basket');
+ $vEvent->add('SEQUENCE', 3);
+ $vEvent->add('STATUS', 'CANCELLED');
+ $vEvent->add('TRANSP', 'OPAQUE');
+ $vEvent->add('ORGANIZER', 'mailto:linus@stardew-tent-living.com', ['CN' => 'admin']);
+ $vEvent->add('ATTENDEE', 'mailto:pierre@general-store.com', [
+ 'CN' => 'pierre@general-store.com',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'PARTSTAT' => 'ACCEPTED',
+ ]);
+
}
/**
@@ -300,8 +342,42 @@ class ManagerTest extends TestCase {
$recipient = 'attendee1@testing.com';
$calendar = $this->vCalendar1a;
$calendar->add('METHOD', 'REQUEST');
- // test method
+ // Act
$result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipRequestWithInvalidData(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('error')
+ ->with('iMip message could not be processed because an error occurred while parsing the iMip message');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, 'Invalid data');
+ // Assert
$this->assertFalse($result);
}
@@ -333,8 +409,9 @@ class ManagerTest extends TestCase {
$sender = 'organizer@testing.com';
$recipient = 'attendee1@testing.com';
$calendar = $this->vCalendar1a;
- // test method
+ // Act
$result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
@@ -367,8 +444,9 @@ class ManagerTest extends TestCase {
$recipient = 'attendee1@testing.com';
$calendar = $this->vCalendar1a;
$calendar->add('METHOD', 'CANCEL');
- // test method
+ // Act
$result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
@@ -402,8 +480,9 @@ class ManagerTest extends TestCase {
$calendar = $this->vCalendar1a;
$calendar->add('METHOD', 'REQUEST');
$calendar->remove('VEVENT');
- // test method
+ // Act
$result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
@@ -437,8 +516,45 @@ class ManagerTest extends TestCase {
$calendar = $this->vCalendar1a;
$calendar->add('METHOD', 'REQUEST');
$calendar->VEVENT->remove('UID');
- // test method
+ // Act
+ $result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipRequestWithNoOrganizer(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains an organizer');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $calendar = $this->vCalendar1a;
+ $calendar->add('METHOD', 'REQUEST');
+ $calendar->VEVENT->remove('ORGANIZER');
+ // Act
$result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
@@ -472,8 +588,9 @@ class ManagerTest extends TestCase {
$calendar = $this->vCalendar1a;
$calendar->add('METHOD', 'REQUEST');
$calendar->VEVENT->remove('ATTENDEE');
- // test method
+ // Act
$result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
@@ -506,8 +623,9 @@ class ManagerTest extends TestCase {
$recipient = 'attendee2@testing.com';
$calendar = $this->vCalendar1a;
$calendar->add('METHOD', 'REQUEST');
- // test method
+ // Act
$result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
@@ -545,15 +663,16 @@ class ManagerTest extends TestCase {
->willReturn([$userCalendar]);
// construct logger returns
$this->logger->expects(self::once())->method('warning')
- ->with('iMip message event could not be processed because the no corresponding event was found in any calendar');
+ ->with('iMip message event could not be processed because no corresponding event was found in any calendar');
// construct parameters
$principalUri = 'principals/user/attendee1';
$sender = 'organizer@testing.com';
$recipient = 'attendee1@testing.com';
$calendar = $this->vCalendar1a;
$calendar->add('METHOD', 'REQUEST');
- // test method
+ // Act
$result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
@@ -599,62 +718,152 @@ class ManagerTest extends TestCase {
$userCalendar->expects(self::once())
->method('handleIMipMessage')
->with('', $calendar->serialize());
- // test method
+ // Act
$result = $manager->handleIMipRequest($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertTrue($result);
}
- public function testHandleImipReplyWrongMethod(): void {
+ public function testHandleImipReplyWithNoCalendars(): void {
+ // construct calendar manager returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message could not be processed because user has no calendars');
+ // construct parameters
$principalUri = 'principals/user/linus';
$sender = 'pierre@general-store.com';
$recipient = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
- $calendarData->METHOD = 'REQUEST';
-
- $this->logger->expects(self::once())
- ->method('warning');
- $this->time->expects(self::never())
- ->method('getTime');
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'REPLY');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ public function testHandleImipReplyWithInvalidData(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('error')
+ ->with('iMip message could not be processed because an error occurred while parsing the iMip message');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, 'Invalid data');
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipReplyOrganizerNotRecipient(): void {
+ public function testHandleImipReplyWithNoMethod(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains an incorrect or invalid method');
+ // construct parameters
$principalUri = 'principals/user/linus';
- $recipient = 'pierre@general-store.com';
- $sender = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
-
- $this->logger->expects(self::once())
- ->method('warning');
- $this->time->expects(self::never())
- ->method('getTime');
-
- $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $calendar = $this->vCalendar2a;
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipReplyDateInThePast(): void {
+ public function testHandleImipReplyWithInvalidMethod(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains an incorrect or invalid method');
+ // construct parameters
$principalUri = 'principals/user/linus';
$sender = 'pierre@general-store.com';
$recipient = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
- $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past
-
- $this->time->expects(self::once())
- ->method('getTime')
- ->willReturn(time());
-
- $this->logger->expects(self::once())
- ->method('warning');
-
- $result = $this->manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'UNKNOWN');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipReplyNoCalendars(): void {
- /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
+ public function testHandleImipReplyWithNoEvent(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
$manager = $this->getMockBuilder(Manager::class)
->setConstructorArgs([
$this->coordinator,
@@ -665,30 +874,68 @@ class ManagerTest extends TestCase {
$this->userManager,
$this->serverFactory,
])
- ->setMethods([
- 'getCalendarsForPrincipal'
- ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains no event');
+ // construct parameters
$principalUri = 'principals/user/linus';
$sender = 'pierre@general-store.com';
$recipient = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'REPLY');
+ $calendar->remove('VEVENT');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $this->time->expects(self::once())
- ->method('getTime')
- ->willReturn(1628374233);
+ public function testHandleImipReplyWithNoUid(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
$manager->expects(self::once())
->method('getCalendarsForPrincipal')
- ->willReturn([]);
- $this->logger->expects(self::once())
- ->method('warning');
-
- $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains a UID');
+ // construct parameters
+ $principalUri = 'principals/user/linus';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'REPLY');
+ $calendar->VEVENT->remove('UID');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipReplyEventNotFound(): void {
- /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
+ public function testHandleImipReplyWithNoOrganizer(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
$manager = $this->getMockBuilder(Manager::class)
->setConstructorArgs([
$this->coordinator,
@@ -699,31 +946,141 @@ class ManagerTest extends TestCase {
$this->userManager,
$this->serverFactory,
])
- ->setMethods([
- 'getCalendarsForPrincipal'
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains an organizer');
+ // construct parameters
+ $principalUri = 'principals/user/linus';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'REPLY');
+ $calendar->VEVENT->remove('ORGANIZER');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipReplyWithNoAttendee(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
])
+ ->onlyMethods(['getCalendarsForPrincipal'])
->getMock();
- $calendar = $this->createMock(ITestCalendar::class);
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains any attendees');
+ // construct parameters
$principalUri = 'principals/user/linus';
$sender = 'pierre@general-store.com';
$recipient = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
+ $calendar = $this->vCalendar2a;
+ $calendar->add('METHOD', 'REPLY');
+ $calendar->VEVENT->remove('ATTENDEE');
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $this->time->expects(self::once())
- ->method('getTime')
- ->willReturn(1628374233);
+ public function testHandleImipReplyDateInThePast(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
$manager->expects(self::once())
->method('getCalendarsForPrincipal')
- ->willReturn([$calendar]);
- $calendar->expects(self::once())
+ ->willReturn([$userCalendar]);
+ // construct logger and time returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event could not be processed because the event is in the past');
+ $this->time->expects(self::once())
+ ->method('getTime')
+ ->willReturn(time());
+ // construct parameters
+ $principalUri = 'principals/user/linus';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $calendarData = clone $this->vCalendar2a;
+ $calendarData->add('METHOD', 'REPLY');
+ $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past
+ // Act
+ $result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipReplyEventNotFound(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ $userCalendar->expects(self::once())
->method('search')
->willReturn([]);
- $this->logger->expects(self::once())
- ->method('info');
- $calendar->expects(self::never())
- ->method('handleIMipMessage');
-
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct time returns
+ $this->time->expects(self::once())
+ ->method('getTime')
+ ->willReturn(1628374233);
+ // construct parameters
+ $principalUri = 'principals/user/linus';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $calendarData = clone $this->vCalendar2a;
+ $calendarData->add('METHOD', 'REPLY');
+ // construct logger return
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event could not be processed because no corresponding event was found in any calendar ' . $principalUri . 'and UID' . $calendarData->VEVENT->UID->getValue());
+ // Act
$result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ // Assert
$this->assertFalse($result);
}
@@ -747,7 +1104,8 @@ class ManagerTest extends TestCase {
$principalUri = 'principals/user/linus';
$sender = 'pierre@general-store.com';
$recipient = 'linus@stardew-tent-living.com';
- $calendarData = $this->getVCalendarReply();
+ $calendarData = clone $this->vCalendar2a;
+ $calendarData->add('METHOD', 'REPLY');
$this->time->expects(self::once())
->method('getTime')
@@ -761,64 +1119,305 @@ class ManagerTest extends TestCase {
$calendar->expects(self::once())
->method('handleIMipMessage')
->with('testname.ics', $calendarData->serialize());
-
+ // Act
$result = $manager->handleIMipReply($principalUri, $sender, $recipient, $calendarData->serialize());
+ // Assert
$this->assertTrue($result);
}
- public function testHandleImipCancelWrongMethod(): void {
+ public function testHandleImipCancelWithNoCalendars(): void {
+ // construct calendar manager returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message could not be processed because user has no calendars');
+ // construct parameters
$principalUri = 'principals/user/pierre';
$sender = 'linus@stardew-tent-living.com';
$recipient = 'pierre@general-store.com';
$replyTo = null;
- $calendarData = $this->getVCalendarCancel();
- $calendarData->METHOD = 'REQUEST';
-
- $this->logger->expects(self::once())
- ->method('warning');
- $this->time->expects(self::never())
- ->method('getTime');
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'CANCEL');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ public function testHandleImipCancelWithInvalidData(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('error')
+ ->with('iMip message could not be processed because an error occurred while parsing the iMip message');
+ // construct parameters
+ $principalUri = 'principals/user/attendee1';
+ $sender = 'organizer@testing.com';
+ $recipient = 'attendee1@testing.com';
+ $replyTo = null;
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, 'Invalid data');
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipCancelAttendeeNotRecipient(): void {
- $principalUri = '/user/admin';
+
+ public function testHandleImipCancelWithNoMethod(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains an incorrect or invalid method');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
$sender = 'linus@stardew-tent-living.com';
- $recipient = 'leah@general-store.com';
+ $recipient = 'pierre@general-store.com';
$replyTo = null;
- $calendarData = $this->getVCalendarCancel();
+ $calendar = $this->vCalendar3a;
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $this->logger->expects(self::once())
- ->method('warning');
- $this->time->expects(self::never())
- ->method('getTime');
+ public function testHandleImipCancelWithInvalidMethod(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains an incorrect or invalid method');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'linus@stardew-tent-living.com';
+ $recipient = 'pierre@general-store.com';
+ $replyTo = null;
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'UNKNOWN');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ public function testHandleImipCancelWithNoEvent(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message contains no event');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'linus@stardew-tent-living.com';
+ $recipient = 'pierre@general-store.com';
+ $replyTo = null;
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'CANCEL');
+ $calendar->remove('VEVENT');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipCancelDateInThePast(): void {
+ public function testHandleImipCancelWithNoUid(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains a UID');
+ // construct parameters
$principalUri = 'principals/user/pierre';
$sender = 'linus@stardew-tent-living.com';
$recipient = 'pierre@general-store.com';
$replyTo = null;
- $calendarData = $this->getVCalendarCancel();
- $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'CANCEL');
+ $calendar->VEVENT->remove('UID');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $this->time->expects(self::once())
- ->method('getTime')
- ->willReturn(time());
- $this->logger->expects(self::once())
- ->method('warning');
+ public function testHandleImipCancelWithNoOrganizer(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains an organizer');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'linus@stardew-tent-living.com';
+ $recipient = 'pierre@general-store.com';
+ $replyTo = null;
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'CANCEL');
+ $calendar->VEVENT->remove('ORGANIZER');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
- $result = $this->manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ public function testHandleImipCancelWithNoAttendee(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event dose not contains any attendees');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'pierre@general-store.com';
+ $recipient = 'linus@stardew-tent-living.com';
+ $replyTo = null;
+ $calendar = $this->vCalendar3a;
+ $calendar->add('METHOD', 'CANCEL');
+ $calendar->VEVENT->remove('ATTENDEE');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendar->serialize());
+ // Assert
$this->assertFalse($result);
}
- public function testHandleImipCancelNoCalendars(): void {
- /** @var Manager | \PHPUnit\Framework\MockObject\MockObject $manager */
+ public function testHandleImipCancelAttendeeNotRecipient(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
$manager = $this->getMockBuilder(Manager::class)
->setConstructorArgs([
$this->coordinator,
@@ -829,27 +1428,107 @@ class ManagerTest extends TestCase {
$this->userManager,
$this->serverFactory,
])
- ->setMethods([
- 'getCalendarsForPrincipal'
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event could not be processed because recipient must be an ATTENDEE of this event');
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'linus@stardew-tent-living.com';
+ $recipient = 'leah@general-store.com';
+ $replyTo = null;
+ $calendarData = clone $this->vCalendar3a;
+ $calendarData->add('METHOD', 'CANCEL');
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+
+ public function testHandleImipCancelDateInThePast(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
])
+ ->onlyMethods(['getCalendarsForPrincipal'])
->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct logger and time returns
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event could not be processed because the event is in the past');
+ $this->time->expects(self::once())
+ ->method('getTime')
+ ->willReturn(time());
+ // construct parameters
$principalUri = 'principals/user/pierre';
$sender = 'linus@stardew-tent-living.com';
$recipient = 'pierre@general-store.com';
$replyTo = null;
- $calendarData = $this->getVCalendarCancel();
+ $calendarData = clone $this->vCalendar3a;
+ $calendarData->add('METHOD', 'CANCEL');
+ $calendarData->VEVENT->DTSTART = new \DateTime('2013-04-07'); // set to in the past
+ // Act
+ $result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ // Assert
+ $this->assertFalse($result);
+ }
+ public function testHandleImipCancelEventNotFound(): void {
+ // construct mock user calendar
+ $userCalendar = $this->createMock(ITestCalendar::class);
+ $userCalendar->expects(self::once())
+ ->method('search')
+ ->willReturn([]);
+ // construct mock calendar manager and returns
+ /** @var Manager&MockObject $manager */
+ $manager = $this->getMockBuilder(Manager::class)
+ ->setConstructorArgs([
+ $this->coordinator,
+ $this->container,
+ $this->logger,
+ $this->time,
+ $this->secureRandom,
+ $this->userManager,
+ $this->serverFactory,
+ ])
+ ->onlyMethods(['getCalendarsForPrincipal'])
+ ->getMock();
+ $manager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$userCalendar]);
+ // construct time returns
$this->time->expects(self::once())
->method('getTime')
->willReturn(1628374233);
- $manager->expects(self::once())
- ->method('getCalendarsForPrincipal')
- ->with($principalUri)
- ->willReturn([]);
- $this->logger->expects(self::once())
- ->method('warning');
-
+ // construct parameters
+ $principalUri = 'principals/user/pierre';
+ $sender = 'linus@stardew-tent-living.com';
+ $recipient = 'pierre@general-store.com';
+ $replyTo = null;
+ $calendarData = clone $this->vCalendar3a;
+ $calendarData->add('METHOD', 'CANCEL');
+ // construct logger return
+ $this->logger->expects(self::once())->method('warning')
+ ->with('iMip message event could not be processed because no corresponding event was found in any calendar ' . $principalUri . 'and UID' . $calendarData->VEVENT->UID->getValue());
+ // Act
$result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ // Assert
$this->assertFalse($result);
}
@@ -869,12 +1548,14 @@ class ManagerTest extends TestCase {
'getCalendarsForPrincipal'
])
->getMock();
+
$principalUri = 'principals/user/pierre';
- $sender = 'clint@stardew-blacksmiths.com';
+ $sender = 'clint@stardew-tent-living.com';
$recipient = 'pierre@general-store.com';
$replyTo = 'linus@stardew-tent-living.com';
$calendar = $this->createMock(ITestCalendar::class);
- $calendarData = $this->getVCalendarCancel();
+ $calendarData = clone $this->vCalendar3a;
+ $calendarData->add('METHOD', 'CANCEL');
$this->time->expects(self::once())
->method('getTime')
@@ -889,7 +1570,9 @@ class ManagerTest extends TestCase {
$calendar->expects(self::once())
->method('handleIMipMessage')
->with('testname.ics', $calendarData->serialize());
+ // Act
$result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ // Assert
$this->assertTrue($result);
}
@@ -914,7 +1597,8 @@ class ManagerTest extends TestCase {
$recipient = 'pierre@general-store.com';
$replyTo = null;
$calendar = $this->createMock(ITestCalendar::class);
- $calendarData = $this->getVCalendarCancel();
+ $calendarData = clone $this->vCalendar3a;
+ $calendarData->add('METHOD', 'CANCEL');
$this->time->expects(self::once())
->method('getTime')
@@ -929,68 +1613,12 @@ class ManagerTest extends TestCase {
$calendar->expects(self::once())
->method('handleIMipMessage')
->with('testname.ics', $calendarData->serialize());
+ // Act
$result = $manager->handleIMipCancel($principalUri, $sender, $replyTo, $recipient, $calendarData->serialize());
+ // Assert
$this->assertTrue($result);
}
- private function getVCalendarReply(): Document {
- $data = <<<EOF
-BEGIN:VCALENDAR
-PRODID:-//Nextcloud/Nextcloud CalDAV Server//EN
-VERSION:2.0
-CALSCALE:GREGORIAN
-METHOD:REPLY
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20210820
-DTEND;VALUE=DATE:20220821
-DTSTAMP:20210812T100040Z
-ORGANIZER;CN=admin:mailto:linus@stardew-tent-living.com
-UID:dcc733bf-b2b2-41f2-a8cf-550ae4b67aff
-ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=pierr
- e@general-store.com;X-NUM-GUESTS=0:mailto:pierre@general-store.com
-CREATED:20220812T100021Z
-DESCRIPTION:
-LAST-MODIFIED:20220812T100040Z
-LOCATION:
-SEQUENCE:3
-STATUS:CONFIRMED
-SUMMARY:berry basket
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR
-EOF;
- return Reader::read($data);
- }
-
- private function getVCalendarCancel(): Document {
- $data = <<<EOF
-BEGIN:VCALENDAR
-PRODID:-//Nextcloud/Nextcloud CalDAV Server//EN
-VERSION:2.0
-CALSCALE:GREGORIAN
-METHOD:CANCEL
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20210820
-DTEND;VALUE=DATE:20220821
-DTSTAMP:20210812T100040Z
-ORGANIZER;CN=admin:mailto:linus@stardew-tent-living.com
-UID:dcc733bf-b2b2-41f2-a8cf-550ae4b67aff
-ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=pierr
- e@general-store.com;X-NUM-GUESTS=0:mailto:pierre@general-store.com
-CREATED:20220812T100021Z
-DESCRIPTION:
-LAST-MODIFIED:20220812T100040Z
-LOCATION:
-SEQUENCE:3
-STATUS:CANCELLED
-SUMMARY:berry basket
-TRANSP:OPAQUE
-END:VEVENT
-END:VCALENDAR
-EOF;
- return Reader::read($data);
- }
-
private function getFreeBusyResponse(): string {
return <<<EOF
<?xml version="1.0" encoding="utf-8"?>