diff options
Diffstat (limited to 'apps/dav/lib/CalDAV')
-rw-r--r-- | apps/dav/lib/CalDAV/CalendarImpl.php | 30 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/EmbeddedCalDavServer.php | 118 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/EventReader.php | 4 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/Status/StatusService.php | 2 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/UpcomingEventsService.php | 8 |
5 files changed, 145 insertions, 17 deletions
diff --git a/apps/dav/lib/CalDAV/CalendarImpl.php b/apps/dav/lib/CalDAV/CalendarImpl.php index b79bf7ea2d0..5f912da732e 100644 --- a/apps/dav/lib/CalDAV/CalendarImpl.php +++ b/apps/dav/lib/CalDAV/CalendarImpl.php @@ -156,19 +156,15 @@ class CalendarImpl implements ICreateFromString, IHandleImipMessage, ICalendarIs } /** - * Create a new calendar event for this calendar - * by way of an ICS string - * - * @param string $name the file name - needs to contain the .ics ending - * @param string $calendarData a string containing a valid VEVENT ics - * * @throws CalendarException */ - public function createFromString(string $name, string $calendarData): void { - $server = new InvitationResponseServer(false); - + private function createFromStringInServer( + string $name, + string $calendarData, + \OCA\DAV\Connector\Sabre\Server $server, + ): void { /** @var CustomPrincipalPlugin $plugin */ - $plugin = $server->getServer()->getPlugin('auth'); + $plugin = $server->getPlugin('auth'); // we're working around the previous implementation // that only allowed the public system principal to be used // so set the custom principal here @@ -184,14 +180,14 @@ class CalendarImpl implements ICreateFromString, IHandleImipMessage, ICalendarIs // Force calendar change URI /** @var Schedule\Plugin $schedulingPlugin */ - $schedulingPlugin = $server->getServer()->getPlugin('caldav-schedule'); + $schedulingPlugin = $server->getPlugin('caldav-schedule'); $schedulingPlugin->setPathOfCalendarObjectChange($fullCalendarFilename); $stream = fopen('php://memory', 'rb+'); fwrite($stream, $calendarData); rewind($stream); try { - $server->getServer()->createFile($fullCalendarFilename, $stream); + $server->createFile($fullCalendarFilename, $stream); } catch (Conflict $e) { throw new CalendarException('Could not create new calendar event: ' . $e->getMessage(), 0, $e); } finally { @@ -199,6 +195,16 @@ class CalendarImpl implements ICreateFromString, IHandleImipMessage, ICalendarIs } } + public function createFromString(string $name, string $calendarData): void { + $server = new EmbeddedCalDavServer(false); + $this->createFromStringInServer($name, $calendarData, $server->getServer()); + } + + public function createFromStringMinimal(string $name, string $calendarData): void { + $server = new InvitationResponseServer(false); + $this->createFromStringInServer($name, $calendarData, $server->getServer()); + } + /** * @throws CalendarException */ diff --git a/apps/dav/lib/CalDAV/EmbeddedCalDavServer.php b/apps/dav/lib/CalDAV/EmbeddedCalDavServer.php new file mode 100644 index 00000000000..21d8c06fa99 --- /dev/null +++ b/apps/dav/lib/CalDAV/EmbeddedCalDavServer.php @@ -0,0 +1,118 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\CalDAV; + +use OCA\DAV\AppInfo\PluginManager; +use OCA\DAV\CalDAV\Auth\CustomPrincipalPlugin; +use OCA\DAV\CalDAV\Auth\PublicPrincipalPlugin; +use OCA\DAV\CalDAV\Publishing\PublishPlugin; +use OCA\DAV\Connector\Sabre\AnonymousOptionsPlugin; +use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin; +use OCA\DAV\Connector\Sabre\CachingTree; +use OCA\DAV\Connector\Sabre\DavAclPlugin; +use OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin; +use OCA\DAV\Connector\Sabre\LockPlugin; +use OCA\DAV\Connector\Sabre\MaintenancePlugin; +use OCA\DAV\Events\SabrePluginAuthInitEvent; +use OCA\DAV\RootCollection; +use OCA\Theming\ThemingDefaults; +use OCP\App\IAppManager; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\IAppConfig; +use OCP\IConfig; +use OCP\IURLGenerator; +use OCP\L10N\IFactory as IL10NFactory; +use OCP\Server; +use Psr\Log\LoggerInterface; + +class EmbeddedCalDavServer { + private readonly \OCA\DAV\Connector\Sabre\Server $server; + + public function __construct(bool $public = true) { + $baseUri = \OC::$WEBROOT . '/remote.php/dav/'; + $logger = Server::get(LoggerInterface::class); + $dispatcher = Server::get(IEventDispatcher::class); + $appConfig = Server::get(IAppConfig::class); + $l10nFactory = Server::get(IL10NFactory::class); + $l10n = $l10nFactory->get('dav'); + + $root = new RootCollection(); + $this->server = new \OCA\DAV\Connector\Sabre\Server(new CachingTree($root)); + + // Add maintenance plugin + $this->server->addPlugin(new MaintenancePlugin(Server::get(IConfig::class), $l10n)); + + // Set URL explicitly due to reverse-proxy situations + $this->server->httpRequest->setUrl($baseUri); + $this->server->setBaseUri($baseUri); + + $this->server->addPlugin(new BlockLegacyClientPlugin( + Server::get(IConfig::class), + Server::get(ThemingDefaults::class), + )); + $this->server->addPlugin(new AnonymousOptionsPlugin()); + + // allow custom principal uri option + if ($public) { + $this->server->addPlugin(new PublicPrincipalPlugin()); + } else { + $this->server->addPlugin(new CustomPrincipalPlugin()); + } + + // allow setup of additional auth backends + $event = new SabrePluginAuthInitEvent($this->server); + $dispatcher->dispatchTyped($event); + + $this->server->addPlugin(new ExceptionLoggerPlugin('webdav', $logger)); + $this->server->addPlugin(new LockPlugin()); + $this->server->addPlugin(new \Sabre\DAV\Sync\Plugin()); + + // acl + $acl = new DavAclPlugin(); + $acl->principalCollectionSet = [ + 'principals/users', 'principals/groups' + ]; + $this->server->addPlugin($acl); + + // 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(Server::get(IConfig::class), Server::get(LoggerInterface::class), 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())); + $this->server->addPlugin(new PublishPlugin( + Server::get(IConfig::class), + Server::get(IURLGenerator::class) + )); + if ($appConfig->getValueString('dav', 'sendInvitations', 'yes') === 'yes') { + $this->server->addPlugin(Server::get(\OCA\DAV\CalDAV\Schedule\IMipPlugin::class)); + } + + // wait with registering these until auth is handled and the filesystem is setup + $this->server->on('beforeMethod:*', function () use ($root): void { + // register plugins from apps + $pluginManager = new PluginManager( + \OC::$server, + Server::get(IAppManager::class) + ); + foreach ($pluginManager->getAppPlugins() as $appPlugin) { + $this->server->addPlugin($appPlugin); + } + foreach ($pluginManager->getAppCollections() as $appCollection) { + $root->addChild($appCollection); + } + }); + } + + public function getServer(): \OCA\DAV\Connector\Sabre\Server { + return $this->server; + } +} diff --git a/apps/dav/lib/CalDAV/EventReader.php b/apps/dav/lib/CalDAV/EventReader.php index b7dd2889956..ee2b8f33f9a 100644 --- a/apps/dav/lib/CalDAV/EventReader.php +++ b/apps/dav/lib/CalDAV/EventReader.php @@ -46,8 +46,8 @@ class EventReader { 7 => 'July', 8 => 'August', 9 => 'September', 10 => 'October', 11 => 'November', 12 => 'December' ]; protected array $relativePositionNamesMap = [ - 1 => 'First', 2 => 'Second', 3 => 'Third', 4 => 'Fourth', 5 => 'Fifty', - -1 => 'Last', -2 => 'Second Last', -3 => 'Third Last', -4 => 'Fourth Last', -5 => 'Fifty Last' + 1 => 'First', 2 => 'Second', 3 => 'Third', 4 => 'Fourth', 5 => 'Fifth', + -1 => 'Last', -2 => 'Second Last', -3 => 'Third Last', -4 => 'Fourth Last', -5 => 'Fifth Last' ]; /** diff --git a/apps/dav/lib/CalDAV/Status/StatusService.php b/apps/dav/lib/CalDAV/Status/StatusService.php index de19174de58..9ee0e9bf356 100644 --- a/apps/dav/lib/CalDAV/Status/StatusService.php +++ b/apps/dav/lib/CalDAV/Status/StatusService.php @@ -141,7 +141,7 @@ class StatusService { $this->logger->debug("Found $count applicable event(s), changing user status", ['user' => $userId]); $this->userStatusService->setUserStatus( $userId, - IUserStatus::AWAY, + IUserStatus::BUSY, IUserStatus::MESSAGE_CALENDAR_BUSY, true ); diff --git a/apps/dav/lib/CalDAV/UpcomingEventsService.php b/apps/dav/lib/CalDAV/UpcomingEventsService.php index 6614d937ff7..1a8aed5bd71 100644 --- a/apps/dav/lib/CalDAV/UpcomingEventsService.php +++ b/apps/dav/lib/CalDAV/UpcomingEventsService.php @@ -47,7 +47,7 @@ class UpcomingEventsService { $this->userManager->get($userId), ); - return array_map(function (array $event) use ($userId, $calendarAppEnabled) { + return array_filter(array_map(function (array $event) use ($userId, $calendarAppEnabled) { $calendarAppUrl = null; if ($calendarAppEnabled) { @@ -67,6 +67,10 @@ class UpcomingEventsService { $calendarAppUrl = $this->urlGenerator->linkToRouteAbsolute('calendar.view.indexdirect.edit', $arguments); } + if (isset($event['objects'][0]['STATUS']) && $event['objects'][0]['STATUS'][0] === 'CANCELLED') { + return false; + } + return new UpcomingEvent( $event['uri'], ($event['objects'][0]['RECURRENCE-ID'][0] ?? null)?->getTimeStamp(), @@ -76,7 +80,7 @@ class UpcomingEventsService { $event['objects'][0]['LOCATION'][0] ?? null, $calendarAppUrl, ); - }, $events); + }, $events)); } } |