fix(caldav): Correctly handle calendar recreation for invitations when the current calendar is in the trashbin

Follow-up to #32361, see https://github.com/nextcloud/calendar/issues/4098 for details

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
pull/36594/head
Thomas Citharel 2023-02-07 18:37:58 +07:00
parent d0eeb279b7
commit 4fd58aa45c
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
2 changed files with 48 additions and 18 deletions

@ -48,7 +48,6 @@ use Sabre\VObject\Component;
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;
@ -329,12 +328,12 @@ EOF;
/** @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 = [];
@ -359,9 +358,16 @@ EOF;
$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);
}
}
}
@ -609,4 +615,19 @@ EOF;
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,
]);
}
}

@ -197,6 +197,16 @@ class PluginTest extends TestCase {
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
],
@ -225,6 +235,7 @@ class PluginTest extends TestCase {
true,
false,
false,
false,
],
[
'principals/users/myuser',
@ -263,16 +274,8 @@ class PluginTest extends TestCase {
/**
* @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,
[
@ -328,6 +331,12 @@ class PluginTest extends TestCase {
->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;
@ -349,7 +358,7 @@ class PluginTest extends TestCase {
)
] : [];
if (!$exists) {
if (!$exists || $deleted) {
if (!$hasExistingCalendars) {
$calendarBackend->expects($this->once())
->method('createCalendar')