aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel <mail@danielkesselberg.de>2024-06-02 22:04:27 +0200
committerGitHub <noreply@github.com>2024-06-02 22:04:27 +0200
commit50b65a3a959ebf7763a06e7d5ab1868498dd3036 (patch)
tree7cf98ecd0ad92a9d9b12a344f5fd3d99b969db3e
parent5bc8329bf389daf21e2cf1d04c49f876f7295ab2 (diff)
parent9bcff76908a73adfed83f499105f41e915d17d63 (diff)
downloadnextcloud-server-50b65a3a959ebf7763a06e7d5ab1868498dd3036.tar.gz
nextcloud-server-50b65a3a959ebf7763a06e7d5ab1868498dd3036.zip
Merge pull request #45232 from nextcloud/backport/44752/stable27
[stable27] Expose subscription calendars
-rw-r--r--apps/dav/composer/composer/autoload_classmap.php2
-rw-r--r--apps/dav/composer/composer/autoload_static.php2
-rw-r--r--apps/dav/lib/AppInfo/Application.php2
-rw-r--r--apps/dav/lib/CalDAV/AppCalendar/AppCalendarPlugin.php2
-rw-r--r--apps/dav/lib/CalDAV/CachedSubscription.php6
-rw-r--r--apps/dav/lib/CalDAV/CachedSubscriptionImpl.php117
-rw-r--r--apps/dav/lib/CalDAV/CachedSubscriptionProvider.php57
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php8
-rw-r--r--apps/dav/lib/CalDAV/CalendarHome.php14
-rw-r--r--apps/dav/lib/CalDAV/CalendarRoot.php13
-rw-r--r--apps/dav/lib/CalDAV/WebcalCaching/Plugin.php20
-rw-r--r--apps/dav/lib/Connector/Sabre/DavAclPlugin.php6
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php96
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php88
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php5
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarHomeTest.php127
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarImplTest.php3
-rw-r--r--apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php51
-rw-r--r--build/integration/features/caldav.feature4
19 files changed, 593 insertions, 30 deletions
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index 83aa8370f89..d3627ee1e26 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -45,7 +45,9 @@ return array(
'OCA\\DAV\\CalDAV\\BirthdayCalendar\\EnablePlugin' => $baseDir . '/../lib/CalDAV/BirthdayCalendar/EnablePlugin.php',
'OCA\\DAV\\CalDAV\\BirthdayService' => $baseDir . '/../lib/CalDAV/BirthdayService.php',
'OCA\\DAV\\CalDAV\\CachedSubscription' => $baseDir . '/../lib/CalDAV/CachedSubscription.php',
+ 'OCA\\DAV\\CalDAV\\CachedSubscriptionImpl' => $baseDir . '/../lib/CalDAV/CachedSubscriptionImpl.php',
'OCA\\DAV\\CalDAV\\CachedSubscriptionObject' => $baseDir . '/../lib/CalDAV/CachedSubscriptionObject.php',
+ 'OCA\\DAV\\CalDAV\\CachedSubscriptionProvider' => $baseDir . '/../lib/CalDAV/CachedSubscriptionProvider.php',
'OCA\\DAV\\CalDAV\\CalDavBackend' => $baseDir . '/../lib/CalDAV/CalDavBackend.php',
'OCA\\DAV\\CalDAV\\Calendar' => $baseDir . '/../lib/CalDAV/Calendar.php',
'OCA\\DAV\\CalDAV\\CalendarHome' => $baseDir . '/../lib/CalDAV/CalendarHome.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index cbf2abe3a4e..6a424ba975a 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -60,7 +60,9 @@ class ComposerStaticInitDAV
'OCA\\DAV\\CalDAV\\BirthdayCalendar\\EnablePlugin' => __DIR__ . '/..' . '/../lib/CalDAV/BirthdayCalendar/EnablePlugin.php',
'OCA\\DAV\\CalDAV\\BirthdayService' => __DIR__ . '/..' . '/../lib/CalDAV/BirthdayService.php',
'OCA\\DAV\\CalDAV\\CachedSubscription' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscription.php',
+ 'OCA\\DAV\\CalDAV\\CachedSubscriptionImpl' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscriptionImpl.php',
'OCA\\DAV\\CalDAV\\CachedSubscriptionObject' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscriptionObject.php',
+ 'OCA\\DAV\\CalDAV\\CachedSubscriptionProvider' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscriptionProvider.php',
'OCA\\DAV\\CalDAV\\CalDavBackend' => __DIR__ . '/..' . '/../lib/CalDAV/CalDavBackend.php',
'OCA\\DAV\\CalDAV\\Calendar' => __DIR__ . '/..' . '/../lib/CalDAV/Calendar.php',
'OCA\\DAV\\CalDAV\\CalendarHome' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarHome.php',
diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php
index 10e1130f907..d543eb2a825 100644
--- a/apps/dav/lib/AppInfo/Application.php
+++ b/apps/dav/lib/AppInfo/Application.php
@@ -36,6 +36,7 @@ use Exception;
use OCA\DAV\BackgroundJob\UpdateCalendarResourcesRoomsBackgroundJob;
use OCA\DAV\CalDAV\Activity\Backend;
use OCA\DAV\CalDAV\AppCalendar\AppCalendarPlugin;
+use OCA\DAV\CalDAV\CachedSubscriptionProvider;
use OCA\DAV\CalDAV\CalendarManager;
use OCA\DAV\CalDAV\CalendarProvider;
use OCA\DAV\CalDAV\Reminder\NotificationProvider\AudioProvider;
@@ -199,6 +200,7 @@ class Application extends App implements IBootstrap {
$context->registerNotifierService(Notifier::class);
$context->registerCalendarProvider(CalendarProvider::class);
+ $context->registerCalendarProvider(CachedSubscriptionProvider::class);
$context->registerUserMigrator(CalendarMigrator::class);
$context->registerUserMigrator(ContactsMigrator::class);
diff --git a/apps/dav/lib/CalDAV/AppCalendar/AppCalendarPlugin.php b/apps/dav/lib/CalDAV/AppCalendar/AppCalendarPlugin.php
index cdf7cb9059a..2666b352496 100644
--- a/apps/dav/lib/CalDAV/AppCalendar/AppCalendarPlugin.php
+++ b/apps/dav/lib/CalDAV/AppCalendar/AppCalendarPlugin.php
@@ -67,7 +67,7 @@ class AppCalendarPlugin implements ICalendarProvider {
return array_values(
array_filter($this->manager->getCalendarsForPrincipal($principalUri, $calendarUris), function ($c) {
// We must not provide a wrapper for DAV calendars
- return ! ($c instanceof \OCA\DAV\CalDAV\CalendarImpl);
+ return ! (($c instanceof \OCA\DAV\CalDAV\CalendarImpl) || ($c instanceof \OCA\DAV\CalDAV\CachedSubscriptionImpl));
})
);
}
diff --git a/apps/dav/lib/CalDAV/CachedSubscription.php b/apps/dav/lib/CalDAV/CachedSubscription.php
index dc7f66e59b4..8dfb8a3f78b 100644
--- a/apps/dav/lib/CalDAV/CachedSubscription.php
+++ b/apps/dav/lib/CalDAV/CachedSubscription.php
@@ -73,6 +73,11 @@ class CachedSubscription extends \Sabre\CalDAV\Calendar {
'principal' => '{DAV:}authenticated',
'protected' => true,
],
+ [
+ 'privilege' => '{DAV:}write-properties',
+ 'principal' => $this->getOwner(),
+ 'protected' => true,
+ ]
];
}
@@ -97,7 +102,6 @@ class CachedSubscription extends \Sabre\CalDAV\Calendar {
'principal' => $this->getOwner() . '/calendar-proxy-read',
'protected' => true,
],
-
];
}
diff --git a/apps/dav/lib/CalDAV/CachedSubscriptionImpl.php b/apps/dav/lib/CalDAV/CachedSubscriptionImpl.php
new file mode 100644
index 00000000000..3406707d0d4
--- /dev/null
+++ b/apps/dav/lib/CalDAV/CachedSubscriptionImpl.php
@@ -0,0 +1,117 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2024 Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @author Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OCA\DAV\CalDAV;
+
+use OCP\Calendar\ICalendar;
+use OCP\Constants;
+
+class CachedSubscriptionImpl implements ICalendar {
+ private CalDavBackend $backend;
+ private CachedSubscription $calendar;
+ /** @var array<string, mixed> */
+ private array $calendarInfo;
+
+ public function __construct(
+ CachedSubscription $calendar,
+ array $calendarInfo,
+ CalDavBackend $backend
+ ) {
+ $this->calendar = $calendar;
+ $this->calendarInfo = $calendarInfo;
+ $this->backend = $backend;
+ }
+
+ /**
+ * @return string defining the technical unique key
+ * @since 13.0.0
+ */
+ public function getKey(): string {
+ return (string) $this->calendarInfo['id'];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getUri(): string {
+ return $this->calendarInfo['uri'];
+ }
+
+ /**
+ * In comparison to getKey() this function returns a human readable (maybe translated) name
+ * @since 13.0.0
+ */
+ public function getDisplayName(): ?string {
+ return $this->calendarInfo['{DAV:}displayname'];
+ }
+
+ /**
+ * Calendar color
+ * @since 13.0.0
+ */
+ public function getDisplayColor(): ?string {
+ return $this->calendarInfo['{http://apple.com/ns/ical/}calendar-color'];
+ }
+
+ /**
+ * @param string $pattern which should match within the $searchProperties
+ * @param array $searchProperties defines the properties within the query pattern should match
+ * @param array $options - optional parameters:
+ * ['timerange' => ['start' => new DateTime(...), 'end' => new DateTime(...)]]
+ * @param int|null $limit - limit number of search results
+ * @param int|null $offset - offset for paging of search results
+ * @return array an array of events/journals/todos which are arrays of key-value-pairs
+ * @since 13.0.0
+ */
+ public function search(string $pattern, array $searchProperties = [], array $options = [], $limit = null, $offset = null): array {
+ return $this->backend->search($this->calendarInfo, $pattern, $searchProperties, $options, $limit, $offset);
+ }
+
+ /**
+ * @return int build up using \OCP\Constants
+ * @since 13.0.0
+ */
+ public function getPermissions(): int {
+ $permissions = $this->calendar->getACL();
+ $result = 0;
+ foreach ($permissions as $permission) {
+ switch ($permission['privilege']) {
+ case '{DAV:}read':
+ $result |= Constants::PERMISSION_READ;
+ break;
+ }
+ }
+
+ return $result;
+ }
+
+ public function isDeleted(): bool {
+ return false;
+ }
+
+ public function getSource(): string {
+ return $this->calendarInfo['source'];
+ }
+}
diff --git a/apps/dav/lib/CalDAV/CachedSubscriptionProvider.php b/apps/dav/lib/CalDAV/CachedSubscriptionProvider.php
new file mode 100644
index 00000000000..e2508af5592
--- /dev/null
+++ b/apps/dav/lib/CalDAV/CachedSubscriptionProvider.php
@@ -0,0 +1,57 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2024 Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @author Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OCA\DAV\CalDAV;
+
+use OCP\Calendar\ICalendarProvider;
+
+class CachedSubscriptionProvider implements ICalendarProvider {
+
+ public function __construct(
+ private CalDavBackend $calDavBackend
+ ) {
+ }
+
+ public function getCalendars(string $principalUri, array $calendarUris = []): array {
+ $calendarInfos = $this->calDavBackend->getSubscriptionsForUser($principalUri);
+
+ if (count($calendarUris) > 0) {
+ $calendarInfos = array_filter($calendarInfos, fn (array $subscription) => in_array($subscription['uri'], $calendarUris));
+ }
+
+ $calendarInfos = array_values(array_filter($calendarInfos));
+
+ $iCalendars = [];
+ foreach ($calendarInfos as $calendarInfo) {
+ $calendar = new CachedSubscription($this->calDavBackend, $calendarInfo);
+ $iCalendars[] = new CachedSubscriptionImpl(
+ $calendar,
+ $calendarInfo,
+ $this->calDavBackend,
+ );
+ }
+ return $iCalendars;
+ }
+}
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index 651483f000c..8890e1d8a95 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -1881,12 +1881,18 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$outerQuery = $this->db->getQueryBuilder();
$innerQuery = $this->db->getQueryBuilder();
+ if (isset($calendarInfo['source'])) {
+ $calendarType = self::CALENDAR_TYPE_SUBSCRIPTION;
+ } else {
+ $calendarType = self::CALENDAR_TYPE_CALENDAR;
+ }
+
$innerQuery->selectDistinct('op.objectid')
->from($this->dbObjectPropertiesTable, 'op')
->andWhere($innerQuery->expr()->eq('op.calendarid',
$outerQuery->createNamedParameter($calendarInfo['id'])))
->andWhere($innerQuery->expr()->eq('op.calendartype',
- $outerQuery->createNamedParameter(self::CALENDAR_TYPE_CALENDAR)));
+ $outerQuery->createNamedParameter($calendarType)));
$outerQuery->select('c.id', 'c.calendardata', 'c.componenttype', 'c.uid', 'c.uri')
->from('calendarobjects', 'c')
diff --git a/apps/dav/lib/CalDAV/CalendarHome.php b/apps/dav/lib/CalDAV/CalendarHome.php
index cbf5cebc9e7..31463bcc678 100644
--- a/apps/dav/lib/CalDAV/CalendarHome.php
+++ b/apps/dav/lib/CalDAV/CalendarHome.php
@@ -53,14 +53,16 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
/** @var PluginManager */
private $pluginManager;
- /** @var bool */
- private $returnCachedSubscriptions = false;
-
/** @var LoggerInterface */
private $logger;
private ?array $cachedChildren = null;
- public function __construct(BackendInterface $caldavBackend, $principalInfo, LoggerInterface $logger) {
+ public function __construct(
+ BackendInterface $caldavBackend,
+ array $principalInfo,
+ LoggerInterface $logger,
+ private bool $returnCachedSubscriptions
+ ) {
parent::__construct($caldavBackend, $principalInfo);
$this->l10n = \OC::$server->getL10N('dav');
$this->config = \OC::$server->getConfig();
@@ -219,8 +221,4 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
$principalUri = $this->principalInfo['uri'];
return $this->caldavBackend->calendarSearch($principalUri, $filters, $limit, $offset);
}
-
- public function enableCachedSubscriptionsForThisRequest() {
- $this->returnCachedSubscriptions = true;
- }
}
diff --git a/apps/dav/lib/CalDAV/CalendarRoot.php b/apps/dav/lib/CalDAV/CalendarRoot.php
index 0c701d9cdcf..bece2087e8a 100644
--- a/apps/dav/lib/CalDAV/CalendarRoot.php
+++ b/apps/dav/lib/CalDAV/CalendarRoot.php
@@ -32,6 +32,8 @@ use Sabre\DAVACL\PrincipalBackend;
class CalendarRoot extends \Sabre\CalDAV\CalendarRoot {
private LoggerInterface $logger;
+ private array $returnCachedSubscriptions = [];
+
public function __construct(
PrincipalBackend\BackendInterface $principalBackend,
Backend\BackendInterface $caldavBackend,
@@ -43,7 +45,12 @@ class CalendarRoot extends \Sabre\CalDAV\CalendarRoot {
}
public function getChildForPrincipal(array $principal) {
- return new CalendarHome($this->caldavBackend, $principal, $this->logger);
+ return new CalendarHome(
+ $this->caldavBackend,
+ $principal,
+ $this->logger,
+ array_key_exists($principal['uri'], $this->returnCachedSubscriptions)
+ );
}
public function getName() {
@@ -56,4 +63,8 @@ class CalendarRoot extends \Sabre\CalDAV\CalendarRoot {
return parent::getName();
}
+
+ public function enableReturnCachedSubscriptions(string $principalUri): void {
+ $this->returnCachedSubscriptions['principals/users/' . $principalUri] = true;
+ }
}
diff --git a/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php b/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php
index 3dd8a7c81e5..e7dea134011 100644
--- a/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php
+++ b/apps/dav/lib/CalDAV/WebcalCaching/Plugin.php
@@ -26,7 +26,7 @@ declare(strict_types=1);
*/
namespace OCA\DAV\CalDAV\WebcalCaching;
-use OCA\DAV\CalDAV\CalendarHome;
+use OCA\DAV\CalDAV\CalendarRoot;
use OCP\IRequest;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\Server;
@@ -71,6 +71,11 @@ class Plugin extends ServerPlugin {
if ($magicHeader === 'On') {
$this->enabled = true;
}
+
+ $isExportRequest = $request->getMethod() === 'GET' && array_key_exists('export', $request->getParams());
+ if ($isExportRequest) {
+ $this->enabled = true;
+ }
}
/**
@@ -85,7 +90,7 @@ class Plugin extends ServerPlugin {
*/
public function initialize(Server $server) {
$this->server = $server;
- $server->on('beforeMethod:*', [$this, 'beforeMethod']);
+ $server->on('beforeMethod:*', [$this, 'beforeMethod'], 15);
}
/**
@@ -103,16 +108,11 @@ class Plugin extends ServerPlugin {
return;
}
- // $calendarHomePath will look like: calendars/username
- $calendarHomePath = $pathParts[0] . '/' . $pathParts[1];
try {
- $calendarHome = $this->server->tree->getNodeForPath($calendarHomePath);
- if (!($calendarHome instanceof CalendarHome)) {
- //how did we end up here?
- return;
+ $calendarRoot = $this->server->tree->getNodeForPath($pathParts[0]);
+ if ($calendarRoot instanceof CalendarRoot) {
+ $calendarRoot->enableReturnCachedSubscriptions($pathParts[1]);
}
-
- $calendarHome->enableCachedSubscriptionsForThisRequest();
} catch (NotFound $ex) {
return;
}
diff --git a/apps/dav/lib/Connector/Sabre/DavAclPlugin.php b/apps/dav/lib/Connector/Sabre/DavAclPlugin.php
index 236ca3da7fa..8e5000fa9fb 100644
--- a/apps/dav/lib/Connector/Sabre/DavAclPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/DavAclPlugin.php
@@ -27,6 +27,8 @@
*/
namespace OCA\DAV\Connector\Sabre;
+use OCA\DAV\CalDAV\CachedSubscription;
+use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CardDAV\AddressBook;
use Sabre\CalDAV\Principal\User;
use Sabre\DAV\Exception\NotFound;
@@ -59,6 +61,10 @@ class DavAclPlugin extends \Sabre\DAVACL\Plugin {
case AddressBook::class:
$type = 'Addressbook';
break;
+ case Calendar::class:
+ case CachedSubscription::class:
+ $type = 'Calendar';
+ break;
default:
$type = 'Node';
break;
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php
new file mode 100644
index 00000000000..1d612585c49
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php
@@ -0,0 +1,96 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2024 Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @author Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\DAV\Tests\unit\CalDAV;
+
+use OCA\DAV\CalDAV\CachedSubscription;
+use OCA\DAV\CalDAV\CachedSubscriptionImpl;
+use OCA\DAV\CalDAV\CalDavBackend;
+use Test\TestCase;
+
+class CachedSubscriptionImplTest extends TestCase {
+ private CachedSubscription $cachedSubscription;
+ private array $cachedSubscriptionInfo;
+ private CachedSubscriptionImpl $cachedSubscriptionImpl;
+ private CalDavBackend $backend;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->cachedSubscription = $this->createMock(CachedSubscription::class);
+ $this->cachedSubscriptionInfo = [
+ 'id' => 'fancy_id_123',
+ '{DAV:}displayname' => 'user readable name 123',
+ '{http://apple.com/ns/ical/}calendar-color' => '#AABBCC',
+ 'uri' => '/this/is/a/uri',
+ 'source' => 'https://test.localhost/calendar1',
+ ];
+ $this->backend = $this->createMock(CalDavBackend::class);
+
+ $this->cachedSubscriptionImpl = new CachedSubscriptionImpl(
+ $this->cachedSubscription,
+ $this->cachedSubscriptionInfo,
+ $this->backend
+ );
+ }
+
+ public function testGetKey(): void {
+ $this->assertEquals($this->cachedSubscriptionImpl->getKey(), 'fancy_id_123');
+ }
+
+ public function testGetDisplayname(): void {
+ $this->assertEquals($this->cachedSubscriptionImpl->getDisplayName(), 'user readable name 123');
+ }
+
+ public function testGetDisplayColor(): void {
+ $this->assertEquals($this->cachedSubscriptionImpl->getDisplayColor(), '#AABBCC');
+ }
+
+ public function testGetSource(): void {
+ $this->assertEquals($this->cachedSubscriptionImpl->getSource(), 'https://test.localhost/calendar1');
+ }
+
+ public function testSearch(): void {
+ $this->backend->expects($this->once())
+ ->method('search')
+ ->with($this->cachedSubscriptionInfo, 'abc', ['def'], ['ghi'], 42, 1337)
+ ->willReturn(['SEARCHRESULTS']);
+
+ $result = $this->cachedSubscriptionImpl->search('abc', ['def'], ['ghi'], 42, 1337);
+ $this->assertEquals($result, ['SEARCHRESULTS']);
+ }
+
+ public function testGetPermissionRead(): void {
+ $this->cachedSubscription->expects($this->once())
+ ->method('getACL')
+ ->with()
+ ->willReturn([
+ ['privilege' => '{DAV:}read']
+ ]);
+
+ $this->assertEquals(1, $this->cachedSubscriptionImpl->getPermissions());
+ }
+}
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php
new file mode 100644
index 00000000000..8331d259ce8
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php
@@ -0,0 +1,88 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2024 Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @author Daniel Kesselberg <mail@danielkesselberg.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\DAV\Tests\unit\CalDAV;
+
+use OCA\DAV\CalDAV\CachedSubscriptionImpl;
+use OCA\DAV\CalDAV\CachedSubscriptionProvider;
+use OCA\DAV\CalDAV\CalDavBackend;
+use Test\TestCase;
+
+class CachedSubscriptionProviderTest extends TestCase {
+
+ private CalDavBackend $backend;
+ private CachedSubscriptionProvider $provider;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->backend = $this->createMock(CalDavBackend::class);
+ $this->backend
+ ->expects(self::once())
+ ->method('getSubscriptionsForUser')
+ ->with('user-principal-123')
+ ->willReturn([
+ [
+ 'id' => 'subscription-1',
+ 'uri' => 'subscription-1',
+ 'principaluris' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-1',
+ // A subscription array has actually more properties.
+ ],
+ [
+ 'id' => 'subscription-2',
+ 'uri' => 'subscription-2',
+ 'principaluri' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-2',
+ // A subscription array has actually more properties.
+ ]
+ ]);
+
+ $this->provider = new CachedSubscriptionProvider($this->backend);
+ }
+
+ public function testGetCalendars() {
+ $calendars = $this->provider->getCalendars(
+ 'user-principal-123',
+ []
+ );
+
+ $this->assertCount(2, $calendars);
+ $this->assertInstanceOf(CachedSubscriptionImpl::class, $calendars[0]);
+ $this->assertInstanceOf(CachedSubscriptionImpl::class, $calendars[1]);
+ }
+
+ public function testGetCalendarsFilterByUri() {
+ $calendars = $this->provider->getCalendars(
+ 'user-principal-123',
+ ['subscription-1']
+ );
+
+ $this->assertCount(1, $calendars);
+ $this->assertInstanceOf(CachedSubscriptionImpl::class, $calendars[0]);
+ $this->assertEquals('subscription-1', $calendars[0]->getUri());
+ }
+}
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
index 254c3199472..285609496a7 100644
--- a/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
@@ -61,6 +61,11 @@ class CachedSubscriptionTest extends \Test\TestCase {
'principal' => '{DAV:}authenticated',
'protected' => true,
],
+ [
+ 'privilege' => '{DAV:}write-properties',
+ 'principal' => 'user1',
+ 'protected' => 'true'
+ ]
], $calendar->getACL());
}
diff --git a/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php b/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
index 50430029c61..bc3082ac0ad 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
@@ -26,6 +26,7 @@
namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\AppInfo\PluginManager;
+use OCA\DAV\CalDAV\CachedSubscription;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\CalendarHome;
use OCA\DAV\CalDAV\Integration\ExternalCalendar;
@@ -35,6 +36,7 @@ use OCA\DAV\CalDAV\Trashbin\TrashbinHome;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\CalDAV\Schedule\Inbox;
+use Sabre\CalDAV\Subscriptions\Subscription;
use Sabre\DAV\MkCol;
use Test\TestCase;
@@ -68,7 +70,8 @@ class CalendarHomeTest extends TestCase {
$this->calendarHome = new CalendarHome(
$this->backend,
$this->principalInfo,
- $this->logger
+ $this->logger,
+ false
);
// Replace PluginManager with our mock
@@ -249,4 +252,126 @@ class CalendarHomeTest extends TestCase {
$actual = $this->calendarHome->getChild('app-generated--calendar_plugin_2--calendar-uri-from-backend');
$this->assertEquals($externalCalendarMock, $actual);
}
+
+ public function testGetChildrenSubscriptions(): void {
+ $this->backend
+ ->expects(self::once())
+ ->method('getCalendarsForUser')
+ ->with('user-principal-123')
+ ->willReturn([]);
+
+ $this->backend
+ ->expects(self::once())
+ ->method('getSubscriptionsForUser')
+ ->with('user-principal-123')
+ ->willReturn([
+ [
+ 'id' => 'subscription-1',
+ 'uri' => 'subscription-1',
+ 'principaluri' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-1',
+ // A subscription array has actually more properties.
+ ],
+ [
+ 'id' => 'subscription-2',
+ 'uri' => 'subscription-2',
+ 'principaluri' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-2',
+ // A subscription array has actually more properties.
+ ]
+ ]);
+
+ /*
+ * @FIXME: PluginManager should be injected via constructor.
+ */
+
+ $pluginManager = $this->createMock(PluginManager::class);
+ $pluginManager
+ ->expects(self::once())
+ ->method('getCalendarPlugins')
+ ->with()
+ ->willReturn([]);
+
+ $calendarHome = new CalendarHome(
+ $this->backend,
+ $this->principalInfo,
+ $this->logger,
+ false
+ );
+
+ $reflection = new \ReflectionClass($calendarHome);
+ $reflectionProperty = $reflection->getProperty('pluginManager');
+ $reflectionProperty->setAccessible(true);
+ $reflectionProperty->setValue($calendarHome, $pluginManager);
+
+ $actual = $calendarHome->getChildren();
+
+ $this->assertCount(5, $actual);
+ $this->assertInstanceOf(Inbox::class, $actual[0]);
+ $this->assertInstanceOf(Outbox::class, $actual[1]);
+ $this->assertInstanceOf(TrashbinHome::class, $actual[2]);
+ $this->assertInstanceOf(Subscription::class, $actual[3]);
+ $this->assertInstanceOf(Subscription::class, $actual[4]);
+ }
+
+ public function testGetChildrenCachedSubscriptions(): void {
+ $this->backend
+ ->expects(self::once())
+ ->method('getCalendarsForUser')
+ ->with('user-principal-123')
+ ->willReturn([]);
+
+ $this->backend
+ ->expects(self::once())
+ ->method('getSubscriptionsForUser')
+ ->with('user-principal-123')
+ ->willReturn([
+ [
+ 'id' => 'subscription-1',
+ 'uri' => 'subscription-1',
+ 'principaluris' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-1',
+ // A subscription array has actually more properties.
+ ],
+ [
+ 'id' => 'subscription-2',
+ 'uri' => 'subscription-2',
+ 'principaluri' => 'user-principal-123',
+ 'source' => 'https://localhost/subscription-2',
+ // A subscription array has actually more properties.
+ ]
+ ]);
+
+ /*
+ * @FIXME: PluginManager should be injected via constructor.
+ */
+
+ $pluginManager = $this->createMock(PluginManager::class);
+ $pluginManager
+ ->expects(self::once())
+ ->method('getCalendarPlugins')
+ ->with()
+ ->willReturn([]);
+
+ $calendarHome = new CalendarHome(
+ $this->backend,
+ $this->principalInfo,
+ $this->logger,
+ true
+ );
+
+ $reflection = new \ReflectionClass($calendarHome);
+ $reflectionProperty = $reflection->getProperty('pluginManager');
+ $reflectionProperty->setAccessible(true);
+ $reflectionProperty->setValue($calendarHome, $pluginManager);
+
+ $actual = $calendarHome->getChildren();
+
+ $this->assertCount(5, $actual);
+ $this->assertInstanceOf(Inbox::class, $actual[0]);
+ $this->assertInstanceOf(Outbox::class, $actual[1]);
+ $this->assertInstanceOf(TrashbinHome::class, $actual[2]);
+ $this->assertInstanceOf(CachedSubscription::class, $actual[3]);
+ $this->assertInstanceOf(CachedSubscription::class, $actual[4]);
+ }
}
diff --git a/apps/dav/tests/unit/CalDAV/CalendarImplTest.php b/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
index 132526e604f..85f2b1aedaf 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
@@ -39,9 +39,6 @@ use Sabre\VObject\Component\VEvent;
use Sabre\VObject\ITip\Message;
use Sabre\VObject\Reader;
-/**
- * @group DB
- */
class CalendarImplTest extends \Test\TestCase {
/** @var CalendarImpl */
private $calendarImpl;
diff --git a/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php b/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
index c99a859ac16..f3f74d00cdc 100644
--- a/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
@@ -44,17 +44,64 @@ class PluginTest extends \Test\TestCase {
$this->assertEquals(false, $plugin->isCachingEnabledForThisRequest());
}
- public function testEnabled(): void {
+ public function testEnabledUserAgent(): void {
$request = $this->createMock(IRequest::class);
$request->expects($this->once())
->method('isUserAgent')
->with(Plugin::ENABLE_FOR_CLIENTS)
- ->willReturn(false);
+ ->willReturn(true);
+ $request->expects($this->once())
+ ->method('getHeader')
+ ->with('X-NC-CalDAV-Webcal-Caching')
+ ->willReturn('');
+ $request->expects($this->once())
+ ->method('getMethod')
+ ->willReturn('REPORT');
+ $request->expects($this->never())
+ ->method('getParams');
+
+ $plugin = new Plugin($request);
+ $this->assertEquals(true, $plugin->isCachingEnabledForThisRequest());
+ }
+
+ public function testEnabledWebcalCachingHeader(): void {
+ $request = $this->createMock(IRequest::class);
+ $request->expects($this->once())
+ ->method('isUserAgent')
+ ->with(Plugin::ENABLE_FOR_CLIENTS)
+ ->willReturn(false);
$request->expects($this->once())
->method('getHeader')
->with('X-NC-CalDAV-Webcal-Caching')
->willReturn('On');
+ $request->expects($this->once())
+ ->method('getMethod')
+ ->willReturn('REPORT');
+ $request->expects($this->never())
+ ->method('getParams');
+
+ $plugin = new Plugin($request);
+
+ $this->assertEquals(true, $plugin->isCachingEnabledForThisRequest());
+ }
+
+ public function testEnabledExportRequest(): void {
+ $request = $this->createMock(IRequest::class);
+ $request->expects($this->once())
+ ->method('isUserAgent')
+ ->with(Plugin::ENABLE_FOR_CLIENTS)
+ ->willReturn(false);
+ $request->expects($this->once())
+ ->method('getHeader')
+ ->with('X-NC-CalDAV-Webcal-Caching')
+ ->willReturn('');
+ $request->expects($this->once())
+ ->method('getMethod')
+ ->willReturn('GET');
+ $request->expects($this->once())
+ ->method('getParams')
+ ->willReturn(['export' => '']);
$plugin = new Plugin($request);
diff --git a/build/integration/features/caldav.feature b/build/integration/features/caldav.feature
index e2cb4f8dc92..fffdd89d367 100644
--- a/build/integration/features/caldav.feature
+++ b/build/integration/features/caldav.feature
@@ -13,7 +13,7 @@ Feature: caldav
When "user0" requests calendar "admin/MyCalendar" on the endpoint "/remote.php/dav/calendars/"
Then The CalDAV HTTP status code should be "404"
And The exception is "Sabre\DAV\Exception\NotFound"
- And The error message is "Node with name 'MyCalendar' could not be found"
+ And The error message is "Calendar with name 'MyCalendar' could not be found"
Scenario: Accessing a not shared calendar of another user via the legacy endpoint
Given user "user0" exists
@@ -22,7 +22,7 @@ Feature: caldav
When "user0" requests calendar "admin/MyCalendar" on the endpoint "/remote.php/caldav/calendars/"
Then The CalDAV HTTP status code should be "404"
And The exception is "Sabre\DAV\Exception\NotFound"
- And The error message is "Node with name 'MyCalendar' could not be found"
+ And The error message is "Calendar with name 'MyCalendar' could not be found"
Scenario: Accessing a not existing calendar of another user
Given user "user0" exists