mirror of
https://github.com/nextcloud/server.git
synced 2026-02-20 00:12:30 -05:00
Merge pull request #45667 from nextcloud/fix/caldav/strict-default-calendar-checks
fix(caldav): stricter default calendar checks
This commit is contained in:
commit
e54d39b076
13 changed files with 326 additions and 19 deletions
|
|
@ -9,6 +9,7 @@
|
|||
use OC\KnownUser\KnownUserService;
|
||||
use OCA\DAV\CalDAV\CalDavBackend;
|
||||
use OCA\DAV\CalDAV\CalendarRoot;
|
||||
use OCA\DAV\CalDAV\DefaultCalendarValidator;
|
||||
use OCA\DAV\CalDAV\Security\RateLimitingPlugin;
|
||||
use OCA\DAV\CalDAV\Validation\CalDavValidatePlugin;
|
||||
use OCA\DAV\Connector\LegacyDAVACL;
|
||||
|
|
@ -92,7 +93,7 @@ if ($debugging) {
|
|||
|
||||
$server->addPlugin(new \Sabre\DAV\Sync\Plugin());
|
||||
$server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
|
||||
$server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class)));
|
||||
$server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class), \OC::$server->get(DefaultCalendarValidator::class)));
|
||||
|
||||
if ($sendInvitations) {
|
||||
$server->addPlugin(\OC::$server->query(\OCA\DAV\CalDAV\Schedule\IMipPlugin::class));
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ return array(
|
|||
'OCA\\DAV\\CalDAV\\CalendarObject' => $baseDir . '/../lib/CalDAV/CalendarObject.php',
|
||||
'OCA\\DAV\\CalDAV\\CalendarProvider' => $baseDir . '/../lib/CalDAV/CalendarProvider.php',
|
||||
'OCA\\DAV\\CalDAV\\CalendarRoot' => $baseDir . '/../lib/CalDAV/CalendarRoot.php',
|
||||
'OCA\\DAV\\CalDAV\\DefaultCalendarValidator' => $baseDir . '/../lib/CalDAV/DefaultCalendarValidator.php',
|
||||
'OCA\\DAV\\CalDAV\\EventComparisonService' => $baseDir . '/../lib/CalDAV/EventComparisonService.php',
|
||||
'OCA\\DAV\\CalDAV\\EventReader' => $baseDir . '/../lib/CalDAV/EventReader.php',
|
||||
'OCA\\DAV\\CalDAV\\EventReaderRDate' => $baseDir . '/../lib/CalDAV/EventReaderRDate.php',
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ class ComposerStaticInitDAV
|
|||
'OCA\\DAV\\CalDAV\\CalendarObject' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarObject.php',
|
||||
'OCA\\DAV\\CalDAV\\CalendarProvider' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarProvider.php',
|
||||
'OCA\\DAV\\CalDAV\\CalendarRoot' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarRoot.php',
|
||||
'OCA\\DAV\\CalDAV\\DefaultCalendarValidator' => __DIR__ . '/..' . '/../lib/CalDAV/DefaultCalendarValidator.php',
|
||||
'OCA\\DAV\\CalDAV\\EventComparisonService' => __DIR__ . '/..' . '/../lib/CalDAV/EventComparisonService.php',
|
||||
'OCA\\DAV\\CalDAV\\EventReader' => __DIR__ . '/..' . '/../lib/CalDAV/EventReader.php',
|
||||
'OCA\\DAV\\CalDAV\\EventReaderRDate' => __DIR__ . '/..' . '/../lib/CalDAV/EventReaderRDate.php',
|
||||
|
|
|
|||
41
apps/dav/lib/CalDAV/DefaultCalendarValidator.php
Normal file
41
apps/dav/lib/CalDAV/DefaultCalendarValidator.php
Normal file
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ namespace OCA\DAV\CalDAV\InvitationResponse;
|
|||
use OCA\DAV\AppInfo\PluginManager;
|
||||
use OCA\DAV\CalDAV\Auth\CustomPrincipalPlugin;
|
||||
use OCA\DAV\CalDAV\Auth\PublicPrincipalPlugin;
|
||||
use OCA\DAV\CalDAV\DefaultCalendarValidator;
|
||||
use OCA\DAV\Connector\Sabre\AnonymousOptionsPlugin;
|
||||
use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin;
|
||||
use OCA\DAV\Connector\Sabre\CachingTree;
|
||||
|
|
@ -69,7 +70,7 @@ class InvitationResponseServer {
|
|||
// calendar plugins
|
||||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin());
|
||||
$this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
|
||||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class)));
|
||||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class), \OC::$server->get(DefaultCalendarValidator::class)));
|
||||
$this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin());
|
||||
$this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin());
|
||||
//$this->server->addPlugin(new \OCA\DAV\DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest()));
|
||||
|
|
|
|||
|
|
@ -9,11 +9,13 @@ use DateTimeZone;
|
|||
use OCA\DAV\CalDAV\CalDavBackend;
|
||||
use OCA\DAV\CalDAV\Calendar;
|
||||
use OCA\DAV\CalDAV\CalendarHome;
|
||||
use OCA\DAV\CalDAV\DefaultCalendarValidator;
|
||||
use OCP\IConfig;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Sabre\CalDAV\ICalendar;
|
||||
use Sabre\CalDAV\ICalendarObject;
|
||||
use Sabre\CalDAV\Schedule\ISchedulingObject;
|
||||
use Sabre\DAV\Exception as DavException;
|
||||
use Sabre\DAV\INode;
|
||||
use Sabre\DAV\IProperties;
|
||||
use Sabre\DAV\PropFind;
|
||||
|
|
@ -51,13 +53,15 @@ class Plugin extends \Sabre\CalDAV\Schedule\Plugin {
|
|||
public const CALENDAR_USER_TYPE = '{' . self::NS_CALDAV . '}calendar-user-type';
|
||||
public const SCHEDULE_DEFAULT_CALENDAR_URL = '{' . Plugin::NS_CALDAV . '}schedule-default-calendar-URL';
|
||||
private LoggerInterface $logger;
|
||||
private DefaultCalendarValidator $defaultCalendarValidator;
|
||||
|
||||
/**
|
||||
* @param IConfig $config
|
||||
*/
|
||||
public function __construct(IConfig $config, LoggerInterface $logger) {
|
||||
public function __construct(IConfig $config, LoggerInterface $logger, DefaultCalendarValidator $defaultCalendarValidator) {
|
||||
$this->config = $config;
|
||||
$this->logger = $logger;
|
||||
$this->defaultCalendarValidator = $defaultCalendarValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -360,11 +364,20 @@ EOF;
|
|||
* - isn't a calendar subscription
|
||||
* - user can write to it (no virtual/3rd-party calendars)
|
||||
* - calendar isn't a share
|
||||
* - calendar supports VEVENTs
|
||||
*/
|
||||
foreach ($calendarHome->getChildren() as $node) {
|
||||
if ($node instanceof Calendar && !$node->isSubscription() && $node->canWrite() && !$node->isShared() && !$node->isDeleted()) {
|
||||
$userCalendars[] = $node;
|
||||
if (!($node instanceof Calendar)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->defaultCalendarValidator->validateScheduleDefaultCalendar($node);
|
||||
} catch (DavException $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$userCalendars[] = $node;
|
||||
}
|
||||
|
||||
if (count($userCalendars) > 0) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
namespace OCA\DAV\Connector\Sabre;
|
||||
|
||||
use OCA\DAV\AppInfo\PluginManager;
|
||||
use OCA\DAV\CalDAV\DefaultCalendarValidator;
|
||||
use OCA\DAV\DAV\ViewOnlyPlugin;
|
||||
use OCA\DAV\Files\BrowserErrorPagePlugin;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
|
|
@ -167,7 +168,8 @@ class ServerFactory {
|
|||
$server,
|
||||
$objectTree,
|
||||
$this->databaseConnection,
|
||||
$this->userSession->getUser()
|
||||
$this->userSession->getUser(),
|
||||
\OC::$server->get(DefaultCalendarValidator::class),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,12 +8,13 @@
|
|||
namespace OCA\DAV\DAV;
|
||||
|
||||
use Exception;
|
||||
use OCA\DAV\CalDAV\Calendar;
|
||||
use OCA\DAV\CalDAV\DefaultCalendarValidator;
|
||||
use OCA\DAV\Connector\Sabre\Directory;
|
||||
use OCA\DAV\Connector\Sabre\FilesPlugin;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUser;
|
||||
use Sabre\CalDAV\ICalendar;
|
||||
use Sabre\DAV\Exception as DavException;
|
||||
use Sabre\DAV\PropertyStorage\Backend\BackendInterface;
|
||||
use Sabre\DAV\PropFind;
|
||||
|
|
@ -135,6 +136,7 @@ class CustomPropertiesBackend implements BackendInterface {
|
|||
|
||||
private Server $server;
|
||||
private XmlService $xmlService;
|
||||
private DefaultCalendarValidator $defaultCalendarValidator;
|
||||
|
||||
/**
|
||||
* @param Tree $tree node tree
|
||||
|
|
@ -146,6 +148,7 @@ class CustomPropertiesBackend implements BackendInterface {
|
|||
Tree $tree,
|
||||
IDBConnection $connection,
|
||||
IUser $user,
|
||||
DefaultCalendarValidator $defaultCalendarValidator,
|
||||
) {
|
||||
$this->server = $server;
|
||||
$this->tree = $tree;
|
||||
|
|
@ -156,6 +159,7 @@ class CustomPropertiesBackend implements BackendInterface {
|
|||
$this->xmlService->elementMap,
|
||||
self::COMPLEX_XML_ELEMENT_MAP,
|
||||
);
|
||||
$this->defaultCalendarValidator = $defaultCalendarValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -319,10 +323,11 @@ class CustomPropertiesBackend implements BackendInterface {
|
|||
|
||||
// $path is the principal here as this prop is only set on principals
|
||||
$node = $this->tree->getNodeForPath($href);
|
||||
if (!($node instanceof ICalendar) || $node->getOwner() !== $path) {
|
||||
if (!($node instanceof Calendar) || $node->getOwner() !== $path) {
|
||||
throw new DavException('No such calendar');
|
||||
}
|
||||
|
||||
$this->defaultCalendarValidator->validateScheduleDefaultCalendar($node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ namespace OCA\DAV;
|
|||
use OCA\DAV\AppInfo\PluginManager;
|
||||
use OCA\DAV\BulkUpload\BulkUploadPlugin;
|
||||
use OCA\DAV\CalDAV\BirthdayService;
|
||||
use OCA\DAV\CalDAV\DefaultCalendarValidator;
|
||||
use OCA\DAV\CalDAV\Schedule\IMipPlugin;
|
||||
use OCA\DAV\CalDAV\Security\RateLimitingPlugin;
|
||||
use OCA\DAV\CalDAV\Validation\CalDavValidatePlugin;
|
||||
|
|
@ -153,7 +154,7 @@ class Server {
|
|||
$this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest(), \OC::$server->getConfig()));
|
||||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin());
|
||||
$this->server->addPlugin(new \OCA\DAV\CalDAV\ICSExportPlugin\ICSExportPlugin(\OC::$server->getConfig(), $logger));
|
||||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class)));
|
||||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class), \OC::$server->get(DefaultCalendarValidator::class)));
|
||||
|
||||
$this->server->addPlugin(\OC::$server->get(\OCA\DAV\CalDAV\Trashbin\Plugin::class));
|
||||
$this->server->addPlugin(new \OCA\DAV\CalDAV\WebcalCaching\Plugin($request));
|
||||
|
|
@ -254,7 +255,8 @@ class Server {
|
|||
$this->server,
|
||||
$this->server->tree,
|
||||
\OC::$server->getDatabaseConnection(),
|
||||
\OC::$server->getUserSession()->getUser()
|
||||
\OC::$server->getUserSession()->getUser(),
|
||||
\OC::$server->get(DefaultCalendarValidator::class),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
|||
171
apps/dav/tests/unit/CalDAV/DefaultCalendarValidatorTest.php
Normal file
171
apps/dav/tests/unit/CalDAV/DefaultCalendarValidatorTest.php
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ namespace OCA\DAV\Tests\unit\CalDAV\Schedule;
|
|||
use OCA\DAV\CalDAV\CalDavBackend;
|
||||
use OCA\DAV\CalDAV\Calendar;
|
||||
use OCA\DAV\CalDAV\CalendarHome;
|
||||
use OCA\DAV\CalDAV\DefaultCalendarValidator;
|
||||
use OCA\DAV\CalDAV\Plugin as CalDAVPlugin;
|
||||
use OCA\DAV\CalDAV\Schedule\Plugin;
|
||||
use OCA\DAV\CalDAV\Trashbin\Plugin as TrashbinPlugin;
|
||||
|
|
@ -39,6 +40,9 @@ class PluginTest extends TestCase {
|
|||
/** @var MockObject|LoggerInterface */
|
||||
private $logger;
|
||||
|
||||
/** @property MockObject|DefaultCalendarValidator */
|
||||
private $defaultCalendarValidator;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
|
|
@ -53,13 +57,14 @@ class PluginTest extends TestCase {
|
|||
$this->server->xml = new Service();
|
||||
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
$this->defaultCalendarValidator = $this->createMock(DefaultCalendarValidator::class);
|
||||
|
||||
$this->plugin = new Plugin($this->config, $this->logger);
|
||||
$this->plugin = new Plugin($this->config, $this->logger, $this->defaultCalendarValidator);
|
||||
$this->plugin->initialize($this->server);
|
||||
}
|
||||
|
||||
public function testInitialize(): void {
|
||||
$plugin = new Plugin($this->config, $this->logger);
|
||||
$plugin = new Plugin($this->config, $this->logger, $this->defaultCalendarValidator);
|
||||
|
||||
$this->server->expects($this->exactly(10))
|
||||
->method('on')
|
||||
|
|
@ -376,6 +381,13 @@ class PluginTest extends TestCase {
|
|||
->with($calendarHome .'/' . $calendarUri, [], 1)
|
||||
->willReturn($properties);
|
||||
|
||||
$this->defaultCalendarValidator->method('validateScheduleDefaultCalendar')
|
||||
->willReturnCallback(function (Calendar $node) {
|
||||
if ($node->isDeleted()) {
|
||||
throw new \Sabre\DAV\Exception('Deleted calendar');
|
||||
}
|
||||
});
|
||||
|
||||
$this->plugin->propFindDefaultCalendarUrl($propFind, $node);
|
||||
|
||||
if (!$propertiesForPath) {
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@
|
|||
*/
|
||||
namespace OCA\DAV\Tests\unit\Connector\Sabre;
|
||||
|
||||
use OCA\DAV\CalDAV\DefaultCalendarValidator;
|
||||
use OCA\DAV\Connector\Sabre\Directory;
|
||||
use OCA\DAV\Connector\Sabre\File;
|
||||
use OCP\IUser;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Sabre\DAV\Tree;
|
||||
|
||||
/**
|
||||
|
|
@ -41,6 +43,9 @@ class CustomPropertiesBackendTest extends \Test\TestCase {
|
|||
*/
|
||||
private $user;
|
||||
|
||||
/** @property MockObject|DefaultCalendarValidator */
|
||||
private $defaultCalendarValidator;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->server = new \Sabre\DAV\Server();
|
||||
|
|
@ -57,11 +62,14 @@ class CustomPropertiesBackendTest extends \Test\TestCase {
|
|||
->method('getUID')
|
||||
->willReturn($userId);
|
||||
|
||||
$this->defaultCalendarValidator = $this->createMock(DefaultCalendarValidator::class);
|
||||
|
||||
$this->plugin = new \OCA\DAV\DAV\CustomPropertiesBackend(
|
||||
$this->server,
|
||||
$this->tree,
|
||||
\OC::$server->getDatabaseConnection(),
|
||||
$this->user
|
||||
$this->user,
|
||||
$this->defaultCalendarValidator,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@
|
|||
*/
|
||||
namespace OCA\DAV\Tests\DAV;
|
||||
|
||||
use OCA\DAV\CalDAV\Calendar;
|
||||
use OCA\DAV\CalDAV\DefaultCalendarValidator;
|
||||
use OCA\DAV\DAV\CustomPropertiesBackend;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUser;
|
||||
use Sabre\CalDAV\ICalendar;
|
||||
use Sabre\DAV\Exception\NotFound;
|
||||
use Sabre\DAV\PropFind;
|
||||
use Sabre\DAV\PropPatch;
|
||||
|
|
@ -41,6 +42,9 @@ class CustomPropertiesBackendTest extends TestCase {
|
|||
/** @var CustomPropertiesBackend | \PHPUnit\Framework\MockObject\MockObject */
|
||||
private $backend;
|
||||
|
||||
/** @property DefaultCalendarValidator | \PHPUnit\Framework\MockObject\MockObject */
|
||||
private $defaultCalendarValidator;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
|
|
@ -53,12 +57,14 @@ class CustomPropertiesBackendTest extends TestCase {
|
|||
->with()
|
||||
->willReturn('dummy_user_42');
|
||||
$this->dbConnection = \OC::$server->getDatabaseConnection();
|
||||
$this->defaultCalendarValidator = $this->createMock(DefaultCalendarValidator::class);
|
||||
|
||||
$this->backend = new CustomPropertiesBackend(
|
||||
$this->server,
|
||||
$this->tree,
|
||||
$this->dbConnection,
|
||||
$this->user,
|
||||
$this->defaultCalendarValidator,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +137,7 @@ class CustomPropertiesBackendTest extends TestCase {
|
|||
$this->tree,
|
||||
$db,
|
||||
$this->user,
|
||||
$this->defaultCalendarValidator,
|
||||
);
|
||||
|
||||
$propFind = $this->createMock(PropFind::class);
|
||||
|
|
@ -195,7 +202,7 @@ class CustomPropertiesBackendTest extends TestCase {
|
|||
public function testPropFindPrincipalCall(): void {
|
||||
$this->tree->method('getNodeForPath')
|
||||
->willReturnCallback(function ($uri) {
|
||||
$node = $this->createMock(ICalendar::class);
|
||||
$node = $this->createMock(Calendar::class);
|
||||
$node->method('getOwner')
|
||||
->willReturn('principals/users/dummy_user_42');
|
||||
return $node;
|
||||
|
|
@ -242,21 +249,21 @@ class CustomPropertiesBackendTest extends TestCase {
|
|||
return [
|
||||
[ // Exists
|
||||
'dummy_user_42',
|
||||
['calendars/dummy_user_42/foo/' => ICalendar::class],
|
||||
['calendars/dummy_user_42/foo/' => Calendar::class],
|
||||
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/dummy_user_42/foo/')],
|
||||
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL'],
|
||||
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/dummy_user_42/foo/')],
|
||||
],
|
||||
[ // Doesn't exist
|
||||
'dummy_user_42',
|
||||
['calendars/dummy_user_42/foo/' => ICalendar::class],
|
||||
['calendars/dummy_user_42/foo/' => Calendar::class],
|
||||
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/dummy_user_42/bar/')],
|
||||
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL'],
|
||||
[],
|
||||
],
|
||||
[ // No privilege
|
||||
'dummy_user_42',
|
||||
['calendars/user2/baz/' => ICalendar::class],
|
||||
['calendars/user2/baz/' => Calendar::class],
|
||||
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('calendars/user2/baz/')],
|
||||
['{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL'],
|
||||
[],
|
||||
|
|
@ -349,7 +356,7 @@ class CustomPropertiesBackendTest extends TestCase {
|
|||
});
|
||||
$this->tree->method('getNodeForPath')
|
||||
->willReturnCallback(function ($uri) {
|
||||
$node = $this->createMock(ICalendar::class);
|
||||
$node = $this->createMock(Calendar::class);
|
||||
$node->method('getOwner')
|
||||
->willReturn('principals/users/' . $this->user->getUID());
|
||||
return $node;
|
||||
|
|
@ -377,6 +384,48 @@ class CustomPropertiesBackendTest extends TestCase {
|
|||
];
|
||||
}
|
||||
|
||||
public function testPropPatchWithUnsuitableCalendar(): void {
|
||||
$path = 'principals/users/' . $this->user->getUID();
|
||||
|
||||
$node = $this->createMock(Calendar::class);
|
||||
$node->expects(self::once())
|
||||
->method('getOwner')
|
||||
->willReturn($path);
|
||||
|
||||
$this->defaultCalendarValidator->expects(self::once())
|
||||
->method('validateScheduleDefaultCalendar')
|
||||
->with($node)
|
||||
->willThrowException(new \Sabre\DAV\Exception("Invalid calendar"));
|
||||
|
||||
$this->server->method('calculateUri')
|
||||
->willReturnCallback(function ($uri) {
|
||||
if (str_starts_with($uri, self::BASE_URI)) {
|
||||
return trim(substr($uri, strlen(self::BASE_URI)), '/');
|
||||
}
|
||||
return null;
|
||||
});
|
||||
$this->tree->expects(self::once())
|
||||
->method('getNodeForPath')
|
||||
->with('foo/bar/')
|
||||
->willReturn($node);
|
||||
|
||||
$storedProps = $this->getProps($this->user->getUID(), $path);
|
||||
$this->assertEquals([], $storedProps);
|
||||
|
||||
$propPatch = new PropPatch([
|
||||
'{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL' => new Href('foo/bar/'),
|
||||
]);
|
||||
$this->backend->propPatch($path, $propPatch);
|
||||
try {
|
||||
$propPatch->commit();
|
||||
} catch (\Throwable $e) {
|
||||
$this->assertInstanceOf(\Sabre\DAV\Exception::class, $e);
|
||||
}
|
||||
|
||||
$storedProps = $this->getProps($this->user->getUID(), $path);
|
||||
$this->assertEquals([], $storedProps);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider deleteProvider
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue