From bb802956a2e3fd1f2d8d229cf4fad5b39f9226fb Mon Sep 17 00:00:00 2001 From: Johannes Merkel Date: Mon, 22 May 2023 15:25:16 +0200 Subject: [PATCH] enh(contacts): show/hide addressbooks for all Signed-off-by: Johannes Merkel --- apps/dav/lib/CardDAV/AddressBook.php | 24 ++++++++------- apps/dav/lib/DAV/CustomPropertiesBackend.php | 15 ++++++++++ .../tests/unit/CardDAV/AddressBookTest.php | 29 ++++++++++++++++--- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/apps/dav/lib/CardDAV/AddressBook.php b/apps/dav/lib/CardDAV/AddressBook.php index e9eec4161cb..b0fb8c8ee5c 100644 --- a/apps/dav/lib/CardDAV/AddressBook.php +++ b/apps/dav/lib/CardDAV/AddressBook.php @@ -46,7 +46,6 @@ use Sabre\DAV\PropPatch; * @property CardDavBackend $carddavBackend */ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable, IMoveTarget { - /** * AddressBook constructor. * @@ -116,7 +115,12 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable, IMov 'privilege' => '{DAV:}write', 'principal' => $this->getOwner(), 'protected' => true, - ] + ], + [ + 'privilege' => '{DAV:}write-properties', + 'principal' => '{DAV:}authenticated', + 'protected' => true, + ], ]; if ($this->getOwner() === 'principals/system/system') { @@ -147,7 +151,7 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable, IMov } $acl = $this->carddavBackend->applyShareAcl($this->getResourceId(), $acl); - $allowedPrincipals = [$this->getOwner(), parent::getOwner(), 'principals/system/system']; + $allowedPrincipals = [$this->getOwner(), parent::getOwner(), 'principals/system/system', '{DAV:}authenticated']; return array_filter($acl, function ($rule) use ($allowedPrincipals) { return \in_array($rule['principal'], $allowedPrincipals, true); }); @@ -166,8 +170,7 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable, IMov return new Card($this->carddavBackend, $this->addressBookInfo, $obj); } - public function getChildren() - { + public function getChildren() { $objs = $this->carddavBackend->getCards($this->addressBookInfo['id']); $children = []; foreach ($objs as $obj) { @@ -178,8 +181,7 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable, IMov return $children; } - public function getMultipleChildren(array $paths) - { + public function getMultipleChildren(array $paths) { $objs = $this->carddavBackend->getMultipleCards($this->addressBookInfo['id'], $paths); $children = []; foreach ($objs as $obj) { @@ -221,10 +223,12 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable, IMov } public function propPatch(PropPatch $propPatch) { - if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) { - throw new Forbidden(); + // shared address books will be handled by + // \OCA\DAV\DAV\CustomPropertiesBackend::propPatch + // to save values in db table instead of dav object + if (!$this->isShared()) { + parent::propPatch($propPatch); } - parent::propPatch($propPatch); } public function getContactsGroups() { diff --git a/apps/dav/lib/DAV/CustomPropertiesBackend.php b/apps/dav/lib/DAV/CustomPropertiesBackend.php index 3bc3ba33173..9de06334611 100644 --- a/apps/dav/lib/DAV/CustomPropertiesBackend.php +++ b/apps/dav/lib/DAV/CustomPropertiesBackend.php @@ -176,6 +176,21 @@ class CustomPropertiesBackend implements BackendInterface { } } + // substr of addressbooks/ => path is inside the CardDAV component + // three '/' => this a addressbook (no addressbook-home nor contact object) + if (str_starts_with($path, 'addressbooks/') && substr_count($path, '/') === 3) { + $allRequestedProps = $propFind->getRequestedProperties(); + $customPropertiesForShares = [ + '{DAV:}displayname', + ]; + + foreach ($customPropertiesForShares as $customPropertyForShares) { + if (in_array($customPropertyForShares, $allRequestedProps, true)) { + $requestedProps[] = $customPropertyForShares; + } + } + } + if (empty($requestedProps)) { return; } diff --git a/apps/dav/tests/unit/CardDAV/AddressBookTest.php b/apps/dav/tests/unit/CardDAV/AddressBookTest.php index 81361d02068..9aa7eb14fff 100644 --- a/apps/dav/tests/unit/CardDAV/AddressBookTest.php +++ b/apps/dav/tests/unit/CardDAV/AddressBookTest.php @@ -29,6 +29,7 @@ namespace OCA\DAV\Tests\unit\CardDAV; use OCA\DAV\CardDAV\AddressBook; use OCA\DAV\CardDAV\Card; use OCA\DAV\CardDAV\CardDavBackend; +use OCA\DAV\DAV\CustomPropertiesBackend; use OCP\IL10N; use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; @@ -101,11 +102,10 @@ class AddressBookTest extends TestCase { } - public function testPropPatch(): void { - $this->expectException(Forbidden::class); - + public function testPropPatchShared(): void { /** @var MockObject | CardDavBackend $backend */ $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock(); + $backend->expects($this->never())->method('updateAddressBook'); $addressBookInfo = [ '{http://owncloud.org/ns}owner-principal' => 'user1', '{DAV:}displayname' => 'Test address book', @@ -116,7 +116,24 @@ class AddressBookTest extends TestCase { $l10n = $this->createMock(IL10N::class); $logger = $this->createMock(LoggerInterface::class); $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger); - $addressBook->propPatch(new PropPatch([])); + $addressBook->propPatch(new PropPatch(['{DAV:}displayname' => 'Test address book'])); + } + + public function testPropPatchNotShared(): void { + /** @var MockObject | CardDavBackend $backend */ + $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock(); + $backend->expects($this->atLeast(1))->method('updateAddressBook'); + $addressBookInfo = [ + '{http://owncloud.org/ns}owner-principal' => 'user1', + '{DAV:}displayname' => 'Test address book', + 'principaluri' => 'user1', + 'id' => 666, + 'uri' => 'default', + ]; + $l10n = $this->createMock(IL10N::class); + $logger = $this->createMock(LoggerInterface::class); + $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger); + $addressBook->propPatch(new PropPatch(['{DAV:}displayname' => 'Test address book'])); } /** @@ -152,6 +169,10 @@ class AddressBookTest extends TestCase { 'privilege' => '{DAV:}write', 'principal' => $hasOwnerSet ? 'user1' : 'user2', 'protected' => true + ], [ + 'privilege' => '{DAV:}write-properties', + 'principal' => '{DAV:}authenticated', + 'protected' => true ]]; if ($hasOwnerSet) { $expectedAcl[] = [ -- 2.39.5