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/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 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 a5833e5175f48..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,10 +185,13 @@ 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() - )); + $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(), + \OC::$server->getURLGenerator() + )); + } } // addressbook plugins 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 {