Skip to content

Commit

Permalink
fix(caldav): Correctly handle calendar recreation for invitations whe…
Browse files Browse the repository at this point in the history
…n the current calendar is in the trashbin

Follow-up to #32361, see nextcloud/calendar#4098 for details

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
  • Loading branch information
tcitworld committed Feb 9, 2023
1 parent d0eeb27 commit 4fd58aa
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 18 deletions.
37 changes: 29 additions & 8 deletions apps/dav/lib/CalDAV/Schedule/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\Component\VEvent;
use Sabre\VObject\DateTimeParser;
use Sabre\VObject\Document;
use Sabre\VObject\FreeBusyGenerator;
use Sabre\VObject\ITip;
use Sabre\VObject\Parameter;
Expand Down Expand Up @@ -329,12 +328,12 @@ public function propFindDefaultCalendarUrl(PropFind $propFind, INode $node) {

/** @var CalendarHome $calendarHome */
$calendarHome = $this->server->tree->getNodeForPath($calendarHomePath);
if (!$calendarHome->childExists($uri)) {
$currentCalendarDeleted = false;
if (!$calendarHome->childExists($uri) || $currentCalendarDeleted = $this->isCalendarDeleted($calendarHome, $uri)) {
// If the default calendar doesn't exist
if ($isResourceOrRoom) {
$calendarHome->getCalDAVBackend()->createCalendar($principalUrl, $uri, [
'{DAV:}displayname' => $displayName,
]);
// Resources or rooms can't be in the trashbin, so we're fine
$this->createCalendar($calendarHome, $principalUrl, $uri, $displayName);
} else {
// And we're not handling scheduling on resource/room booking
$userCalendars = [];
Expand All @@ -359,9 +358,16 @@ public function propFindDefaultCalendarUrl(PropFind $propFind, INode $node) {
$uri = $userCalendars[0]->getName();
} else {
// Otherwise if we have really nothing, create a new calendar
$calendarHome->getCalDAVBackend()->createCalendar($principalUrl, $uri, [
'{DAV:}displayname' => $displayName,
]);
if ($currentCalendarDeleted) {
// If the calendar exists but is deleted, we need to purge it first
// This may cause some issues in a non synchronous database setup
$calendar = $this->getCalendar($calendarHome, $uri);
if ($calendar instanceof Calendar) {
$calendar->disableTrashbin();
$calendar->delete();
}
}
$this->createCalendar($calendarHome, $principalUrl, $uri, $displayName);
}
}
}
Expand Down Expand Up @@ -609,4 +615,19 @@ private function stripOffMailTo(string $email): string {

return $email;
}

private function getCalendar(CalendarHome $calendarHome, string $uri): INode {
return $calendarHome->getChild($uri);
}

private function isCalendarDeleted(CalendarHome $calendarHome, string $uri): bool {
$calendar = $this->getCalendar($calendarHome, $uri);
return $calendar instanceof Calendar && $calendar->isDeleted();
}

private function createCalendar(CalendarHome $calendarHome, string $principalUri, string $uri, string $displayName): void {
$calendarHome->getCalDAVBackend()->createCalendar($principalUri, $uri, [
'{DAV:}displayname' => $displayName,
]);
}
}
29 changes: 19 additions & 10 deletions apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,16 @@ public function propFindDefaultCalendarUrlProvider(): array {
false,
CalDavBackend::PERSONAL_CALENDAR_URI,
CalDavBackend::PERSONAL_CALENDAR_NAME,
true,
true
],
[
'principals/users/myuser',
'calendars/myuser',
false,
CalDavBackend::PERSONAL_CALENDAR_URI,
CalDavBackend::PERSONAL_CALENDAR_NAME,
false,
false,
true
],
Expand Down Expand Up @@ -225,6 +235,7 @@ public function propFindDefaultCalendarUrlProvider(): array {
true,
false,
false,
false,
],
[
'principals/users/myuser',
Expand Down Expand Up @@ -263,16 +274,8 @@ public function propFindDefaultCalendarUrlProvider(): array {

/**
* @dataProvider propFindDefaultCalendarUrlProvider
* @param string $principalUri
* @param string|null $calendarHome
* @param bool $isResource
* @param string $calendarUri
* @param string $displayName
* @param bool $exists
* @param bool $propertiesForPath
*/
public function testPropFindDefaultCalendarUrl(string $principalUri, ?string $calendarHome, bool $isResource, string $calendarUri, string $displayName, bool $exists, bool $hasExistingCalendars = false, bool $propertiesForPath = true): void {
/** @var PropFind $propFind */
public function testPropFindDefaultCalendarUrl(string $principalUri, ?string $calendarHome, bool $isResource, string $calendarUri, string $displayName, bool $exists, bool $deleted = false, bool $hasExistingCalendars = false, bool $propertiesForPath = true): void {
$propFind = new PropFind(
$principalUri,
[
Expand Down Expand Up @@ -328,6 +331,12 @@ public function testPropFindDefaultCalendarUrl(string $principalUri, ?string $ca
->with($calendarUri)
->willReturn($exists);

if ($exists) {
$calendar = $this->createMock(Calendar::class);
$calendar->expects($this->once())->method('isDeleted')->willReturn($deleted);
$calendarHomeObject->expects($deleted && !$hasExistingCalendars ? $this->exactly(2) : $this->once())->method('getChild')->with($calendarUri)->willReturn($calendar);
}

$calendarBackend = $this->createMock(CalDavBackend::class);
$calendarUri = $hasExistingCalendars ? 'custom' : $calendarUri;
$displayName = $hasExistingCalendars ? 'Custom Calendar' : $displayName;
Expand All @@ -349,7 +358,7 @@ public function testPropFindDefaultCalendarUrl(string $principalUri, ?string $ca
)
] : [];

if (!$exists) {
if (!$exists || $deleted) {
if (!$hasExistingCalendars) {
$calendarBackend->expects($this->once())
->method('createCalendar')
Expand Down

0 comments on commit 4fd58aa

Please sign in to comment.