diff --git a/build/integration/dav_features/caldav-delegation.feature b/build/integration/dav_features/caldav-delegation.feature new file mode 100644 index 0000000000000..d4cc781f320e6 --- /dev/null +++ b/build/integration/dav_features/caldav-delegation.feature @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +Feature: calendar delegation + Calendar delegation grants another user/principal control of a calendar account, + including all calendars the delegator can access. + + @caldav-delegation + Scenario: admin grants user0 read access to her calendar account + Given user "admin" exists + And user "user0" exists + When "admin" updates property "{DAV:}group-member-set" to href "/remote.php/dav/principals/users/user0" of principal "users/admin/calendar-proxy-read" on the endpoint "/remote.php/dav/principals/" + Then The CalDAV response should be multi status + And The CalDAV response should contain an href "/remote.php/dav/principals/users/admin/calendar-proxy-read" + And The CalDAV response should contain a property "{DAV:}group-member-set" + + @caldav-delegation + Scenario: admin grants write access to her calendar account + Given user "admin" exists + And user "user0" exists + When "admin" updates property "{DAV:}group-member-set" to href "/remote.php/dav/principals/users/user0" of principal "users/admin/calendar-proxy-write" on the endpoint "/remote.php/dav/principals/" + Then The CalDAV response should be multi status + And The CalDAV response should contain an href "/remote.php/dav/principals/users/admin/calendar-proxy-write" + And The CalDAV response should contain a property "{DAV:}group-member-set" \ No newline at end of file diff --git a/build/integration/features/bootstrap/CalDavContext.php b/build/integration/features/bootstrap/CalDavContext.php index 9e6b139f374b0..c1203a5b7b926 100644 --- a/build/integration/features/bootstrap/CalDavContext.php +++ b/build/integration/features/bootstrap/CalDavContext.php @@ -42,21 +42,39 @@ public function setUpScenario() { /** @AfterScenario */ public function afterScenario() { - $davUrl = $this->baseUrl. '/remote.php/dav/calendars/admin/MyCalendar'; - try { - $this->client->delete( - $davUrl, - [ - 'auth' => [ - 'admin', - 'admin', - ], - 'headers' => [ - 'X-NC-CalDAV-No-Trashbin' => '1', + foreach (['MyCalendar', 'MyCalendar2'] as $calendarName) { + try { + $this->client->delete( + $this->baseUrl . '/remote.php/dav/calendars/admin/' . $calendarName, + [ + 'auth' => ['admin', 'admin'], + 'headers' => ['X-NC-CalDAV-No-Trashbin' => '1'], ] - ] - ); - } catch (\GuzzleHttp\Exception\ClientException $e) { + ); + } catch (\GuzzleHttp\Exception\ClientException $e) { + } + } + } + + /** @AfterScenario @caldav-delegation */ + public function afterDelegationScenario() { + foreach (['calendar-proxy-read', 'calendar-proxy-write'] as $proxyType) { + try { + $propPatch = new \Sabre\DAV\Xml\Request\PropPatch(); + $propPatch->properties = ['{DAV:}group-member-set' => new \Sabre\DAV\Xml\Property\Href([])]; + $xml = new \Sabre\Xml\Service(); + $body = $xml->write('{DAV:}propertyupdate', $propPatch, '/'); + $this->client->request( + 'PROPPATCH', + $this->baseUrl . '/remote.php/dav/principals/users/admin/' . $proxyType, + [ + 'headers' => ['Content-Type' => 'application/xml; charset=UTF-8'], + 'body' => $body, + 'auth' => ['admin', 'admin'], + ] + ); + } catch (\GuzzleHttp\Exception\ClientException $e) { + } } } @@ -174,6 +192,26 @@ public function theCaldavResponseShouldContainAPropertyWithHrefValue( } } + /** + * @Then The CalDAV response should contain an href :href + * @throws \Exception + */ + public function theCaldavResponseShouldContainAnHref(string $href): void { + /** @var \Sabre\DAV\Xml\Response\MultiStatus $multiStatus */ + $multiStatus = $this->responseXml['value']; + foreach ($multiStatus->getResponses() as $response) { + if ($response->getHref() === $href) { + return; + } + } + throw new \Exception( + sprintf( + 'Expected href %s not found in response', + $href, + ) + ); + } + /** * @Then The CalDAV response should be multi status * @throws \Exception