diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index c99d82a798..8336894a95 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -58,6 +58,7 @@ OCA\DAV\Settings\CalDAVSettings + OCA\DAV\Settings\CardDAVSettings diff --git a/apps/dav/appinfo/v1/carddav.php b/apps/dav/appinfo/v1/carddav.php index bb766bbaec..a98b0440e0 100644 --- a/apps/dav/appinfo/v1/carddav.php +++ b/apps/dav/appinfo/v1/carddav.php @@ -59,7 +59,7 @@ $principalBackend = new Principal( 'principals/' ); $db = \OC::$server->getDatabaseConnection(); -$cardDavBackend = new CardDavBackend($db, $principalBackend, \OC::$server->getUserManager(), \OC::$server->getGroupManager(), \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class), \OC::$server->getEventDispatcher()); +$cardDavBackend = new CardDavBackend($db, $principalBackend, \OC::$server->getUserManager(), \OC::$server->getGroupManager(), \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class), \OC::$server->getEventDispatcher(), \OC::$server->getConfig()); $debugging = \OC::$server->getConfig()->getSystemValue('debug', false); diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 19c0e2549f..af749500c8 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -271,6 +271,7 @@ return array( 'OCA\\DAV\\Search\\TasksSearchProvider' => $baseDir . '/../lib/Search/TasksSearchProvider.php', 'OCA\\DAV\\Server' => $baseDir . '/../lib/Server.php', 'OCA\\DAV\\Settings\\CalDAVSettings' => $baseDir . '/../lib/Settings/CalDAVSettings.php', + 'OCA\\DAV\\Settings\\CardDAVSettings' => $baseDir . '/../lib/Settings/CardDAVSettings.php', 'OCA\\DAV\\Storage\\PublicOwnerWrapper' => $baseDir . '/../lib/Storage/PublicOwnerWrapper.php', 'OCA\\DAV\\SystemTag\\SystemTagMappingNode' => $baseDir . '/../lib/SystemTag/SystemTagMappingNode.php', 'OCA\\DAV\\SystemTag\\SystemTagNode' => $baseDir . '/../lib/SystemTag/SystemTagNode.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index 6895064e39..4a0f478db2 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -286,6 +286,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Search\\TasksSearchProvider' => __DIR__ . '/..' . '/../lib/Search/TasksSearchProvider.php', 'OCA\\DAV\\Server' => __DIR__ . '/..' . '/../lib/Server.php', 'OCA\\DAV\\Settings\\CalDAVSettings' => __DIR__ . '/..' . '/../lib/Settings/CalDAVSettings.php', + 'OCA\\DAV\\Settings\\CardDAVSettings' => __DIR__ . '/..' . '/../lib/Settings/CardDAVSettings.php', 'OCA\\DAV\\Storage\\PublicOwnerWrapper' => __DIR__ . '/..' . '/../lib/Storage/PublicOwnerWrapper.php', 'OCA\\DAV\\SystemTag\\SystemTagMappingNode' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagMappingNode.php', 'OCA\\DAV\\SystemTag\\SystemTagNode' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagNode.php', diff --git a/apps/dav/js/settings-admin-carddav.js b/apps/dav/js/settings-admin-carddav.js new file mode 100644 index 0000000000..daaecae8e5 --- /dev/null +++ b/apps/dav/js/settings-admin-carddav.js @@ -0,0 +1,26 @@ +/** + * @copyright 2017, Bjoern Schiessle + * + * @author Bjoern Schiessle + * + * @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 . + * + */ +"use strict"; + +document.getElementById('carddavExposeSystemAddressBook').addEventListener('change', function(e) { + OCP.AppConfig.setValue('dav', 'exposeSystemAddressBook', e.target.checked ? 'yes' : 'no'); +}); diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index fa7db3750f..fe93e77aa6 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -47,6 +47,7 @@ use OCA\DAV\Events\CardDeletedEvent; use OCA\DAV\Events\CardUpdatedEvent; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IConfig; use OCP\IDBConnection; use OCP\IGroupManager; use OCP\IUser; @@ -97,6 +98,9 @@ class CardDavBackend implements BackendInterface, SyncSupport { /** @var IEventDispatcher */ private $dispatcher; + /** @var IConfig */ + private $config; + /** @var EventDispatcherInterface */ private $legacyDispatcher; @@ -111,18 +115,21 @@ class CardDavBackend implements BackendInterface, SyncSupport { * @param IGroupManager $groupManager * @param IEventDispatcher $dispatcher * @param EventDispatcherInterface $legacyDispatcher + * @param IConfig $config */ public function __construct(IDBConnection $db, Principal $principalBackend, IUserManager $userManager, IGroupManager $groupManager, IEventDispatcher $dispatcher, - EventDispatcherInterface $legacyDispatcher) { + EventDispatcherInterface $legacyDispatcher, + IConfig $config) { $this->db = $db; $this->principalBackend = $principalBackend; $this->userManager = $userManager; $this->dispatcher = $dispatcher; $this->legacyDispatcher = $legacyDispatcher; + $this->config = $config; $this->sharingBackend = new Backend($this->db, $this->userManager, $groupManager, $principalBackend, 'addressbook'); } @@ -243,6 +250,34 @@ class CardDavBackend implements BackendInterface, SyncSupport { } $result->closeCursor(); + // query for system addressbooks + $includeSystemAddressBook = $this->config->getAppValue('dav', 'exposeSystemAddressBook', 'no') === 'yes'; + if ($includeSystemAddressBook) { + $principalUri="principals/system/system"; + $query = $this->db->getQueryBuilder(); + $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken']) + ->from('addressbooks') + ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principalUri))); + $result = $query->execute(); + + while ($row = $result->fetch()) { + $addressBooks[$row['id']] = [ + 'id' => $row['id'], + 'uri' => "system-address-book", + 'principaluri' => $principalUriOriginal, + '{DAV:}displayname' => "System address book", + '{' . Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'], + '{http://calendarserver.org/ns/}getctag' => $row['synctoken'], + '{http://sabredav.org/ns}sync-token' => $row['synctoken'] ?: '0', + '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $row['principaluri'], + $readOnlyPropertyName => true, + ]; + + $this->addOwnerPrincipal($addressBooks[$row['id']]); + } + $result->closeCursor(); + } + return array_values($addressBooks); } diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php index dcc2256680..f8165a4ae7 100644 --- a/apps/dav/lib/RootCollection.php +++ b/apps/dav/lib/RootCollection.php @@ -140,11 +140,11 @@ class RootCollection extends SimpleCollection { ); $pluginManager = new PluginManager(\OC::$server, \OC::$server->query(IAppManager::class)); - $usersCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher, $legacyDispatcher); + $usersCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher, $legacyDispatcher, \OC::$server->getConfig()); $usersAddressBookRoot = new AddressBookRoot($userPrincipalBackend, $usersCardDavBackend, $pluginManager, 'principals/users'); $usersAddressBookRoot->disableListing = $disableListing; - $systemCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher, $legacyDispatcher); + $systemCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher, $legacyDispatcher, \OC::$server->getConfig()); $systemAddressBookRoot = new AddressBookRoot(new SystemPrincipalBackend(), $systemCardDavBackend, $pluginManager, 'principals/system'); $systemAddressBookRoot->disableListing = $disableListing; diff --git a/apps/dav/lib/Settings/CardDAVSettings.php b/apps/dav/lib/Settings/CardDAVSettings.php new file mode 100644 index 0000000000..53435905bf --- /dev/null +++ b/apps/dav/lib/Settings/CardDAVSettings.php @@ -0,0 +1,68 @@ + + * + * @author Bjoern Schiessle + * + * @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\Settings; + +use OCP\AppFramework\Http\TemplateResponse; +use OCP\IConfig; +use OCP\Settings\ISettings; + +class CardDAVSettings implements ISettings { + + /** @var IConfig */ + private $config; + + /** + * CalDAVSettings constructor. + * + * @param IConfig $config + */ + public function __construct(IConfig $config) { + $this->config = $config; + } + + /** + * @return TemplateResponse + */ + public function getForm() { + $parameters = [ + 'expose_system_address_book' => $this->config->getAppValue('dav', 'exposeSystemAddressBook', 'no'), + ]; + + return new TemplateResponse('dav', 'settings-admin-carddav', $parameters); + } + + /** + * @return string + */ + public function getSection() { + return 'groupware'; + } + + /** + * @return int + */ + public function getPriority() { + return 10; + } +} diff --git a/apps/dav/templates/settings-admin-carddav.php b/apps/dav/templates/settings-admin-carddav.php new file mode 100644 index 0000000000..b82a9168f6 --- /dev/null +++ b/apps/dav/templates/settings-admin-carddav.php @@ -0,0 +1,42 @@ + + * + * @author Bjoern Schiessle + * + * @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 . + * + */ + +script('dav', [ + 'settings-admin-carddav' +]); + +/** @var \OCP\IL10N $l */ +/** @var array $_ */ +?> +
+

t('Addressbook server')); ?>

+

+ /> + +
+ + t('Only information set to "Public" or "Trusted" in the user\'s personal settings will be exposed.')); ?> + +

+
diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php index 60f46ce8fa..01b77767b1 100644 --- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php +++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php @@ -83,6 +83,9 @@ class CardDavBackendTest extends TestCase { /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */ private $dispatcher; + /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ + private $config; + /** @var IDBConnection */ private $db; @@ -130,6 +133,9 @@ class CardDavBackendTest extends TestCase { protected function setUp(): void { parent::setUp(); + $this->config = $this->createMock(IConfig::class); + $this->config->expects($this->any())->method('getAppValue') + ->with('dav', 'exposeSystemAddressBook', 'no')->willReturn('no'); $this->userManager = $this->createMock(IUserManager::class); $this->groupManager = $this->createMock(IGroupManager::class); $this->principal = $this->getMockBuilder(Principal::class) @@ -158,7 +164,7 @@ class CardDavBackendTest extends TestCase { $this->db = \OC::$server->getDatabaseConnection(); - $this->backend = new CardDavBackend($this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher); + $this->backend = new CardDavBackend($this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher, $this->config); // start every test with a empty cards_properties and cards table $query = $this->db->getQueryBuilder(); $query->delete('cards_properties')->execute(); @@ -248,7 +254,7 @@ class CardDavBackendTest extends TestCase { /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject $backend */ $backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher, $this->config]) ->setMethods(['updateProperties', 'purgeProperties'])->getMock(); // create a new address book @@ -320,7 +326,7 @@ class CardDavBackendTest extends TestCase { public function testMultiCard() { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher, $this->config]) ->setMethods(['updateProperties'])->getMock(); // create a new address book @@ -373,7 +379,7 @@ class CardDavBackendTest extends TestCase { public function testMultipleUIDOnDifferentAddressbooks() { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher, $this->config]) ->setMethods(['updateProperties'])->getMock(); // create 2 new address books @@ -395,7 +401,7 @@ class CardDavBackendTest extends TestCase { public function testMultipleUIDDenied() { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher, $this->config]) ->setMethods(['updateProperties'])->getMock(); // create a new address book @@ -416,7 +422,7 @@ class CardDavBackendTest extends TestCase { public function testNoValidUID() { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher, $this->config]) ->setMethods(['updateProperties'])->getMock(); // create a new address book @@ -433,7 +439,7 @@ class CardDavBackendTest extends TestCase { public function testDeleteWithoutCard() { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher, $this->config]) ->setMethods([ 'getCardId', 'addChange', @@ -473,7 +479,7 @@ class CardDavBackendTest extends TestCase { public function testSyncSupport() { $this->backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher, $this->config]) ->setMethods(['updateProperties'])->getMock(); // create a new address book @@ -539,7 +545,7 @@ class CardDavBackendTest extends TestCase { $cardId = 2; $backend = $this->getMockBuilder(CardDavBackend::class) - ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher]) + ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher, $this->config]) ->setMethods(['getCardId'])->getMock(); $backend->expects($this->any())->method('getCardId')->willReturn($cardId);