Reject calendars that - are subscriptions - are not writable - are shared with a user - are deleted - don't support VEVENTs Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>pull/45667/head
parent
1768bd6280
commit
cbea787233
@ -0,0 +1,41 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
||||
*/ |
||||
|
||||
namespace OCA\DAV\CalDAV; |
||||
|
||||
use Sabre\DAV\Exception as DavException; |
||||
|
||||
class DefaultCalendarValidator { |
||||
/** |
||||
* Check if a given Calendar node is suitable to be used as the default calendar for scheduling. |
||||
* |
||||
* @throws DavException If the calendar is not suitable to be used as the default calendar |
||||
*/ |
||||
public function validateScheduleDefaultCalendar(Calendar $calendar): void { |
||||
// Sanity checks for a calendar that should handle invitations |
||||
if ($calendar->isSubscription() |
||||
|| !$calendar->canWrite() |
||||
|| $calendar->isShared() |
||||
|| $calendar->isDeleted()) { |
||||
throw new DavException('Calendar is a subscription, not writable, shared or deleted'); |
||||
} |
||||
|
||||
// Calendar must support VEVENTs |
||||
$sCCS = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set'; |
||||
$calendarProperties = $calendar->getProperties([$sCCS]); |
||||
if (isset($calendarProperties[$sCCS])) { |
||||
$supportedComponents = $calendarProperties[$sCCS]->getValue(); |
||||
} else { |
||||
$supportedComponents = ['VJOURNAL', 'VTODO', 'VEVENT']; |
||||
} |
||||
if (!in_array('VEVENT', $supportedComponents, true)) { |
||||
throw new DavException('Calendar does not support VEVENT components'); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,171 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/** |
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
||||
*/ |
||||
|
||||
namespace OCA\DAV\Tests\unit\CalDAV; |
||||
|
||||
use OCA\DAV\CalDAV\Calendar; |
||||
use OCA\DAV\CalDAV\DefaultCalendarValidator; |
||||
use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet; |
||||
use Test\TestCase; |
||||
|
||||
class DefaultCalendarValidatorTest extends TestCase { |
||||
private DefaultCalendarValidator $validator; |
||||
|
||||
protected function setUp(): void { |
||||
parent::setUp(); |
||||
|
||||
$this->validator = new DefaultCalendarValidator(); |
||||
} |
||||
|
||||
public function testValidateScheduleDefaultCalendar(): void { |
||||
$node = $this->createMock(Calendar::class); |
||||
$node->expects(self::once()) |
||||
->method('isSubscription') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('canWrite') |
||||
->willReturn(true); |
||||
$node->expects(self::once()) |
||||
->method('isShared') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('isDeleted') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('getProperties') |
||||
->willReturn([ |
||||
'{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new SupportedCalendarComponentSet(['VEVENT']), |
||||
]); |
||||
|
||||
$this->validator->validateScheduleDefaultCalendar($node); |
||||
} |
||||
|
||||
public function testValidateScheduleDefaultCalendarWithEmptyProperties(): void { |
||||
$node = $this->createMock(Calendar::class); |
||||
$node->expects(self::once()) |
||||
->method('isSubscription') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('canWrite') |
||||
->willReturn(true); |
||||
$node->expects(self::once()) |
||||
->method('isShared') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('isDeleted') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('getProperties') |
||||
->willReturn([]); |
||||
|
||||
$this->validator->validateScheduleDefaultCalendar($node); |
||||
} |
||||
|
||||
public function testValidateScheduleDefaultCalendarWithSubscription(): void { |
||||
$node = $this->createMock(Calendar::class); |
||||
$node->expects(self::once()) |
||||
->method('isSubscription') |
||||
->willReturn(true); |
||||
$node->expects(self::never()) |
||||
->method('canWrite'); |
||||
$node->expects(self::never()) |
||||
->method('isShared'); |
||||
$node->expects(self::never()) |
||||
->method('isDeleted'); |
||||
$node->expects(self::never()) |
||||
->method('getProperties'); |
||||
|
||||
$this->expectException(\Sabre\DAV\Exception::class); |
||||
$this->validator->validateScheduleDefaultCalendar($node); |
||||
} |
||||
|
||||
public function testValidateScheduleDefaultCalendarWithoutWrite(): void { |
||||
$node = $this->createMock(Calendar::class); |
||||
$node->expects(self::once()) |
||||
->method('isSubscription') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('canWrite') |
||||
->willReturn(false); |
||||
$node->expects(self::never()) |
||||
->method('isShared'); |
||||
$node->expects(self::never()) |
||||
->method('isDeleted'); |
||||
$node->expects(self::never()) |
||||
->method('getProperties'); |
||||
|
||||
$this->expectException(\Sabre\DAV\Exception::class); |
||||
$this->validator->validateScheduleDefaultCalendar($node); |
||||
} |
||||
|
||||
public function testValidateScheduleDefaultCalendarWithShared(): void { |
||||
$node = $this->createMock(Calendar::class); |
||||
$node->expects(self::once()) |
||||
->method('isSubscription') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('canWrite') |
||||
->willReturn(true); |
||||
$node->expects(self::once()) |
||||
->method('isShared') |
||||
->willReturn(true); |
||||
$node->expects(self::never()) |
||||
->method('isDeleted'); |
||||
$node->expects(self::never()) |
||||
->method('getProperties'); |
||||
|
||||
$this->expectException(\Sabre\DAV\Exception::class); |
||||
$this->validator->validateScheduleDefaultCalendar($node); |
||||
} |
||||
|
||||
public function testValidateScheduleDefaultCalendarWithDeleted(): void { |
||||
$node = $this->createMock(Calendar::class); |
||||
$node->expects(self::once()) |
||||
->method('isSubscription') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('canWrite') |
||||
->willReturn(true); |
||||
$node->expects(self::once()) |
||||
->method('isShared') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('isDeleted') |
||||
->willReturn(true); |
||||
$node->expects(self::never()) |
||||
->method('getProperties'); |
||||
|
||||
$this->expectException(\Sabre\DAV\Exception::class); |
||||
$this->validator->validateScheduleDefaultCalendar($node); |
||||
} |
||||
|
||||
public function testValidateScheduleDefaultCalendarWithoutVeventSupport(): void { |
||||
$node = $this->createMock(Calendar::class); |
||||
$node->expects(self::once()) |
||||
->method('isSubscription') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('canWrite') |
||||
->willReturn(true); |
||||
$node->expects(self::once()) |
||||
->method('isShared') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('isDeleted') |
||||
->willReturn(false); |
||||
$node->expects(self::once()) |
||||
->method('getProperties') |
||||
->willReturn([ |
||||
'{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new SupportedCalendarComponentSet(['VTODO']), |
||||
]); |
||||
|
||||
$this->expectException(\Sabre\DAV\Exception::class); |
||||
$this->validator->validateScheduleDefaultCalendar($node); |
||||
} |
||||
} |
Loading…
Reference in new issue