diff options
Diffstat (limited to 'apps/dav/lib/CardDAV/AddressBook.php')
-rw-r--r-- | apps/dav/lib/CardDAV/AddressBook.php | 133 |
1 files changed, 81 insertions, 52 deletions
diff --git a/apps/dav/lib/CardDAV/AddressBook.php b/apps/dav/lib/CardDAV/AddressBook.php index 9bd24bedbac..4d30d507a7d 100644 --- a/apps/dav/lib/CardDAV/AddressBook.php +++ b/apps/dav/lib/CardDAV/AddressBook.php @@ -1,47 +1,31 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Georg Ehrke <oc.list@georgehrke.com> - * @author Joas Schilling <coding@schilljs.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace OCA\DAV\CardDAV; use OCA\DAV\DAV\Sharing\IShareable; -use OCA\DAV\Exception\UnsupportedLimitOnInitialSyncException; +use OCP\DB\Exception; use OCP\IL10N; +use OCP\Server; +use Psr\Log\LoggerInterface; use Sabre\CardDAV\Backend\BackendInterface; -use Sabre\CardDAV\Card; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\IMoveTarget; +use Sabre\DAV\INode; use Sabre\DAV\PropPatch; /** * Class AddressBook * * @package OCA\DAV\CardDAV - * @property BackendInterface|CardDavBackend $carddavBackend + * @property CardDavBackend $carddavBackend */ -class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { - +class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable, IMoveTarget { /** * AddressBook constructor. * @@ -52,8 +36,9 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { public function __construct(BackendInterface $carddavBackend, array $addressBookInfo, IL10N $l10n) { parent::__construct($carddavBackend, $addressBookInfo); - if ($this->addressBookInfo['{DAV:}displayname'] === CardDavBackend::PERSONAL_ADDRESSBOOK_NAME && - $this->getName() === CardDavBackend::PERSONAL_ADDRESSBOOK_URI) { + + if ($this->addressBookInfo['{DAV:}displayname'] === CardDavBackend::PERSONAL_ADDRESSBOOK_NAME + && $this->getName() === CardDavBackend::PERSONAL_ADDRESSBOOK_URI) { $this->addressBookInfo['{DAV:}displayname'] = $l10n->t('Contacts'); } } @@ -67,17 +52,15 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { * Every element in the add array has the following properties: * * href - A url. Usually a mailto: address * * commonName - Usually a first and last name, or false - * * summary - A description of the share, can also be false * * readOnly - A boolean value * * Every element in the remove array is just the address string. * - * @param array $add - * @param array $remove - * @return void + * @param list<array{href: string, commonName: string, readOnly: bool}> $add + * @param list<string> $remove * @throws Forbidden */ - public function updateShares(array $add, array $remove) { + public function updateShares(array $add, array $remove): void { if ($this->isShared()) { throw new Forbidden(); } @@ -92,11 +75,10 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { * * commonName - Optional, for example a first + last name * * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants. * * readOnly - boolean - * * summary - Optional, a description for the share * - * @return array + * @return list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}> */ - public function getShares() { + public function getShares(): array { if ($this->isShared()) { return []; } @@ -113,7 +95,12 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { 'privilege' => '{DAV:}write', 'principal' => $this->getOwner(), 'protected' => true, - ] + ], + [ + 'privilege' => '{DAV:}write-properties', + 'principal' => $this->getOwner(), + 'protected' => true, + ], ]; if ($this->getOwner() === 'principals/system/system') { @@ -122,6 +109,11 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { 'principal' => '{DAV:}authenticated', 'protected' => true, ]; + $acl[] = [ + 'privilege' => '{DAV:}write-properties', + 'principal' => '{DAV:}authenticated', + 'protected' => true, + ]; } if (!$this->isShared()) { @@ -144,7 +136,7 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { } $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); }); @@ -163,14 +155,33 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { return new Card($this->carddavBackend, $this->addressBookInfo, $obj); } - /** - * @return int - */ - public function getResourceId() { + public function getChildren() { + $objs = $this->carddavBackend->getCards($this->addressBookInfo['id']); + $children = []; + foreach ($objs as $obj) { + $obj['acl'] = $this->getChildACL(); + $children[] = new Card($this->carddavBackend, $this->addressBookInfo, $obj); + } + + return $children; + } + + public function getMultipleChildren(array $paths) { + $objs = $this->carddavBackend->getMultipleCards($this->addressBookInfo['id'], $paths); + $children = []; + foreach ($objs as $obj) { + $obj['acl'] = $this->getChildACL(); + $children[] = new Card($this->carddavBackend, $this->addressBookInfo, $obj); + } + + return $children; + } + + public function getResourceId(): int { return $this->addressBookInfo['id']; } - public function getOwner() { + public function getOwner(): ?string { if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) { return $this->addressBookInfo['{http://owncloud.org/ns}owner-principal']; } @@ -197,17 +208,16 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { } public function propPatch(PropPatch $propPatch) { - if (isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) { - throw new Forbidden(); + if (!isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) { + parent::propPatch($propPatch); } - parent::propPatch($propPatch); } public function getContactsGroups() { return $this->carddavBackend->collectCardProperties($this->getResourceId(), 'CATEGORIES'); } - private function isShared() { + private function isShared(): bool { if (!isset($this->addressBookInfo['{http://owncloud.org/ns}owner-principal'])) { return false; } @@ -215,7 +225,7 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { return $this->addressBookInfo['{http://owncloud.org/ns}owner-principal'] !== $this->addressBookInfo['principaluri']; } - private function canWrite() { + private function canWrite(): bool { if (isset($this->addressBookInfo['{http://owncloud.org/ns}read-only'])) { return !$this->addressBookInfo['{http://owncloud.org/ns}read-only']; } @@ -223,10 +233,29 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable { } public function getChanges($syncToken, $syncLevel, $limit = null) { - if (!$syncToken && $limit) { - throw new UnsupportedLimitOnInitialSyncException(); - } return parent::getChanges($syncToken, $syncLevel, $limit); } + + /** + * @inheritDoc + */ + public function moveInto($targetName, $sourcePath, INode $sourceNode) { + if (!($sourceNode instanceof Card)) { + return false; + } + + try { + return $this->carddavBackend->moveCard( + $sourceNode->getAddressbookId(), + $sourceNode->getUri(), + $this->getResourceId(), + $targetName, + ); + } catch (Exception $e) { + // Avoid injecting LoggerInterface everywhere + Server::get(LoggerInterface::class)->error('Could not move calendar object: ' . $e->getMessage(), ['exception' => $e]); + return false; + } + } } |