From f9312591081cefe3401191a6a064a10c1659d677 Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Sat, 1 Oct 2022 23:43:43 +0200 Subject: [PATCH 1/3] Disable sharing calendars via link when sharik via link is disabled This mod disallows sharing calendars via link when `shareapi_allow_links` is disabled. Related: https://github.com/nextcloud/calendar/issues/525 Related: https://github.com/nextcloud/calendar/issues/4399 Author-Change-Id: IB#1126264 Signed-off-by: Pawel Boguslawski --- apps/dav/lib/CalDAV/CalDavBackend.php | 9 +++++++++ apps/dav/lib/CalDAV/Publishing/PublishPlugin.php | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index a894b65d75604..9bd776b293174 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -3,6 +3,7 @@ * @copyright Copyright (c) 2016, ownCloud, Inc. * @copyright Copyright (c) 2018 Georg Ehrke * @copyright Copyright (c) 2020, leith abdulla () + * @copyright Copyright (c) 2022 Informatyka Boguslawski sp. z o.o. sp.k., http://www.ib.pl/ * * @author Chih-Hsuan Yen * @author Christoph Wurst @@ -497,6 +498,10 @@ public function getUsersOwnCalendars($principalUri) { * @return array */ public function getPublicCalendars() { + // Sharing via link must be enabled. + if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'no' ) { + return array_values([]); + } $fields = array_column($this->propertyMap, 0); $fields[] = 'a.id'; $fields[] = 'a.uri'; @@ -555,6 +560,10 @@ public function getPublicCalendars() { * @throws NotFound */ public function getPublicCalendar($uri) { + // Sharing via link must be enabled. + if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'no' ) { + throw new NotFound('Node with name \'' . $uri . '\' could not be found'); + } $fields = array_column($this->propertyMap, 0); $fields[] = 'a.id'; $fields[] = 'a.uri'; diff --git a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php index aabf78da1aa8b..e0078fa1fefd6 100644 --- a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php +++ b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php @@ -1,6 +1,7 @@ + * @copyright Copyright (c) 2022 Informatyka Boguslawski sp. z o.o. sp.k., http://www.ib.pl/ * * @author Christoph Wurst * @author Georg Ehrke @@ -205,6 +206,11 @@ public function httpPost(RequestInterface $request, ResponseInterface $response) } } + // Sharing via link must be enabled. + if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'no') { + return; + } + $node->setPublishStatus(true); // iCloud sends back the 202, so we will too. From bbaf2af41617deca82c99fddd3151b847f00fa9a Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Fri, 14 Oct 2022 13:18:04 +0200 Subject: [PATCH 2/3] Disable sharing calendars via link adjusted Fixes: 45eefc221d4439c99fd2c8badfe93dc3af40f028 Related: https://github.com/nextcloud/server/pull/34372 Author-Change-Id: IB#1126264 Signed-off-by: Pawel Boguslawski --- apps/dav/lib/CalDAV/CalDavBackend.php | 9 --------- apps/dav/lib/CalDAV/PublicCalendarRoot.php | 6 ++++++ apps/dav/lib/CalDAV/Publishing/PublishPlugin.php | 6 ------ apps/dav/lib/Server.php | 10 ++++++---- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index 9bd776b293174..a894b65d75604 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -3,7 +3,6 @@ * @copyright Copyright (c) 2016, ownCloud, Inc. * @copyright Copyright (c) 2018 Georg Ehrke * @copyright Copyright (c) 2020, leith abdulla () - * @copyright Copyright (c) 2022 Informatyka Boguslawski sp. z o.o. sp.k., http://www.ib.pl/ * * @author Chih-Hsuan Yen * @author Christoph Wurst @@ -498,10 +497,6 @@ public function getUsersOwnCalendars($principalUri) { * @return array */ public function getPublicCalendars() { - // Sharing via link must be enabled. - if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'no' ) { - return array_values([]); - } $fields = array_column($this->propertyMap, 0); $fields[] = 'a.id'; $fields[] = 'a.uri'; @@ -560,10 +555,6 @@ public function getPublicCalendars() { * @throws NotFound */ public function getPublicCalendar($uri) { - // Sharing via link must be enabled. - if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'no' ) { - throw new NotFound('Node with name \'' . $uri . '\' could not be found'); - } $fields = array_column($this->propertyMap, 0); $fields[] = 'a.id'; $fields[] = 'a.uri'; diff --git a/apps/dav/lib/CalDAV/PublicCalendarRoot.php b/apps/dav/lib/CalDAV/PublicCalendarRoot.php index 4f7dfea268227..1d20f505773a1 100644 --- a/apps/dav/lib/CalDAV/PublicCalendarRoot.php +++ b/apps/dav/lib/CalDAV/PublicCalendarRoot.php @@ -1,6 +1,7 @@ * @author Georg Ehrke @@ -29,6 +30,7 @@ use OCP\IL10N; use Psr\Log\LoggerInterface; use Sabre\DAV\Collection; +use Sabre\DAV\Exception\Forbidden; class PublicCalendarRoot extends Collection { @@ -70,6 +72,10 @@ public function getName() { * @inheritdoc */ public function getChild($name) { + // Sharing via link is allowed by default, but if the option is set it should be checked. + if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'no' ) { + throw new \Sabre\DAV\Exception\Forbidden(); + } $calendar = $this->caldavBackend->getPublicCalendar($name); return new PublicCalendar($this->caldavBackend, $calendar, $this->l10n, $this->config, $this->logger); } diff --git a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php index e0078fa1fefd6..aabf78da1aa8b 100644 --- a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php +++ b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php @@ -1,7 +1,6 @@ - * @copyright Copyright (c) 2022 Informatyka Boguslawski sp. z o.o. sp.k., http://www.ib.pl/ * * @author Christoph Wurst * @author Georg Ehrke @@ -206,11 +205,6 @@ public function httpPost(RequestInterface $request, ResponseInterface $response) } } - // Sharing via link must be enabled. - if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'no') { - return; - } - $node->setPublishStatus(true); // iCloud sends back the 202, so we will too. diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index a5833e5175f48..1a8f7058e92a9 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -184,10 +184,12 @@ public function __construct(IRequest $request, string $baseUri) { $this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin()); $this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest(), \OC::$server->getConfig())); - $this->server->addPlugin(new \OCA\DAV\CalDAV\Publishing\PublishPlugin( - \OC::$server->getConfig(), - \OC::$server->getURLGenerator() - )); + if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes') { + $this->server->addPlugin(new \OCA\DAV\CalDAV\Publishing\PublishPlugin( + \OC::$server->getConfig(), + \OC::$server->getURLGenerator() + )); + } } // addressbook plugins From 7f87ac8d6dea7ef79d3681b42002910276ed82a9 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Fri, 28 Oct 2022 19:58:44 +0200 Subject: [PATCH 3/3] Extract cs:allowed-sharing-modes into it's own plugin So that it's still there when we disable the PublishPlugin Signed-off-by: Thomas Citharel --- .../composer/composer/autoload_classmap.php | 1 + .../dav/composer/composer/autoload_static.php | 1 + .../InvitationResponseServer.php | 2 + .../lib/CalDAV/Publishing/PublishPlugin.php | 48 ++------- apps/dav/lib/CalDAV/SharingPlugin.php | 102 ++++++++++++++++++ apps/dav/lib/Server.php | 2 + .../unit/CalDAV/Publishing/PublishingTest.php | 13 ++- 7 files changed, 120 insertions(+), 49 deletions(-) create mode 100644 apps/dav/lib/CalDAV/SharingPlugin.php diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index ce98cece3a192..43e8e3240d7d9 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -92,6 +92,7 @@ 'OCA\\DAV\\CalDAV\\Search\\Xml\\Filter\\PropFilter' => $baseDir . '/../lib/CalDAV/Search/Xml/Filter/PropFilter.php', 'OCA\\DAV\\CalDAV\\Search\\Xml\\Filter\\SearchTermFilter' => $baseDir . '/../lib/CalDAV/Search/Xml/Filter/SearchTermFilter.php', 'OCA\\DAV\\CalDAV\\Search\\Xml\\Request\\CalendarSearchReport' => $baseDir . '/../lib/CalDAV/Search/Xml/Request/CalendarSearchReport.php', + 'OCA\\DAV\\CalDAV\\SharingPlugin' => $baseDir . '/../lib/CalDAV/SharingPlugin.php', 'OCA\\DAV\\CalDAV\\Trashbin\\DeletedCalendarObject' => $baseDir . '/../lib/CalDAV/Trashbin/DeletedCalendarObject.php', 'OCA\\DAV\\CalDAV\\Trashbin\\DeletedCalendarObjectsCollection' => $baseDir . '/../lib/CalDAV/Trashbin/DeletedCalendarObjectsCollection.php', 'OCA\\DAV\\CalDAV\\Trashbin\\Plugin' => $baseDir . '/../lib/CalDAV/Trashbin/Plugin.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index a5a7d34d128d4..41576e59161c3 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -107,6 +107,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\CalDAV\\Search\\Xml\\Filter\\PropFilter' => __DIR__ . '/..' . '/../lib/CalDAV/Search/Xml/Filter/PropFilter.php', 'OCA\\DAV\\CalDAV\\Search\\Xml\\Filter\\SearchTermFilter' => __DIR__ . '/..' . '/../lib/CalDAV/Search/Xml/Filter/SearchTermFilter.php', 'OCA\\DAV\\CalDAV\\Search\\Xml\\Request\\CalendarSearchReport' => __DIR__ . '/..' . '/../lib/CalDAV/Search/Xml/Request/CalendarSearchReport.php', + 'OCA\\DAV\\CalDAV\\SharingPlugin' => __DIR__ . '/..' . '/../lib/CalDAV/SharingPlugin.php', 'OCA\\DAV\\CalDAV\\Trashbin\\DeletedCalendarObject' => __DIR__ . '/..' . '/../lib/CalDAV/Trashbin/DeletedCalendarObject.php', 'OCA\\DAV\\CalDAV\\Trashbin\\DeletedCalendarObjectsCollection' => __DIR__ . '/..' . '/../lib/CalDAV/Trashbin/DeletedCalendarObjectsCollection.php', 'OCA\\DAV\\CalDAV\\Trashbin\\Plugin' => __DIR__ . '/..' . '/../lib/CalDAV/Trashbin/Plugin.php', diff --git a/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php b/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php index e92eae2d3f173..79eb7c47d3a06 100644 --- a/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php +++ b/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php @@ -35,6 +35,7 @@ use OCA\DAV\Events\SabrePluginAuthInitEvent; use OCA\DAV\RootCollection; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IConfig; use Psr\Log\LoggerInterface; use Sabre\VObject\ITip\Message; @@ -93,6 +94,7 @@ public function __construct(bool $public = true) { $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 \OCA\DAV\CalDAV\SharingPlugin(\OC::$server->get(IConfig::class))); $this->server->addPlugin(new \OCA\DAV\CalDAV\Publishing\PublishPlugin( \OC::$server->getConfig(), \OC::$server->getURLGenerator() diff --git a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php index aabf78da1aa8b..d669854daf871 100644 --- a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php +++ b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php @@ -31,7 +31,6 @@ use OCA\DAV\CalDAV\Publishing\Xml\Publisher; use OCP\IConfig; use OCP\IURLGenerator; -use Sabre\CalDAV\Xml\Property\AllowedSharingModes; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\INode; use Sabre\DAV\PropFind; @@ -43,33 +42,10 @@ class PublishPlugin extends ServerPlugin { public const NS_CALENDARSERVER = 'http://calendarserver.org/ns/'; - /** - * Reference to SabreDAV server object. - * - * @var \Sabre\DAV\Server - */ - protected $server; - - /** - * Config instance to get instance secret. - * - * @var IConfig - */ - protected $config; + protected Server $server; + protected IConfig $config; + protected IURLGenerator $urlGenerator; - /** - * URL Generator for absolute URLs. - * - * @var IURLGenerator - */ - protected $urlGenerator; - - /** - * PublishPlugin constructor. - * - * @param IConfig $config - * @param IURLGenerator $urlGenerator - */ public function __construct(IConfig $config, IURLGenerator $urlGenerator) { $this->config = $config; $this->urlGenerator = $urlGenerator; @@ -83,9 +59,9 @@ public function __construct(IConfig $config, IURLGenerator $urlGenerator) { * * @return string[] */ - public function getFeatures() { + public function getFeatures(): array { // May have to be changed to be detected - return ['oc-calendar-publishing', 'calendarserver-sharing']; + return ['oc-calendar-publishing']; } /** @@ -96,7 +72,7 @@ public function getFeatures() { * * @return string */ - public function getPluginName() { + public function getPluginName(): string { return 'oc-calendar-publishing'; } @@ -128,18 +104,6 @@ public function propFind(PropFind $propFind, INode $node) { return new Publisher($publishUrl, true); } }); - - $propFind->handle('{'.self::NS_CALENDARSERVER.'}allowed-sharing-modes', function () use ($node) { - $canShare = (!$node->isSubscription() && $node->canWrite()); - $canPublish = (!$node->isSubscription() && $node->canWrite()); - - if ($this->config->getAppValue('dav', 'limitAddressBookAndCalendarSharingToOwner', 'no') === 'yes') { - $canShare = $canShare && ($node->getOwner() === $node->getPrincipalURI()); - $canPublish = $canPublish && ($node->getOwner() === $node->getPrincipalURI()); - } - - return new AllowedSharingModes($canShare, $canPublish); - }); } } diff --git a/apps/dav/lib/CalDAV/SharingPlugin.php b/apps/dav/lib/CalDAV/SharingPlugin.php new file mode 100644 index 0000000000000..3a8ca05ef2513 --- /dev/null +++ b/apps/dav/lib/CalDAV/SharingPlugin.php @@ -0,0 +1,102 @@ + + * + * @author Thomas Citharel + * + * @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 . + * + */ +namespace OCA\DAV\CalDAV; + +use OCP\IConfig; +use Sabre\CalDAV\Xml\Property\AllowedSharingModes; +use Sabre\DAV\INode; +use Sabre\DAV\PropFind; +use Sabre\DAV\Server; +use Sabre\DAV\ServerPlugin; + +class SharingPlugin extends ServerPlugin { + public const NS_CALENDARSERVER = 'http://calendarserver.org/ns/'; + + protected Server $server; + protected IConfig $config; + + public function __construct(IConfig $config) { + $this->config = $config; + } + + /** + * This method should return a list of server-features. + * + * This is for example 'versioning' and is added to the DAV: header + * in an OPTIONS response. + * + * @return string[] + */ + public function getFeatures(): array { + // May have to be changed to be detected + return ['calendarserver-sharing']; + } + + /** + * Returns a plugin name. + * + * Using this name other plugins will be able to access other plugins + * using Sabre\DAV\Server::getPlugin + * + * @return string + */ + public function getPluginName(): string { + return 'oc-calendar-sharing'; + } + + /** + * This initializes the plugin. + * + * This function is called by Sabre\DAV\Server, after + * addPlugin is called. + * + * This method should set up the required event subscriptions. + * + * @param Server $server + */ + public function initialize(Server $server) { + $this->server = $server; + + $this->server->on('propFind', [$this, 'propFind']); + } + + public function propFind(PropFind $propFind, INode $node) { + if ($node instanceof Calendar) { + $propFind->handle('{'.self::NS_CALENDARSERVER.'}allowed-sharing-modes', function () use ($node) { + $canShare = (!$node->isSubscription() && $node->canWrite()); + $canPublish = (!$node->isSubscription() && $node->canWrite()); + + if ($this->config->getAppValue('dav', 'limitAddressBookAndCalendarSharingToOwner', 'no') === 'yes') { + $canShare = $canShare && ($node->getOwner() === $node->getPrincipalURI()); + $canPublish = $canPublish && ($node->getOwner() === $node->getPrincipalURI()); + } + + if ($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') { + $canPublish = false; + } + + return new AllowedSharingModes($canShare, $canPublish); + }); + } + } +} diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index 1a8f7058e92a9..4f03ad04bdf75 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -74,6 +74,7 @@ use OCP\AppFramework\Http\Response; use OCP\Diagnostics\IEventLogger; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IConfig; use OCP\IRequest; use OCP\Profiler\IProfiler; use OCP\SabrePluginEvent; @@ -184,6 +185,7 @@ public function __construct(IRequest $request, string $baseUri) { $this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin()); $this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest(), \OC::$server->getConfig())); + $this->server->addPlugin(new \OCA\DAV\CalDAV\SharingPlugin(\OC::$server->get(IConfig::class))); if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes') { $this->server->addPlugin(new \OCA\DAV\CalDAV\Publishing\PublishPlugin( \OC::$server->getConfig(), diff --git a/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php b/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php index 1367b2741e64e..91e93959e644e 100644 --- a/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php +++ b/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php @@ -30,6 +30,7 @@ use OCP\IConfig; use OCP\IRequest; use OCP\IURLGenerator; +use PHPUnit\Framework\MockObject\MockObject; use Sabre\DAV\Server; use Sabre\DAV\SimpleCollection; use Sabre\HTTP\Request; @@ -38,15 +39,13 @@ class PublishingTest extends TestCase { - /** @var PublishPlugin */ - private $plugin; - /** @var Server */ - private $server; - /** @var Calendar | \PHPUnit\Framework\MockObject\MockObject */ + private PublishPlugin $plugin; + private Server $server; + /** @var Calendar | MockObject */ private $book; - /** @var IConfig | \PHPUnit\Framework\MockObject\MockObject */ + /** @var IConfig | MockObject */ private $config; - /** @var IURLGenerator | \PHPUnit\Framework\MockObject\MockObject */ + /** @var IURLGenerator | MockObject */ private $urlGenerator; protected function setUp(): void {