Browse Source

Merge pull request #38397 from nextcloud/enh/contacts/hide-adressbook-option

enh(contacts): show/hide addressbooks for all
Daniel 1 year ago
parent
commit
aa5dcb0952

+ 14 - 10
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() {

+ 15 - 0
apps/dav/lib/DAV/CustomPropertiesBackend.php

@@ -179,6 +179,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;
 		}

+ 25 - 4
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[] = [