SyncFederationAddressBooks.php 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\Federation;
  8. use OC\OCS\DiscoveryService;
  9. use OCA\DAV\CardDAV\SyncService;
  10. use OCP\AppFramework\Http;
  11. use OCP\OCS\IDiscoveryService;
  12. use Psr\Log\LoggerInterface;
  13. class SyncFederationAddressBooks {
  14. private DiscoveryService $ocsDiscoveryService;
  15. public function __construct(
  16. protected DbHandler $dbHandler,
  17. private SyncService $syncService,
  18. IDiscoveryService $ocsDiscoveryService,
  19. private LoggerInterface $logger,
  20. ) {
  21. $this->ocsDiscoveryService = $ocsDiscoveryService;
  22. }
  23. /**
  24. * @param \Closure $callback
  25. */
  26. public function syncThemAll(\Closure $callback) {
  27. $trustedServers = $this->dbHandler->getAllServer();
  28. foreach ($trustedServers as $trustedServer) {
  29. $url = $trustedServer['url'];
  30. $callback($url, null);
  31. $sharedSecret = $trustedServer['shared_secret'];
  32. $syncToken = $trustedServer['sync_token'];
  33. $endPoints = $this->ocsDiscoveryService->discover($url, 'FEDERATED_SHARING');
  34. $cardDavUser = $endPoints['carddav-user'] ?? 'system';
  35. $addressBookUrl = isset($endPoints['system-address-book']) ? trim($endPoints['system-address-book'], '/') : 'remote.php/dav/addressbooks/system/system/system';
  36. if (is_null($sharedSecret)) {
  37. $this->logger->debug("Shared secret for $url is null");
  38. continue;
  39. }
  40. $targetBookId = $trustedServer['url_hash'];
  41. $targetPrincipal = 'principals/system/system';
  42. $targetBookProperties = [
  43. '{DAV:}displayname' => $url
  44. ];
  45. try {
  46. $newToken = $this->syncService->syncRemoteAddressBook($url, $cardDavUser, $addressBookUrl, $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetBookProperties);
  47. if ($newToken !== $syncToken) {
  48. $this->dbHandler->setServerStatus($url, TrustedServers::STATUS_OK, $newToken);
  49. } else {
  50. $this->logger->debug("Sync Token for $url unchanged from previous sync");
  51. // The server status might have been changed to a failure status in previous runs.
  52. if ($this->dbHandler->getServerStatus($url) !== TrustedServers::STATUS_OK) {
  53. $this->dbHandler->setServerStatus($url, TrustedServers::STATUS_OK);
  54. }
  55. }
  56. } catch (\Exception $ex) {
  57. if ($ex->getCode() === Http::STATUS_UNAUTHORIZED) {
  58. $this->dbHandler->setServerStatus($url, TrustedServers::STATUS_ACCESS_REVOKED);
  59. $this->logger->error("Server sync for $url failed because of revoked access.", [
  60. 'exception' => $ex,
  61. ]);
  62. } else {
  63. $this->dbHandler->setServerStatus($url, TrustedServers::STATUS_FAILURE);
  64. $this->logger->error("Server sync for $url failed.", [
  65. 'exception' => $ex,
  66. ]);
  67. }
  68. $callback($url, $ex);
  69. }
  70. }
  71. }
  72. }