Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions lib/private/Calendar/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use DateTimeInterface;
use OC\AppFramework\Bootstrap\Coordinator;
use OCA\DAV\CalDAV\Auth\CustomPrincipalPlugin;
use OCA\DAV\Db\PropertyMapper;
use OCA\DAV\ServerFactory;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Calendar\Exceptions\CalendarException;
Expand Down Expand Up @@ -58,6 +59,7 @@ public function __construct(
private ISecureRandom $random,
private IUserManager $userManager,
private ServerFactory $serverFactory,
private PropertyMapper $propertyMapper,
) {
}

Expand Down Expand Up @@ -227,6 +229,7 @@ public function newQuery(string $principalUri): ICalendarQuery {
protected function handleIMip(
string $userId,
string $message,
array $options = [],
): bool {

$userUri = 'principals/users/' . $userId;
Expand Down Expand Up @@ -287,6 +290,30 @@ protected function handleIMip(
}
}

if ($options['absent'] === 'create') {
// retrieve the primary calendar for the user
$calendar = $this->getPrimaryCalendar($userId);
if ($calendar !== null && (
!$calendar instanceof IHandleImipMessage || !$calendar instanceof ICalendarIsWritable || $calendar->isDeleted() || !$calendar->isWritable()
)) {
$calendar = null;
}
// if no primary calendar is set, use the first writable calendar
if ($calendar === null) {
foreach ($userCalendars as $userCalendar) {
if ($userCalendar instanceof IHandleImipMessage && $userCalendar instanceof ICalendarIsWritable && !$userCalendar->isDeleted() && $userCalendar->isWritable()) {
$calendar = $userCalendar;
break;
}
}
}
if ($calendar === null) {
$this->logger->warning('iMip message could not be processed because no writable calendar was found');
return false;
}
$calendar->handleIMipMessage($userId, $vObject->serialize());
}

$this->logger->warning('iMip message could not be processed because no corresponding event was found in any calendar');

return false;
Expand Down Expand Up @@ -437,4 +464,32 @@ public function checkAvailability(

return $result;
}

public function getPrimaryCalendar(string $userId): ?ICalendar {
// determine if the principal has a default calendar configured
$properties = $this->propertyMapper->findPropertyByPathAndName(
$userId,
'principals/users/' . $userId,
'{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL'
);
if ($properties === []) {
return null;
}
// extract the calendar URI from the property value
$propertyValue = $properties[0]->getPropertyvalue() ?? null;
if (str_starts_with($propertyValue, 'calendars/' . $userId)) {
$calendarUri = rtrim(str_replace('calendars/' . $userId . '/', '', $propertyValue), '/');
}
if (empty($calendarUri)) {
return null;
}
// retrieve the calendar by URI
$calendars = $this->getCalendarsForPrincipal('principals/users/' . $userId, [$calendarUri]);
if ($calendars === []) {
return null;
}

return $calendars[0];
}

}
11 changes: 11 additions & 0 deletions tests/lib/Calendar/ManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class ManagerTest extends TestCase {

private IUserManager&MockObject $userManager;
private ServerFactory&MockObject $serverFactory;
private PropertyMapper&MockObject $propertyMapper;

private VCalendar $vCalendar1a;
private VCalendar $vCalendar2a;
Expand All @@ -73,6 +74,7 @@ protected function setUp(): void {
$this->secureRandom = $this->createMock(ISecureRandom::class);
$this->userManager = $this->createMock(IUserManager::class);
$this->serverFactory = $this->createMock(ServerFactory::class);
$this->propertyMapper = $this->createMock(PropertyMapper::class);

$this->manager = new Manager(
$this->coordinator,
Expand All @@ -82,6 +84,7 @@ protected function setUp(): void {
$this->secureRandom,
$this->userManager,
$this->serverFactory,
$this->propertyMapper,
);

// construct calendar with a 1 hour event and same start/end time zones
Expand Down Expand Up @@ -329,6 +332,7 @@ public function testHandleImipWithNoCalendars(): void {
$this->secureRandom,
$this->userManager,
$this->serverFactory,
$this->propertyMapper,
])
->onlyMethods(['getCalendarsForPrincipal'])
->getMock();
Expand Down Expand Up @@ -362,6 +366,7 @@ public function testHandleImipWithNoEvent(): void {
$this->secureRandom,
$this->userManager,
$this->serverFactory,
$this->propertyMapper,
])
->onlyMethods(['getCalendarsForPrincipal'])
->getMock();
Expand Down Expand Up @@ -396,6 +401,7 @@ public function testHandleImipWithNoUid(): void {
$this->secureRandom,
$this->userManager,
$this->serverFactory,
$this->propertyMapper,
])
->onlyMethods(['getCalendarsForPrincipal'])
->getMock();
Expand Down Expand Up @@ -439,6 +445,7 @@ public function testHandleImipWithNoMatch(): void {
$this->secureRandom,
$this->userManager,
$this->serverFactory,
$this->propertyMapper,
])
->onlyMethods(['getCalendarsForPrincipal'])
->getMock();
Expand Down Expand Up @@ -481,6 +488,7 @@ public function testHandleImip(): void {
$this->secureRandom,
$this->userManager,
$this->serverFactory,
$this->propertyMapper,
])
->onlyMethods(['getCalendarsForPrincipal'])
->getMock();
Expand Down Expand Up @@ -528,6 +536,7 @@ public function testhandleIMipRequest() {
$this->secureRandom,
$this->userManager,
$this->serverFactory,
$this->propertyMapper,
])
->onlyMethods(['handleIMip'])
->getMock();
Expand Down Expand Up @@ -570,6 +579,7 @@ public function testhandleIMipReply() {
$this->secureRandom,
$this->userManager,
$this->serverFactory,
$this->propertyMapper,
])
->onlyMethods(['handleIMip'])
->getMock();
Expand Down Expand Up @@ -614,6 +624,7 @@ public function testhandleIMipCancel() {
$this->secureRandom,
$this->userManager,
$this->serverFactory,
$this->propertyMapper,
])
->onlyMethods(['handleIMip'])
->getMock();
Expand Down
Loading