From cdc536c42367a1c7667a63c598f50b95956da759 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Thu, 3 Dec 2015 16:22:18 +0100 Subject: Allow trusted servers to authenticate --- apps/dav/lib/connector/fedauth.php | 55 ++++++++++++++++++++++++++++++++++++ apps/dav/lib/server.php | 5 +++- apps/federation/appinfo/database.xml | 9 +++++- apps/federation/lib/dbhandler.php | 19 ++++++++++++- 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 apps/dav/lib/connector/fedauth.php diff --git a/apps/dav/lib/connector/fedauth.php b/apps/dav/lib/connector/fedauth.php new file mode 100644 index 00000000000..42a29cef3fc --- /dev/null +++ b/apps/dav/lib/connector/fedauth.php @@ -0,0 +1,55 @@ + + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @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 + * + */ +namespace OCA\DAV\Connector; + +use OCA\Federation\DbHandler; +use OCP\IDBConnection; +use Sabre\DAV\Auth\Backend\AbstractBasic; + +class FedAuth extends AbstractBasic { + + /** + * FedAuth constructor. + * + * @param IDBConnection $db + */ + public function __construct(IDBConnection $db) { + $this->db = $db; + $this->principalPrefix = 'principals/system/'; + } + + /** + * Validates a username and password + * + * This method should return true or false depending on if login + * succeeded. + * + * @param string $username + * @param string $password + * @return bool + */ + protected function validateUserPass($username, $password) { + $h = new DbHandler($this->db, + \OC::$server->getL10N('federation') + ); + return $h->auth($username, $password); + } +} diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php index a6ad878d29f..8b7171c145c 100644 --- a/apps/dav/lib/server.php +++ b/apps/dav/lib/server.php @@ -3,6 +3,7 @@ namespace OCA\DAV; use OCA\DAV\CalDAV\Schedule\IMipPlugin; +use OCA\DAV\Connector\FedAuth; use OCA\DAV\Connector\Sabre\Auth; use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin; use OCA\DAV\Files\CustomPropertiesBackend; @@ -35,7 +36,9 @@ class Server { $this->server->setBaseUri($this->baseUri); $this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig())); - $this->server->addPlugin(new Plugin($authBackend, 'ownCloud')); + $authPlugin = new Plugin($authBackend, 'ownCloud'); + $authPlugin->addBackend(new FedAuth(\OC::$server->getDatabaseConnection())); + $this->server->addPlugin($authPlugin); $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\DummyGetResponsePlugin()); $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $logger)); $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin()); diff --git a/apps/federation/appinfo/database.xml b/apps/federation/appinfo/database.xml index e0bb241918e..e6728df1408 100644 --- a/apps/federation/appinfo/database.xml +++ b/apps/federation/appinfo/database.xml @@ -34,7 +34,7 @@ token text 128 - toke used to exchange the shared secret + token used to exchange the shared secret shared_secret @@ -50,6 +50,13 @@ 2 current status of the connection + + sync_token + integer + true + 0 + cardDav sync token + url_hash true diff --git a/apps/federation/lib/dbhandler.php b/apps/federation/lib/dbhandler.php index 7606593f780..f86a8e15d80 100644 --- a/apps/federation/lib/dbhandler.php +++ b/apps/federation/lib/dbhandler.php @@ -111,7 +111,7 @@ class DbHandler { */ public function getAllServer() { $query = $this->connection->getQueryBuilder(); - $query->select(['url', 'id', 'status'])->from($this->dbTable); + $query->select(['url', 'id', 'status', 'shared_secret', 'sync_token'])->from($this->dbTable); $result = $query->execute()->fetchAll(); return $result; } @@ -267,4 +267,21 @@ class DbHandler { return $normalized; } + /** + * @param $username + * @param $password + * @return bool + */ + public function auth($username, $password) { + if ($username !== 'system') { + return false; + } + $query = $this->connection->getQueryBuilder(); + $query->select('url')->from($this->dbTable) + ->where($query->expr()->eq('shared_secret', $query->createNamedParameter($password))); + + $result = $query->execute()->fetch(); + return !empty($result); + } + } -- cgit v1.2.3 From dbddbb634bcb6df346988b85cb2847e76e22e632 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Fri, 4 Dec 2015 12:11:07 +0100 Subject: Use EventDispatcher to allow additional setup of auth backends - move federation auth to federation app --- apps/dav/lib/connector/fedauth.php | 55 --------------------------------- apps/dav/lib/server.php | 7 ++++- apps/federation/appinfo/application.php | 14 +++++++++ apps/federation/dav/fedauth.php | 55 +++++++++++++++++++++++++++++++++ lib/public/sabrepluginevent.php | 15 ++++++++- 5 files changed, 89 insertions(+), 57 deletions(-) delete mode 100644 apps/dav/lib/connector/fedauth.php create mode 100644 apps/federation/dav/fedauth.php diff --git a/apps/dav/lib/connector/fedauth.php b/apps/dav/lib/connector/fedauth.php deleted file mode 100644 index 42a29cef3fc..00000000000 --- a/apps/dav/lib/connector/fedauth.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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 - * - */ -namespace OCA\DAV\Connector; - -use OCA\Federation\DbHandler; -use OCP\IDBConnection; -use Sabre\DAV\Auth\Backend\AbstractBasic; - -class FedAuth extends AbstractBasic { - - /** - * FedAuth constructor. - * - * @param IDBConnection $db - */ - public function __construct(IDBConnection $db) { - $this->db = $db; - $this->principalPrefix = 'principals/system/'; - } - - /** - * Validates a username and password - * - * This method should return true or false depending on if login - * succeeded. - * - * @param string $username - * @param string $password - * @return bool - */ - protected function validateUserPass($username, $password) { - $h = new DbHandler($this->db, - \OC::$server->getL10N('federation') - ); - return $h->auth($username, $password); - } -} diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php index 8b7171c145c..93e903e6bf1 100644 --- a/apps/dav/lib/server.php +++ b/apps/dav/lib/server.php @@ -8,6 +8,7 @@ use OCA\DAV\Connector\Sabre\Auth; use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin; use OCA\DAV\Files\CustomPropertiesBackend; use OCP\IRequest; +use OCP\SabrePluginEvent; use Sabre\DAV\Auth\Plugin; class Server { @@ -37,8 +38,12 @@ class Server { $this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig())); $authPlugin = new Plugin($authBackend, 'ownCloud'); - $authPlugin->addBackend(new FedAuth(\OC::$server->getDatabaseConnection())); $this->server->addPlugin($authPlugin); + + // allow setup of additional auth backends + $event = new SabrePluginEvent($this->server); + $dispatcher->dispatch('OCA\DAV\Connector\Sabre::authInit', $event); + $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\DummyGetResponsePlugin()); $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $logger)); $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin()); diff --git a/apps/federation/appinfo/application.php b/apps/federation/appinfo/application.php index 45d88548b70..f0fefb948af 100644 --- a/apps/federation/appinfo/application.php +++ b/apps/federation/appinfo/application.php @@ -23,6 +23,7 @@ namespace OCA\Federation\AppInfo; use OCA\Federation\API\OCSAuthAPI; use OCA\Federation\Controller\SettingsController; +use OCA\Federation\DAV\FedAuth; use OCA\Federation\DbHandler; use OCA\Federation\Hooks; use OCA\Federation\Middleware\AddServerMiddleware; @@ -30,7 +31,9 @@ use OCA\Federation\TrustedServers; use OCP\API; use OCP\App; use OCP\AppFramework\IAppContainer; +use OCP\SabrePluginEvent; use OCP\Util; +use Sabre\DAV\Auth\Plugin; class Application extends \OCP\AppFramework\App { @@ -144,6 +147,17 @@ class Application extends \OCP\AppFramework\App { $hooksManager, 'addServerHook' ); + + $dispatcher = $this->getContainer()->getServer()->getEventDispatcher(); + $dispatcher->addListener('OCA\DAV\Connector\Sabre::authInit', function($event) use($container) { + if ($event instanceof SabrePluginEvent) { + $authPlugin = $event->getServer()->getPlugin('auth'); + if ($authPlugin instanceof Plugin) { + $db = $container->getServer()->getDatabaseConnection(); + $authPlugin->addBackend(new FedAuth($db)); + } + } + }); } } diff --git a/apps/federation/dav/fedauth.php b/apps/federation/dav/fedauth.php new file mode 100644 index 00000000000..ade5448d1bc --- /dev/null +++ b/apps/federation/dav/fedauth.php @@ -0,0 +1,55 @@ + + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @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 + * + */ +namespace OCA\Federation\DAV; + +use OCA\Federation\DbHandler; +use OCP\IDBConnection; +use Sabre\DAV\Auth\Backend\AbstractBasic; + +class FedAuth extends AbstractBasic { + + /** + * FedAuth constructor. + * + * @param IDBConnection $db + */ + public function __construct(IDBConnection $db) { + $this->db = $db; + $this->principalPrefix = 'principals/system/'; + } + + /** + * Validates a username and password + * + * This method should return true or false depending on if login + * succeeded. + * + * @param string $username + * @param string $password + * @return bool + */ + protected function validateUserPass($username, $password) { + $h = new DbHandler($this->db, + \OC::$server->getL10N('federation') + ); + return $h->auth($username, $password); + } +} diff --git a/lib/public/sabrepluginevent.php b/lib/public/sabrepluginevent.php index fed3237166d..1a64c8ac3ed 100644 --- a/lib/public/sabrepluginevent.php +++ b/lib/public/sabrepluginevent.php @@ -23,6 +23,7 @@ namespace OCP; use OCP\AppFramework\Http; +use Sabre\DAV\Server; use Symfony\Component\EventDispatcher\Event; /** @@ -36,12 +37,16 @@ class SabrePluginEvent extends Event { /** @var string */ protected $message; + /** @var Server */ + protected $server; + /** * @since 8.2.0 */ - public function __construct() { + public function __construct($server = null) { $this->message = ''; $this->statusCode = Http::STATUS_OK; + $this->server = $server; } /** @@ -79,4 +84,12 @@ class SabrePluginEvent extends Event { public function getMessage() { return $this->message; } + + /** + * @return null|Server + * @since 9.0.0 + */ + public function getServer() { + return $this->server; + } } -- cgit v1.2.3 From 90d9834c8c0d3ae10cc754595d729821584e76a9 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Fri, 4 Dec 2015 13:38:32 +0100 Subject: Decouple federation and dav app --- apps/dav/appinfo/app.php | 15 ++ apps/dav/lib/carddav/carddavbackend.php | 7 +- apps/dav/lib/carddav/syncservice.php | 155 +++++++++++++++++++++ apps/dav/lib/rootcollection.php | 4 +- apps/dav/tests/unit/carddav/carddavbackendtest.php | 14 +- apps/federation/appinfo/database.xml | 5 +- apps/federation/appinfo/info.xml | 2 +- apps/federation/appinfo/register_command.php | 9 ++ .../command/syncfederationaddressbooks.php | 75 ++++++++++ apps/federation/lib/dbhandler.php | 11 +- 10 files changed, 271 insertions(+), 26 deletions(-) create mode 100644 apps/dav/lib/carddav/syncservice.php create mode 100644 apps/federation/appinfo/register_command.php create mode 100644 apps/federation/command/syncfederationaddressbooks.php diff --git a/apps/dav/appinfo/app.php b/apps/dav/appinfo/app.php index bc889176f7f..d09003e19c0 100644 --- a/apps/dav/appinfo/app.php +++ b/apps/dav/appinfo/app.php @@ -19,6 +19,21 @@ * */ +use OCA\DAV\CardDAV\CardDavBackend; +use OCA\DAV\CardDAV\SyncService; +use OCA\DAV\Connector\Sabre\Principal; + +\OC::$server->registerService('CardDAVSyncService', function() { + $principalBackend = new Principal( + $this->config, + $this->userManager + ); + + $backend = new CardDavBackend($this->dbConnection, $principalBackend); + + return new SyncService($backend); +}); + $cm = \OC::$server->getContactsManager(); $cm->register(function() use ($cm) { $userId = \OC::$server->getUserSession()->getUser()->getUID(); diff --git a/apps/dav/lib/carddav/carddavbackend.php b/apps/dav/lib/carddav/carddavbackend.php index 95175b20d1b..cdb3481eaf5 100644 --- a/apps/dav/lib/carddav/carddavbackend.php +++ b/apps/dav/lib/carddav/carddavbackend.php @@ -37,9 +37,6 @@ class CardDavBackend implements BackendInterface, SyncSupport { /** @var Principal */ private $principalBackend; - /** @var ILogger */ - private $logger; - /** @var string */ private $dbCardsTable = 'cards'; @@ -59,12 +56,10 @@ class CardDavBackend implements BackendInterface, SyncSupport { * * @param IDBConnection $db * @param Principal $principalBackend - * @param ILogger $logger */ - public function __construct(IDBConnection $db, Principal $principalBackend, ILogger $logger) { + public function __construct(IDBConnection $db, Principal $principalBackend) { $this->db = $db; $this->principalBackend = $principalBackend; - $this->logger = $logger; } /** diff --git a/apps/dav/lib/carddav/syncservice.php b/apps/dav/lib/carddav/syncservice.php new file mode 100644 index 00000000000..8442f7cf52b --- /dev/null +++ b/apps/dav/lib/carddav/syncservice.php @@ -0,0 +1,155 @@ + + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @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 + * + */ + +namespace OCA\DAV\CardDAV; + +use Sabre\DAV\Client; +use Sabre\DAV\Xml\Response\MultiStatus; +use Sabre\DAV\Xml\Service; + +class SyncService { + + /** @var CardDavBackend */ + private $backend; + + public function __construct(CardDavBackend $backend) { + $this->backend = $backend; + } + + public function syncRemoteAddressBook($url, $userName, $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetProperties) { + // 1. create addressbook + $book = $this->ensureSystemAddressBookExists($targetPrincipal, $targetBookId, $targetProperties); + $addressBookId = $book['id']; + + // 2. query changes + $response = $this->requestSyncReport($url, $userName, $sharedSecret, $syncToken); + + // 3. apply changes + // TODO: use multi-get for download + foreach ($response['response'] as $resource => $status) { + $cardUri = basename($resource); + if (isset($status[200])) { + $vCard = $this->download($url, $sharedSecret, $resource); + $existingCard = $this->backend->getCard($addressBookId, $cardUri); + if ($existingCard === false) { + $this->backend->createCard($addressBookId, $cardUri, $vCard['body']); + } else { + $this->backend->updateCard($addressBookId, $cardUri, $vCard['body']); + } + } else { + $this->backend->deleteCard($addressBookId, $cardUri); + } + } + + return $response['token']; + } + + protected function ensureSystemAddressBookExists($principal, $id, $properties) { + $book = $this->backend->getAddressBooksByUri($id); + if (!is_null($book)) { + return $book; + } + $this->backend->createAddressBook($principal, $id, $properties); + + return $this->backend->getAddressBooksByUri($id); + } + + /** + * @param string $url + * @param string $userName + * @param string $sharedSecret + * @param string $syncToken + * @return array + */ + private function requestSyncReport($url, $userName, $sharedSecret, $syncToken) { + $settings = [ + 'baseUri' => $url, + 'userName' => $userName, + 'password' => $sharedSecret, + ]; + $client = new Client($settings); + $client->setThrowExceptions(true); + + $addressBookUrl = "/remote.php/dav/addressbooks/system/system/system"; + $body = $this->buildSyncCollectionRequestBody($syncToken); + + $response = $client->request('REPORT', $addressBookUrl, $body, [ + 'Content-Type' => 'application/xml' + ]); + +// if ((int)$response->getStatus() >= 400) { +// throw new Exception('HTTP error: ' . $response->getStatus()); +// } + + $result = $this->parseMultiStatus($response['body']); + + return $result; + } + + private function download($url, $sharedSecret, $changeSet) { + $settings = [ + 'baseUri' => $url, + 'userName' => 'system', + 'password' => $sharedSecret, + ]; + $client = new Client($settings); + $client->setThrowExceptions(true); + + $response = $client->request('GET', $changeSet); + return $response; + } + + function buildSyncCollectionRequestBody($synToken) { + + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->formatOutput = true; + $root = $dom->createElementNS('DAV:', 'd:sync-collection'); + $sync = $dom->createElement('d:sync-token', $synToken); + $prop = $dom->createElement('d:prop'); + $cont = $dom->createElement('d:getcontenttype'); + $etag = $dom->createElement('d:getetag'); + + $prop->appendChild($cont); + $prop->appendChild($etag); + $root->appendChild($sync); + $root->appendChild($prop); + $dom->appendChild($root); + $body = $dom->saveXML(); + + return $body; + } + + private function parseMultiStatus($body) { + $xml = new Service(); + + /** @var MultiStatus $multiStatus */ + $multiStatus = $xml->expect('{DAV:}multistatus', $body); + + $result = []; + foreach ($multiStatus->getResponses() as $response) { + $result[$response->getHref()] = $response->getResponseProperties(); + } + + return ['response' => $result, 'token' => $multiStatus->getSyncToken()]; + } + + +} diff --git a/apps/dav/lib/rootcollection.php b/apps/dav/lib/rootcollection.php index 2261712200a..053ff47f977 100644 --- a/apps/dav/lib/rootcollection.php +++ b/apps/dav/lib/rootcollection.php @@ -46,11 +46,11 @@ class RootCollection extends SimpleCollection { \OC::$server->getSystemTagObjectMapper() ); - $usersCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, \OC::$server->getLogger()); + $usersCardDavBackend = new CardDavBackend($db, $userPrincipalBackend); $usersAddressBookRoot = new AddressBookRoot($userPrincipalBackend, $usersCardDavBackend, 'principals/users'); $usersAddressBookRoot->disableListing = $disableListing; - $systemCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, \OC::$server->getLogger()); + $systemCardDavBackend = new CardDavBackend($db, $userPrincipalBackend); $systemAddressBookRoot = new AddressBookRoot(new SystemPrincipalBackend(), $systemCardDavBackend, 'principals/system'); $systemAddressBookRoot->disableListing = $disableListing; diff --git a/apps/dav/tests/unit/carddav/carddavbackendtest.php b/apps/dav/tests/unit/carddav/carddavbackendtest.php index fe01aa65cca..2f5e9eeded6 100644 --- a/apps/dav/tests/unit/carddav/carddavbackendtest.php +++ b/apps/dav/tests/unit/carddav/carddavbackendtest.php @@ -45,9 +45,6 @@ class CardDavBackendTest extends TestCase { /** @var Principal | \PHPUnit_Framework_MockObject_MockObject */ private $principal; - /** @var ILogger | \PHPUnit_Framework_MockObject_MockObject */ - private $logger; - /** @var IDBConnection */ private $db; @@ -70,11 +67,10 @@ class CardDavBackendTest extends TestCase { ->willReturn([ 'uri' => 'principals/best-friend' ]); - $this->logger = $this->getMock('\OCP\ILogger'); $this->db = \OC::$server->getDatabaseConnection(); - $this->backend = new CardDavBackend($this->db, $this->principal, $this->logger); + $this->backend = new CardDavBackend($this->db, $this->principal); // start every test with a empty cards_properties and cards table $query = $this->db->getQueryBuilder(); @@ -129,7 +125,7 @@ class CardDavBackendTest extends TestCase { /** @var CardDavBackend | \PHPUnit_Framework_MockObject_MockObject $backend */ $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') - ->setConstructorArgs([$this->db, $this->principal, $this->logger]) + ->setConstructorArgs([$this->db, $this->principal]) ->setMethods(['updateProperties', 'purgeProperties'])->getMock(); // create a new address book @@ -175,7 +171,7 @@ class CardDavBackendTest extends TestCase { public function testMultiCard() { $this->backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') - ->setConstructorArgs([$this->db, $this->principal, $this->logger]) + ->setConstructorArgs([$this->db, $this->principal]) ->setMethods(['updateProperties'])->getMock(); // create a new address book @@ -222,7 +218,7 @@ class CardDavBackendTest extends TestCase { public function testSyncSupport() { $this->backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') - ->setConstructorArgs([$this->db, $this->principal, $this->logger]) + ->setConstructorArgs([$this->db, $this->principal]) ->setMethods(['updateProperties'])->getMock(); // create a new address book @@ -279,7 +275,7 @@ class CardDavBackendTest extends TestCase { $cardId = 2; $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDavBackend') - ->setConstructorArgs([$this->db, $this->principal, $this->logger]) + ->setConstructorArgs([$this->db, $this->principal]) ->setMethods(['getCardId'])->getMock(); $backend->expects($this->any())->method('getCardId')->willReturn($cardId); diff --git a/apps/federation/appinfo/database.xml b/apps/federation/appinfo/database.xml index e6728df1408..05b7fb12b49 100644 --- a/apps/federation/appinfo/database.xml +++ b/apps/federation/appinfo/database.xml @@ -52,9 +52,8 @@ sync_token - integer - true - 0 + text + 512 cardDav sync token diff --git a/apps/federation/appinfo/info.xml b/apps/federation/appinfo/info.xml index 92afc995366..bfb4ca8f8c9 100644 --- a/apps/federation/appinfo/info.xml +++ b/apps/federation/appinfo/info.xml @@ -5,7 +5,7 @@ ownCloud Federation allows you to connect with other trusted ownClouds to exchange the user directory. For example this will be used to auto-complete external users for federated sharing. AGPL Bjoern Schiessle - 0.0.1 + 0.0.2 Federation other diff --git a/apps/federation/appinfo/register_command.php b/apps/federation/appinfo/register_command.php new file mode 100644 index 00000000000..8509a9721ad --- /dev/null +++ b/apps/federation/appinfo/register_command.php @@ -0,0 +1,9 @@ +getConfig(); +$dbConnection = \OC::$server->getDatabaseConnection(); +$userManager = OC::$server->getUserManager(); +$config = \OC::$server->getConfig(); + +/** @var Symfony\Component\Console\Application $application */ +$application->add(new \OCA\Federation\Command\SyncFederationAddressBooks($userManager, $dbConnection, $config)); diff --git a/apps/federation/command/syncfederationaddressbooks.php b/apps/federation/command/syncfederationaddressbooks.php new file mode 100644 index 00000000000..497eba66bec --- /dev/null +++ b/apps/federation/command/syncfederationaddressbooks.php @@ -0,0 +1,75 @@ +syncService = \OC::$server->query('CardDAVSyncService'); + $this->dbConnection = $dbConnection; + } + + protected function configure() { + $this + ->setName('federation:sync-addressbooks') + ->setDescription('Synchronizes addressbooks of all federated clouds'); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + */ + protected function execute(InputInterface $input, OutputInterface $output) { + + $progress = new ProgressBar($output); + $progress->start(); + $db = new DbHandler($this->dbConnection, null); + $trustedServers = $db->getAllServer(); + foreach ($trustedServers as $trustedServer) { + $progress->advance(); + $url = $trustedServer['url']; + $sharedSecret = $trustedServer['shared_secret']; + $syncToken = $trustedServer['sync_token']; + + if (is_null($sharedSecret)) { + continue; + } + $targetBookId = md5($url); + $targetPrincipal = "principals/system/system"; + $targetBookProperties = [ + '{DAV:}displayname' => $url + ]; + $newToken = $this->syncService->syncRemoteAddressBook($url, 'system', $sharedSecret, $syncToken, $targetPrincipal, $targetBookId, $targetBookProperties); + if ($newToken !== $syncToken) { + $db->setServerStatus($url, TrustedServers::STATUS_OK, $newToken); + } + } + $progress->finish(); + $output->writeln(''); + } +} diff --git a/apps/federation/lib/dbhandler.php b/apps/federation/lib/dbhandler.php index f86a8e15d80..0677430f799 100644 --- a/apps/federation/lib/dbhandler.php +++ b/apps/federation/lib/dbhandler.php @@ -207,14 +207,15 @@ class DbHandler { * @param string $url * @param int $status */ - public function setServerStatus($url, $status) { + public function setServerStatus($url, $status, $token = null) { $hash = $this->hash($url); $query = $this->connection->getQueryBuilder(); $query->update($this->dbTable) - ->set('status', $query->createParameter('status')) - ->where($query->expr()->eq('url_hash', $query->createParameter('url_hash'))) - ->setParameter('url_hash', $hash) - ->setParameter('status', $status); + ->set('status', $query->createNamedParameter($status)) + ->where($query->expr()->eq('url_hash', $query->createNamedParameter($hash))); + if (!is_null($token)) { + $query->set('sync_token', $query->createNamedParameter($token)); + } $query->execute(); } -- cgit v1.2.3 From 0bf026cceab5f5e910f5e7c163397dbe76dbe0f2 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Fri, 4 Dec 2015 13:53:53 +0100 Subject: Fix registration of sync command --- apps/federation/appinfo/register_command.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/federation/appinfo/register_command.php b/apps/federation/appinfo/register_command.php index 8509a9721ad..28829ccfca1 100644 --- a/apps/federation/appinfo/register_command.php +++ b/apps/federation/appinfo/register_command.php @@ -1,9 +1,6 @@ getConfig(); $dbConnection = \OC::$server->getDatabaseConnection(); -$userManager = OC::$server->getUserManager(); -$config = \OC::$server->getConfig(); /** @var Symfony\Component\Console\Application $application */ -$application->add(new \OCA\Federation\Command\SyncFederationAddressBooks($userManager, $dbConnection, $config)); +$application->add(new \OCA\Federation\Command\SyncFederationAddressBooks($dbConnection)); -- cgit v1.2.3 From 1a20af253bc90de35a1bf3b65adb33ab44d17c1d Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Mon, 7 Dec 2015 15:28:06 +0100 Subject: Adding tests and adjust PHPDoc --- apps/dav/lib/carddav/syncservice.php | 38 +++++++++++++++++++-- apps/federation/appinfo/application.php | 6 ++-- apps/federation/dav/fedauth.php | 10 ++---- apps/federation/lib/dbhandler.php | 1 + apps/federation/tests/dav/fedauthtest.php | 52 +++++++++++++++++++++++++++++ apps/federation/tests/lib/dbhandlertest.php | 26 ++++++++++++++- 6 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 apps/federation/tests/dav/fedauthtest.php diff --git a/apps/dav/lib/carddav/syncservice.php b/apps/dav/lib/carddav/syncservice.php index 8442f7cf52b..bfaf09f4c0e 100644 --- a/apps/dav/lib/carddav/syncservice.php +++ b/apps/dav/lib/carddav/syncservice.php @@ -34,6 +34,16 @@ class SyncService { $this->backend = $backend; } + /** + * @param string $url + * @param string $userName + * @param string $sharedSecret + * @param string $syncToken + * @param int $targetBookId + * @param string $targetPrincipal + * @param array $targetProperties + * @return string + */ public function syncRemoteAddressBook($url, $userName, $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetProperties) { // 1. create addressbook $book = $this->ensureSystemAddressBookExists($targetPrincipal, $targetBookId, $targetProperties); @@ -62,6 +72,13 @@ class SyncService { return $response['token']; } + /** + * @param string $principal + * @param string $id + * @param array $properties + * @return array|null + * @throws \Sabre\DAV\Exception\BadRequest + */ protected function ensureSystemAddressBookExists($principal, $id, $properties) { $book = $this->backend->getAddressBooksByUri($id); if (!is_null($book)) { @@ -104,7 +121,13 @@ class SyncService { return $result; } - private function download($url, $sharedSecret, $changeSet) { + /** + * @param string $url + * @param string $sharedSecret + * @param string $resourcePath + * @return array + */ + private function download($url, $sharedSecret, $resourcePath) { $settings = [ 'baseUri' => $url, 'userName' => 'system', @@ -113,11 +136,15 @@ class SyncService { $client = new Client($settings); $client->setThrowExceptions(true); - $response = $client->request('GET', $changeSet); + $response = $client->request('GET', $resourcePath); return $response; } - function buildSyncCollectionRequestBody($synToken) { + /** + * @param string|null $synToken + * @return string + */ + private function buildSyncCollectionRequestBody($synToken) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->formatOutput = true; @@ -137,6 +164,11 @@ class SyncService { return $body; } + /** + * @param string $body + * @return array + * @throws \Sabre\Xml\ParseException + */ private function parseMultiStatus($body) { $xml = new Service(); diff --git a/apps/federation/appinfo/application.php b/apps/federation/appinfo/application.php index f0fefb948af..0214d73d900 100644 --- a/apps/federation/appinfo/application.php +++ b/apps/federation/appinfo/application.php @@ -153,8 +153,10 @@ class Application extends \OCP\AppFramework\App { if ($event instanceof SabrePluginEvent) { $authPlugin = $event->getServer()->getPlugin('auth'); if ($authPlugin instanceof Plugin) { - $db = $container->getServer()->getDatabaseConnection(); - $authPlugin->addBackend(new FedAuth($db)); + $h = new DbHandler($container->getServer()->getDatabaseConnection(), + $container->getServer()->getL10N('federation') + ); + $authPlugin->addBackend(new FedAuth($h)); } } }); diff --git a/apps/federation/dav/fedauth.php b/apps/federation/dav/fedauth.php index ade5448d1bc..56173233bf3 100644 --- a/apps/federation/dav/fedauth.php +++ b/apps/federation/dav/fedauth.php @@ -21,7 +21,6 @@ namespace OCA\Federation\DAV; use OCA\Federation\DbHandler; -use OCP\IDBConnection; use Sabre\DAV\Auth\Backend\AbstractBasic; class FedAuth extends AbstractBasic { @@ -29,9 +28,9 @@ class FedAuth extends AbstractBasic { /** * FedAuth constructor. * - * @param IDBConnection $db + * @param DbHandler $db */ - public function __construct(IDBConnection $db) { + public function __construct(DbHandler $db) { $this->db = $db; $this->principalPrefix = 'principals/system/'; } @@ -47,9 +46,6 @@ class FedAuth extends AbstractBasic { * @return bool */ protected function validateUserPass($username, $password) { - $h = new DbHandler($this->db, - \OC::$server->getL10N('federation') - ); - return $h->auth($username, $password); + return $this->db->auth($username, $password); } } diff --git a/apps/federation/lib/dbhandler.php b/apps/federation/lib/dbhandler.php index 0677430f799..f50854fefb3 100644 --- a/apps/federation/lib/dbhandler.php +++ b/apps/federation/lib/dbhandler.php @@ -206,6 +206,7 @@ class DbHandler { * * @param string $url * @param int $status + * @param string|null $token */ public function setServerStatus($url, $status, $token = null) { $hash = $this->hash($url); diff --git a/apps/federation/tests/dav/fedauthtest.php b/apps/federation/tests/dav/fedauthtest.php new file mode 100644 index 00000000000..845cfc622d2 --- /dev/null +++ b/apps/federation/tests/dav/fedauthtest.php @@ -0,0 +1,52 @@ + + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @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 + * + */ + + +namespace OCA\Federation\Tests\DAV; + +use OCA\Federation\DAV\FedAuth; +use OCA\Federation\DbHandler; +use Test\TestCase; + +class FedAuthTest extends TestCase { + + /** + * @dataProvider providesUser + * + * @param array $expected + * @param string $user + * @param string $password + */ + public function testFedAuth($expected, $user, $password) { + /** @var DbHandler | \PHPUnit_Framework_MockObject_MockObject $db */ + $db = $this->getMockBuilder('OCA\Federation\DbHandler')->disableOriginalConstructor()->getMock(); + $db->method('auth')->willReturn(true); + $auth = new FedAuth($db); + $result = $this->invokePrivate($auth, 'validateUserPass', [$user, $password]); + $this->assertEquals($expected, $result); + } + + public function providesUser() { + return [ + [true, 'system', '123456'] + ]; + } +} diff --git a/apps/federation/tests/lib/dbhandlertest.php b/apps/federation/tests/lib/dbhandlertest.php index 123eaaee450..65126e39f72 100644 --- a/apps/federation/tests/lib/dbhandlertest.php +++ b/apps/federation/tests/lib/dbhandlertest.php @@ -26,6 +26,7 @@ namespace OCA\Federation\Tests\lib; use OCA\Federation\DbHandler; use OCA\Federation\TrustedServers; use OCP\IDBConnection; +use OCP\IL10N; use Test\TestCase; /** @@ -36,7 +37,7 @@ class DbHandlerTest extends TestCase { /** @var DbHandler */ private $dbHandler; - /** @var \PHPUnit_Framework_MockObject_MockObject */ + /** @var IL10N | \PHPUnit_Framework_MockObject_MockObject */ private $il10n; /** @var IDBConnection */ @@ -209,6 +210,11 @@ class DbHandlerTest extends TestCase { $this->assertSame(TrustedServers::STATUS_OK, $this->dbHandler->getServerStatus('https://server1') ); + + // test sync token + $this->dbHandler->setServerStatus('http://server1', TrustedServers::STATUS_OK, 'token1234567890'); + $servers = $this->dbHandler->getAllServer(); + $this->assertSame('token1234567890', $servers[0]['sync_token']); } /** @@ -256,4 +262,22 @@ class DbHandlerTest extends TestCase { ]; } + /** + * @dataProvider providesAuth + */ + public function testAuth($expectedResult, $user, $password) { + if ($expectedResult) { + $this->dbHandler->addServer('url1'); + $this->dbHandler->addSharedSecret('url1', $password); + } + $result = $this->dbHandler->auth($user, $password); + $this->assertEquals($expectedResult, $result); + } + + public function providesAuth() { + return [ + [false, 'foo', ''], + [true, 'system', '123456789'], + ]; + } } -- cgit v1.2.3 From 451ab84d112b1362edc58eb48a970e186d6f6701 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Thu, 10 Dec 2015 15:53:44 +0100 Subject: Adding unit tests for the sync service --- apps/dav/lib/carddav/syncservice.php | 2 +- apps/dav/tests/unit/carddav/syncservicetest.php | 93 +++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 apps/dav/tests/unit/carddav/syncservicetest.php diff --git a/apps/dav/lib/carddav/syncservice.php b/apps/dav/lib/carddav/syncservice.php index bfaf09f4c0e..dbe10bbcc81 100644 --- a/apps/dav/lib/carddav/syncservice.php +++ b/apps/dav/lib/carddav/syncservice.php @@ -96,7 +96,7 @@ class SyncService { * @param string $syncToken * @return array */ - private function requestSyncReport($url, $userName, $sharedSecret, $syncToken) { + protected function requestSyncReport($url, $userName, $sharedSecret, $syncToken) { $settings = [ 'baseUri' => $url, 'userName' => $userName, diff --git a/apps/dav/tests/unit/carddav/syncservicetest.php b/apps/dav/tests/unit/carddav/syncservicetest.php new file mode 100644 index 00000000000..f1ef934b8c6 --- /dev/null +++ b/apps/dav/tests/unit/carddav/syncservicetest.php @@ -0,0 +1,93 @@ + + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @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 + * + */ +namespace OCA\DAV\CardDAV; + +use Test\TestCase; + +class SyncServiceTest extends TestCase { + public function testEmptySync() { + $backend = $this->getBackendMock(0, 0, 0); + + $ss = $this->getSyncServiceMock($backend, []); + $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []); + $this->assertEquals('sync-token-1', $return); + } + + public function testSyncWithNewElement() { + $backend = $this->getBackendMock(1, 0, 0); + $backend->method('getCard')->willReturn(false); + + $ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]); + $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []); + $this->assertEquals('sync-token-1', $return); + } + + public function testSyncWithUpdatedElement() { + $backend = $this->getBackendMock(0, 1, 0); + $backend->method('getCard')->willReturn(true); + + $ss = $this->getSyncServiceMock($backend, ['0' => [200 => '']]); + $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []); + $this->assertEquals('sync-token-1', $return); + } + + public function testSyncWithDeletedElement() { + $backend = $this->getBackendMock(0, 0, 1); +// $backend->method('getCard')->willReturn(true); + + $ss = $this->getSyncServiceMock($backend, ['0' => [404 => '']]); + $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []); + $this->assertEquals('sync-token-1', $return); + } + + /** + * @param int $createCount + * @param int $updateCount + * @param int $deleteCount + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function getBackendMock($createCount, $updateCount, $deleteCount) { + $backend = $this->getMockBuilder('OCA\DAV\CardDAV\CardDAVBackend')->disableOriginalConstructor()->getMock(); + $backend->expects($this->exactly($createCount))->method('createCard'); + $backend->expects($this->exactly($updateCount))->method('updateCard'); + $backend->expects($this->exactly($deleteCount))->method('deleteCard'); + return $backend; + } + + /** + * @param $backend + * @param $response + * @return SyncService|\PHPUnit_Framework_MockObject_MockObject + */ + private function getSyncServiceMock($backend, $response) { + /** @var SyncService | \PHPUnit_Framework_MockObject_MockObject $ss */ + $ss = $this->getMock('OCA\DAV\CardDAV\SyncService', ['ensureSystemAddressBookExists', 'requestSyncReport', 'download'], [$backend]); + $ss->method('requestSyncReport')->withAnyParameters()->willReturn(['response' => $response, 'token' => 'sync-token-1']); + $ss->method('ensureSystemAddressBookExists')->willReturn(['id' => 1]); + $ss->method('download')->willReturn([ + 'body' => '', + 'statusCode' => 200, + 'headers' => [] + ]); + return $ss; + } + +} -- cgit v1.2.3 From 06dac9726ea4ca33c19bbc7791e3a7875705c763 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Wed, 16 Dec 2015 21:04:54 +0100 Subject: Address comments --- apps/dav/appinfo/app.php | 11 ++++++++--- apps/dav/lib/carddav/syncservice.php | 6 +++--- apps/dav/tests/unit/carddav/syncservicetest.php | 1 - 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/apps/dav/appinfo/app.php b/apps/dav/appinfo/app.php index d09003e19c0..9d092d84eb4 100644 --- a/apps/dav/appinfo/app.php +++ b/apps/dav/appinfo/app.php @@ -24,12 +24,17 @@ use OCA\DAV\CardDAV\SyncService; use OCA\DAV\Connector\Sabre\Principal; \OC::$server->registerService('CardDAVSyncService', function() { + + $config = \OC::$server->getConfig(); + $userManager = \OC::$server->getUserManager(); + $dbConnection = \OC::$server->getDatabaseConnection(); + $principalBackend = new Principal( - $this->config, - $this->userManager + $config, + $userManager ); - $backend = new CardDavBackend($this->dbConnection, $principalBackend); + $backend = new CardDavBackend($dbConnection, $principalBackend); return new SyncService($backend); }); diff --git a/apps/dav/lib/carddav/syncservice.php b/apps/dav/lib/carddav/syncservice.php index dbe10bbcc81..494db61d989 100644 --- a/apps/dav/lib/carddav/syncservice.php +++ b/apps/dav/lib/carddav/syncservice.php @@ -141,15 +141,15 @@ class SyncService { } /** - * @param string|null $synToken + * @param string|null $syncToken * @return string */ - private function buildSyncCollectionRequestBody($synToken) { + private function buildSyncCollectionRequestBody($syncToken) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->formatOutput = true; $root = $dom->createElementNS('DAV:', 'd:sync-collection'); - $sync = $dom->createElement('d:sync-token', $synToken); + $sync = $dom->createElement('d:sync-token', $syncToken); $prop = $dom->createElement('d:prop'); $cont = $dom->createElement('d:getcontenttype'); $etag = $dom->createElement('d:getetag'); diff --git a/apps/dav/tests/unit/carddav/syncservicetest.php b/apps/dav/tests/unit/carddav/syncservicetest.php index f1ef934b8c6..a6a773babc2 100644 --- a/apps/dav/tests/unit/carddav/syncservicetest.php +++ b/apps/dav/tests/unit/carddav/syncservicetest.php @@ -51,7 +51,6 @@ class SyncServiceTest extends TestCase { public function testSyncWithDeletedElement() { $backend = $this->getBackendMock(0, 0, 1); -// $backend->method('getCard')->willReturn(true); $ss = $this->getSyncServiceMock($backend, ['0' => [404 => '']]); $return = $ss->syncRemoteAddressBook('', 'system', '1234567890', null, '1', 'principals/system/system', []); -- cgit v1.2.3 From 6d223df2f47a330c1bd61d2483de9bc113616068 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Thu, 17 Dec 2015 11:23:22 +0100 Subject: md5 -> sha1 --- apps/federation/command/syncfederationaddressbooks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/federation/command/syncfederationaddressbooks.php b/apps/federation/command/syncfederationaddressbooks.php index 497eba66bec..d152f1b19db 100644 --- a/apps/federation/command/syncfederationaddressbooks.php +++ b/apps/federation/command/syncfederationaddressbooks.php @@ -59,7 +59,7 @@ class SyncFederationAddressBooks extends Command { if (is_null($sharedSecret)) { continue; } - $targetBookId = md5($url); + $targetBookId = sha1($url); $targetPrincipal = "principals/system/system"; $targetBookProperties = [ '{DAV:}displayname' => $url -- cgit v1.2.3 From 693617d8a5b566454a2d18ff4cb9bcfd8559f3bd Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Thu, 17 Dec 2015 17:01:24 +0100 Subject: Inject DbHandler .... --- apps/federation/appinfo/register_command.php | 4 +++- apps/federation/command/syncfederationaddressbooks.php | 15 +++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/federation/appinfo/register_command.php b/apps/federation/appinfo/register_command.php index 28829ccfca1..541b01706d0 100644 --- a/apps/federation/appinfo/register_command.php +++ b/apps/federation/appinfo/register_command.php @@ -1,6 +1,8 @@ getDatabaseConnection(); +$l10n = \OC::$server->getL10N('federation'); +$dbHandler = new \OCA\Federation\DbHandler($dbConnection, $l10n); /** @var Symfony\Component\Console\Application $application */ -$application->add(new \OCA\Federation\Command\SyncFederationAddressBooks($dbConnection)); +$application->add(new \OCA\Federation\Command\SyncFederationAddressBooks($dbHandler)); diff --git a/apps/federation/command/syncfederationaddressbooks.php b/apps/federation/command/syncfederationaddressbooks.php index d152f1b19db..d7761d14814 100644 --- a/apps/federation/command/syncfederationaddressbooks.php +++ b/apps/federation/command/syncfederationaddressbooks.php @@ -16,22 +16,22 @@ use Symfony\Component\Console\Output\OutputInterface; class SyncFederationAddressBooks extends Command { - /** @var \OCP\IDBConnection */ - protected $dbConnection; + /** @var DbHandler */ + protected $dbHandler; /** @var SyncService */ private $syncService; /** * @param IUserManager $userManager - * @param IDBConnection $dbConnection + * @param IDBConnection $dbHandler * @param IConfig $config */ - function __construct(IDBConnection $dbConnection) { + function __construct(DbHandler $dbHandler) { parent::__construct(); $this->syncService = \OC::$server->query('CardDAVSyncService'); - $this->dbConnection = $dbConnection; + $this->dbHandler = $dbHandler; } protected function configure() { @@ -48,8 +48,7 @@ class SyncFederationAddressBooks extends Command { $progress = new ProgressBar($output); $progress->start(); - $db = new DbHandler($this->dbConnection, null); - $trustedServers = $db->getAllServer(); + $trustedServers = $this->dbHandler->getAllServer(); foreach ($trustedServers as $trustedServer) { $progress->advance(); $url = $trustedServer['url']; @@ -66,7 +65,7 @@ class SyncFederationAddressBooks extends Command { ]; $newToken = $this->syncService->syncRemoteAddressBook($url, 'system', $sharedSecret, $syncToken, $targetPrincipal, $targetBookId, $targetBookProperties); if ($newToken !== $syncToken) { - $db->setServerStatus($url, TrustedServers::STATUS_OK, $newToken); + $this->dbHandler->setServerStatus($url, TrustedServers::STATUS_OK, $newToken); } } $progress->finish(); -- cgit v1.2.3 From ca8c9f6ad52c6171fdecc2348fefbeef7cc5d2a3 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Mon, 21 Dec 2015 17:32:21 +0100 Subject: federation has to be of type filesystem so that we load this app for webdav requests --- apps/federation/appinfo/info.xml | 3 +++ apps/federation/dav/fedauth.php | 3 +++ 2 files changed, 6 insertions(+) diff --git a/apps/federation/appinfo/info.xml b/apps/federation/appinfo/info.xml index bfb4ca8f8c9..54ea4831be0 100644 --- a/apps/federation/appinfo/info.xml +++ b/apps/federation/appinfo/info.xml @@ -11,4 +11,7 @@ + + + diff --git a/apps/federation/dav/fedauth.php b/apps/federation/dav/fedauth.php index 56173233bf3..09d61a1f2c7 100644 --- a/apps/federation/dav/fedauth.php +++ b/apps/federation/dav/fedauth.php @@ -25,6 +25,9 @@ use Sabre\DAV\Auth\Backend\AbstractBasic; class FedAuth extends AbstractBasic { + /** @var DbHandler */ + private $db; + /** * FedAuth constructor. * -- cgit v1.2.3 From 94856cb892bba5b123c3f7e9ebeb042c960f72dd Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Mon, 21 Dec 2015 17:32:39 +0100 Subject: Catch exceptions during sync --- apps/dav/lib/carddav/syncservice.php | 5 +---- apps/federation/command/syncfederationaddressbooks.php | 10 +++++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/dav/lib/carddav/syncservice.php b/apps/dav/lib/carddav/syncservice.php index 494db61d989..b8dfcfdbc5e 100644 --- a/apps/dav/lib/carddav/syncservice.php +++ b/apps/dav/lib/carddav/syncservice.php @@ -24,6 +24,7 @@ namespace OCA\DAV\CardDAV; use Sabre\DAV\Client; use Sabre\DAV\Xml\Response\MultiStatus; use Sabre\DAV\Xml\Service; +use Sabre\HTTP\ClientException; class SyncService { @@ -112,10 +113,6 @@ class SyncService { 'Content-Type' => 'application/xml' ]); -// if ((int)$response->getStatus() >= 400) { -// throw new Exception('HTTP error: ' . $response->getStatus()); -// } - $result = $this->parseMultiStatus($response['body']); return $result; diff --git a/apps/federation/command/syncfederationaddressbooks.php b/apps/federation/command/syncfederationaddressbooks.php index d7761d14814..9fb1e51f643 100644 --- a/apps/federation/command/syncfederationaddressbooks.php +++ b/apps/federation/command/syncfederationaddressbooks.php @@ -63,9 +63,13 @@ class SyncFederationAddressBooks extends Command { $targetBookProperties = [ '{DAV:}displayname' => $url ]; - $newToken = $this->syncService->syncRemoteAddressBook($url, 'system', $sharedSecret, $syncToken, $targetPrincipal, $targetBookId, $targetBookProperties); - if ($newToken !== $syncToken) { - $this->dbHandler->setServerStatus($url, TrustedServers::STATUS_OK, $newToken); + try { + $newToken = $this->syncService->syncRemoteAddressBook($url, 'system', $sharedSecret, $syncToken, $targetPrincipal, $targetBookId, $targetBookProperties); + if ($newToken !== $syncToken) { + $this->dbHandler->setServerStatus($url, TrustedServers::STATUS_OK, $newToken); + } + } catch (\Exception $ex) { + $output->writeln("Error while syncing $url : " . $ex->getMessage()); } } $progress->finish(); -- cgit v1.2.3 From fa561071d26ed0d28e90fddd01ea17c200ba17ed Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Mon, 11 Jan 2016 16:28:54 +0100 Subject: create urls in a way that sabredav handles it correctly --- apps/dav/lib/carddav/syncservice.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dav/lib/carddav/syncservice.php b/apps/dav/lib/carddav/syncservice.php index b8dfcfdbc5e..148ba4b9081 100644 --- a/apps/dav/lib/carddav/syncservice.php +++ b/apps/dav/lib/carddav/syncservice.php @@ -99,14 +99,14 @@ class SyncService { */ protected function requestSyncReport($url, $userName, $sharedSecret, $syncToken) { $settings = [ - 'baseUri' => $url, + 'baseUri' => $url . '/', 'userName' => $userName, 'password' => $sharedSecret, ]; $client = new Client($settings); $client->setThrowExceptions(true); - $addressBookUrl = "/remote.php/dav/addressbooks/system/system/system"; + $addressBookUrl = "remote.php/dav/addressbooks/system/system/system"; $body = $this->buildSyncCollectionRequestBody($syncToken); $response = $client->request('REPORT', $addressBookUrl, $body, [ -- cgit v1.2.3 From e7a8be258817f317319900f104d14417806bbc60 Mon Sep 17 00:00:00 2001 From: Björn Schießle Date: Mon, 11 Jan 2016 16:44:44 +0100 Subject: fix doc-block --- apps/federation/command/syncfederationaddressbooks.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/apps/federation/command/syncfederationaddressbooks.php b/apps/federation/command/syncfederationaddressbooks.php index 9fb1e51f643..516029d25ab 100644 --- a/apps/federation/command/syncfederationaddressbooks.php +++ b/apps/federation/command/syncfederationaddressbooks.php @@ -5,12 +5,8 @@ namespace OCA\Federation\Command; use OCA\DAV\CardDAV\SyncService; use OCA\Federation\DbHandler; use OCA\Federation\TrustedServers; -use OCP\IConfig; -use OCP\IDBConnection; -use OCP\IUserManager; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\ProgressBar; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -23,9 +19,7 @@ class SyncFederationAddressBooks extends Command { private $syncService; /** - * @param IUserManager $userManager - * @param IDBConnection $dbHandler - * @param IConfig $config + * @param DbHandler $dbHandler */ function __construct(DbHandler $dbHandler) { parent::__construct(); -- cgit v1.2.3 From 23a8c93fd2b4757e5e61297318b2ce7937ab9bb5 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Tue, 12 Jan 2016 14:08:10 +0100 Subject: Fix ctor call --- apps/dav/appinfo/app.php | 2 -- apps/dav/command/createaddressbook.php | 1 - apps/dav/command/syncsystemaddressbook.php | 1 - 3 files changed, 4 deletions(-) diff --git a/apps/dav/appinfo/app.php b/apps/dav/appinfo/app.php index 9d092d84eb4..f6c74c9c943 100644 --- a/apps/dav/appinfo/app.php +++ b/apps/dav/appinfo/app.php @@ -25,12 +25,10 @@ use OCA\DAV\Connector\Sabre\Principal; \OC::$server->registerService('CardDAVSyncService', function() { - $config = \OC::$server->getConfig(); $userManager = \OC::$server->getUserManager(); $dbConnection = \OC::$server->getDatabaseConnection(); $principalBackend = new Principal( - $config, $userManager ); diff --git a/apps/dav/command/createaddressbook.php b/apps/dav/command/createaddressbook.php index 7b70cea7f80..4d72c12954f 100644 --- a/apps/dav/command/createaddressbook.php +++ b/apps/dav/command/createaddressbook.php @@ -63,7 +63,6 @@ class CreateAddressBook extends Command { throw new \InvalidArgumentException("User <$user> in unknown."); } $principalBackend = new Principal( - $this->config, $this->userManager ); diff --git a/apps/dav/command/syncsystemaddressbook.php b/apps/dav/command/syncsystemaddressbook.php index 162ab362892..8e04df46098 100644 --- a/apps/dav/command/syncsystemaddressbook.php +++ b/apps/dav/command/syncsystemaddressbook.php @@ -57,7 +57,6 @@ class SyncSystemAddressBook extends Command { */ protected function execute(InputInterface $input, OutputInterface $output) { $principalBackend = new Principal( - $this->config, $this->userManager ); -- cgit v1.2.3 From bf1a2f28c2fae8de1441962208eb112e86266bcf Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Tue, 12 Jan 2016 14:27:50 +0100 Subject: Reuse backend as provided by the app container --- apps/dav/appinfo/app.php | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/apps/dav/appinfo/app.php b/apps/dav/appinfo/app.php index f6c74c9c943..51689b965da 100644 --- a/apps/dav/appinfo/app.php +++ b/apps/dav/appinfo/app.php @@ -21,18 +21,12 @@ use OCA\DAV\CardDAV\CardDavBackend; use OCA\DAV\CardDAV\SyncService; -use OCA\DAV\Connector\Sabre\Principal; \OC::$server->registerService('CardDAVSyncService', function() { - $userManager = \OC::$server->getUserManager(); - $dbConnection = \OC::$server->getDatabaseConnection(); - - $principalBackend = new Principal( - $userManager - ); - - $backend = new CardDavBackend($dbConnection, $principalBackend); + $app = new \OCA\Dav\AppInfo\Application(); + /** @var CardDavBackend */ + $backend = $app->getContainer()->query('CardDavBackend'); return new SyncService($backend); }); -- cgit v1.2.3