From e93752aef86ba3a1e5becab89a3fe5fbe027a41a Mon Sep 17 00:00:00 2001 From: Hamza Mahjoubi Date: Sun, 12 Jan 2025 15:53:56 +0700 Subject: [PATCH] fixup! feat(cardav): support result truncation for addressbook federation Signed-off-by: Hamza Mahjoubi --- apps/dav/lib/CardDAV/CardDavBackend.php | 17 ++++++++++++++--- apps/dav/lib/CardDAV/SyncService.php | 9 ++------- apps/dav/lib/CardDAV/SystemAddressbook.php | 2 +- apps/dav/lib/RootCollection.php | 6 ++++++ apps/dav/lib/Server.php | 3 ++- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index daad251d77899..f1237ae70e394 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -21,6 +21,8 @@ use OCA\DAV\Events\CardUpdatedEvent; use OCP\AppFramework\Db\TTransactional; use OCP\DB\Exception; +use Psr\Log\LoggerInterface; +use OCP\IConfig; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\IEventDispatcher; use OCP\IDBConnection; @@ -59,6 +61,8 @@ public function __construct( private IUserManager $userManager, private IEventDispatcher $dispatcher, private Sharing\Backend $sharingBackend, + private LoggerInterface $logger, + private IConfig $config, ) { } @@ -851,6 +855,10 @@ public function deleteCard($addressBookId, $cardUri) { * @return array */ public function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel, $limit = null) { + if($limit === null){ + $limit = $this->config->getSystemValueInt('carddav_sync_request_limit',1); + + } // Current synctoken return $this->atomic(function () use ($addressBookId, $syncToken, $syncLevel, $limit) { $qb = $this->db->getQueryBuilder(); @@ -873,6 +881,7 @@ public function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel, 'modified' => [], 'deleted' => [], ]; + $this->logger->error('getChangesForAddressBook', ['syncToken' => $syncToken, 'currentToken' => $currentToken, 'limit' => $limit]); if(str_starts_with($syncToken, "init_")) { $syncValues = explode("_", $syncToken); $lastID = $syncValues[1]; @@ -949,8 +958,8 @@ public function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel, if (is_int($limit) && $limit > 0) { $qb->setMaxResults($limit); $stmt = $qb->executeQuery(); - $values = $stmt->fetchAll(\PDO::FETCH_KEY_PAIR); - $lastID = array_key_last($values); + $values = $stmt->fetchAll(\PDO::FETCH_ASSOC); + $lastID = end($values)['id']; if(count(array_values($values)) === $limit ){ $result['syncToken'] = 'init_'. $lastID.'_'.$currentToken; $result['result_truncated'] = true; @@ -958,8 +967,10 @@ public function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel, } else { $stmt = $qb->executeQuery(); + $values = $stmt->fetchAll(\PDO::FETCH_ASSOC); + $this->logger->error('getChangesForAddressBook', ['values' => $values]); } - $result['added'] = array_values($values); + $result['added'] =array_column($values, 'uri'); $stmt->closeCursor(); } diff --git a/apps/dav/lib/CardDAV/SyncService.php b/apps/dav/lib/CardDAV/SyncService.php index ff84c0fb486c1..cf597d078a39c 100644 --- a/apps/dav/lib/CardDAV/SyncService.php +++ b/apps/dav/lib/CardDAV/SyncService.php @@ -63,6 +63,7 @@ public function syncRemoteAddressBook(string $url, string $userName, string $add $this->logger->error('Client exception:', ['app' => 'dav', 'exception' => $ex]); throw $ex; } + $this->logger->error('sync response',[$response]); // 3. apply changes // TODO: use multi-get for download @@ -162,7 +163,7 @@ protected function requestSyncReport(string $url, string $userName, string $addr 'auth' => [$userName, $sharedSecret], 'body' => $this->buildSyncCollectionRequestBody($syncToken), 'headers' => ['Content-Type' => 'application/xml'], - 'timeout' => $this->config->getSystemValueInt('carddav_sync_request_timeout', IClient::DEFAULT_REQUEST_TIMEOUT), + 'timeout' => $this->config->getSystemValueInt('carddav_sync_request_timeout', IClient::DEFAULT_REQUEST_TIMEOUT) ]; $response = $client->request( @@ -194,23 +195,17 @@ protected function download(string $url, string $userName, string $sharedSecret, } private function buildSyncCollectionRequestBody(?string $syncToken): string { - $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->formatOutput = true; $root = $dom->createElementNS('DAV:', 'd:sync-collection'); $sync = $dom->createElement('d:sync-token', $syncToken ?? ''); - $limit = $dom->createElement('d:limit'); - $nresuts = $dom->createElement('d:nresults',$this->config->getSystemValueInt('carddav_sync_request_limit',IClient::DEFAULT_ADDRESSBOOK_INITIAL_SYNC_LIMIT)); - $limit->appendChild($nresuts); $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($limit); $root->appendChild($prop); $dom->appendChild($root); return $dom->saveXML(); diff --git a/apps/dav/lib/CardDAV/SystemAddressbook.php b/apps/dav/lib/CardDAV/SystemAddressbook.php index ee066bf97d7c8..4270a87fc4418 100644 --- a/apps/dav/lib/CardDAV/SystemAddressbook.php +++ b/apps/dav/lib/CardDAV/SystemAddressbook.php @@ -211,7 +211,7 @@ public function getChild($name): Card { $obj['carddata'] = $carddata; } return new Card($this->carddavBackend, $this->addressBookInfo, $obj); - } + } public function getChanges($syncToken, $syncLevel, $limit = null) { if (!$this->carddavBackend instanceof SyncSupport) { diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php index 751ab17bb7aa6..014c9b192a519 100644 --- a/apps/dav/lib/RootCollection.php +++ b/apps/dav/lib/RootCollection.php @@ -124,6 +124,8 @@ public function __construct() { ); $contactsSharingBackend = \OC::$server->get(\OCA\DAV\CardDAV\Sharing\Backend::class); + $logger = \OC::$server->get(\Psr\Log\LoggerInterface::class); + $config = \OC::$server->get(IConfig::class); $pluginManager = new PluginManager(\OC::$server, \OC::$server->query(IAppManager::class)); $usersCardDavBackend = new CardDavBackend( @@ -132,6 +134,8 @@ public function __construct() { $userManager, $dispatcher, $contactsSharingBackend, + $logger, + $config ); $usersAddressBookRoot = new AddressBookRoot($userPrincipalBackend, $usersCardDavBackend, $pluginManager, $userSession->getUser(), $groupManager, 'principals/users'); $usersAddressBookRoot->disableListing = $disableListing; @@ -142,6 +146,8 @@ public function __construct() { $userManager, $dispatcher, $contactsSharingBackend, + $logger, + $config ); $systemAddressBookRoot = new AddressBookRoot(new SystemPrincipalBackend(), $systemCardDavBackend, $pluginManager, $userSession->getUser(), $groupManager, 'principals/system'); $systemAddressBookRoot->disableListing = $disableListing; diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index f07927ff0f95b..2ed316d7ee240 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -160,7 +160,8 @@ public function __construct( $this->server->addPlugin(new ExceptionLoggerPlugin('webdav', $logger)); $this->server->addPlugin(new LockPlugin()); - $this->server->addPlugin(new \Sabre\DAV\Sync\Plugin()); + $logger = \OC::$server->get(LoggerInterface::class); + $this->server->addPlugin(new \Sabre\DAV\Sync\Plugin($logger)); // acl $acl = new DavAclPlugin();