Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/dav/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@
'OCA\\DAV\\Listener\\CardListener' => $baseDir . '/../lib/Listener/CardListener.php',
'OCA\\DAV\\Listener\\ClearPhotoCacheListener' => $baseDir . '/../lib/Listener/ClearPhotoCacheListener.php',
'OCA\\DAV\\Listener\\SubscriptionListener' => $baseDir . '/../lib/Listener/SubscriptionListener.php',
'OCA\\DAV\\Listener\\TrustedServerRemovedListener' => $baseDir . '/../lib/Listener/TrustedServerRemovedListener.php',
'OCA\\DAV\\Migration\\BuildCalendarSearchIndex' => $baseDir . '/../lib/Migration/BuildCalendarSearchIndex.php',
'OCA\\DAV\\Migration\\BuildCalendarSearchIndexBackgroundJob' => $baseDir . '/../lib/Migration/BuildCalendarSearchIndexBackgroundJob.php',
'OCA\\DAV\\Migration\\BuildSocialSearchIndex' => $baseDir . '/../lib/Migration/BuildSocialSearchIndex.php',
Expand Down
1 change: 1 addition & 0 deletions apps/dav/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Listener\\CardListener' => __DIR__ . '/..' . '/../lib/Listener/CardListener.php',
'OCA\\DAV\\Listener\\ClearPhotoCacheListener' => __DIR__ . '/..' . '/../lib/Listener/ClearPhotoCacheListener.php',
'OCA\\DAV\\Listener\\SubscriptionListener' => __DIR__ . '/..' . '/../lib/Listener/SubscriptionListener.php',
'OCA\\DAV\\Listener\\TrustedServerRemovedListener' => __DIR__ . '/..' . '/../lib/Listener/TrustedServerRemovedListener.php',
'OCA\\DAV\\Migration\\BuildCalendarSearchIndex' => __DIR__ . '/..' . '/../lib/Migration/BuildCalendarSearchIndex.php',
'OCA\\DAV\\Migration\\BuildCalendarSearchIndexBackgroundJob' => __DIR__ . '/..' . '/../lib/Migration/BuildCalendarSearchIndexBackgroundJob.php',
'OCA\\DAV\\Migration\\BuildSocialSearchIndex' => __DIR__ . '/..' . '/../lib/Migration/BuildSocialSearchIndex.php',
Expand Down
15 changes: 3 additions & 12 deletions apps/dav/lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
use OCA\DAV\Events\CardUpdatedEvent;
use OCA\DAV\Events\SubscriptionCreatedEvent;
use OCA\DAV\Events\SubscriptionDeletedEvent;
use OCP\Federation\Events\TrustedServerRemovedEvent;
use OCA\DAV\HookManager;
use OCA\DAV\Listener\ActivityUpdaterListener;
use OCA\DAV\Listener\AddressbookListener;
Expand All @@ -83,6 +84,7 @@
use OCA\DAV\Listener\CardListener;
use OCA\DAV\Listener\ClearPhotoCacheListener;
use OCA\DAV\Listener\SubscriptionListener;
use OCA\DAV\Listener\TrustedServerRemovedListener;
use OCA\DAV\Search\ContactsSearchProvider;
use OCA\DAV\Search\EventsSearchProvider;
use OCA\DAV\Search\TasksSearchProvider;
Expand Down Expand Up @@ -182,6 +184,7 @@ public function register(IRegistrationContext $context): void {
$context->registerEventListener(CardUpdatedEvent::class, BirthdayListener::class);
$context->registerEventListener(CardDeletedEvent::class, ClearPhotoCacheListener::class);
$context->registerEventListener(CardUpdatedEvent::class, ClearPhotoCacheListener::class);
$context->registerEventListener(TrustedServerRemovedEvent::class, TrustedServerRemovedListener::class);

$context->registerNotifierService(Notifier::class);

Expand Down Expand Up @@ -235,18 +238,6 @@ public function registerHooks(HookManager $hm,
// Here we should recalculate if reminders should be sent to new or old sharees
});

$dispatcher->addListener('OCP\Federation\TrustedServerEvent::remove',
function (GenericEvent $event) {
/** @var CardDavBackend $cardDavBackend */
$cardDavBackend = \OC::$server->query(CardDavBackend::class);
$addressBookUri = $event->getSubject();
$addressBook = $cardDavBackend->getAddressBooksByUri('principals/system/system', $addressBookUri);
if (!is_null($addressBook)) {
$cardDavBackend->deleteAddressBook($addressBook['id']);
}
}
);

$eventHandler = function () use ($container, $serverContainer): void {
try {
/** @var UpdateCalendarResourcesRoomsBackgroundJob $job */
Expand Down
8 changes: 2 additions & 6 deletions apps/dav/lib/CardDAV/CardDavBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,18 +296,14 @@ public function getAddressBookById(int $addressBookId): ?array {
return $addressBook;
}

/**
* @param $addressBookUri
* @return array|null
*/
public function getAddressBooksByUri($principal, $addressBookUri) {
public function getAddressBooksByUri(string $principal, string $addressBookUri): ?array {
$query = $this->db->getQueryBuilder();
$result = $query->select(['id', 'uri', 'displayname', 'principaluri', 'description', 'synctoken'])
->from('addressbooks')
->where($query->expr()->eq('uri', $query->createNamedParameter($addressBookUri)))
->andWhere($query->expr()->eq('principaluri', $query->createNamedParameter($principal)))
->setMaxResults(1)
->execute();
->executeQuery();

$row = $result->fetch();
$result->closeCursor();
Expand Down
88 changes: 17 additions & 71 deletions apps/dav/lib/CardDAV/SyncService.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,13 @@
use Sabre\VObject\Reader;

class SyncService {

/** @var CardDavBackend */
private $backend;

/** @var IUserManager */
private $userManager;

private CardDavBackend $backend;
private IUserManager $userManager;
private LoggerInterface $logger;
private ?array $localSystemAddressBook = null;
private Converter $converter;
protected string $certPath;

/** @var array */
private $localSystemAddressBook;

/** @var Converter */
private $converter;

/** @var string */
protected $certPath;

/**
* SyncService constructor.
*/
public function __construct(CardDavBackend $backend,
IUserManager $userManager,
LoggerInterface $logger,
Expand All @@ -73,20 +59,11 @@ public function __construct(CardDavBackend $backend,
}

/**
* @param string $url
* @param string $userName
* @param string $addressBookUrl
* @param string $sharedSecret
* @param string $syncToken
* @param int $targetBookId
* @param string $targetPrincipal
* @param array $targetProperties
* @return string
* @throws \Exception
*/
public function syncRemoteAddressBook($url, $userName, $addressBookUrl, $sharedSecret, $syncToken, $targetBookId, $targetPrincipal, $targetProperties) {
public function syncRemoteAddressBook(string $url, string $userName, string $addressBookUrl, string $sharedSecret, ?string $syncToken, string $targetBookHash, string $targetPrincipal, array $targetProperties): string {
// 1. create addressbook
$book = $this->ensureSystemAddressBookExists($targetPrincipal, (string)$targetBookId, $targetProperties);
$book = $this->ensureSystemAddressBookExists($targetPrincipal, $targetBookHash, $targetProperties);
$addressBookId = $book['id'];

// 2. query changes
Expand Down Expand Up @@ -122,28 +99,23 @@ public function syncRemoteAddressBook($url, $userName, $addressBookUrl, $sharedS
}

/**
* @param string $principal
* @param string $id
* @param array $properties
* @return array|null
* @throws \Sabre\DAV\Exception\BadRequest
*/
public function ensureSystemAddressBookExists($principal, $id, $properties) {
$book = $this->backend->getAddressBooksByUri($principal, $id);
public function ensureSystemAddressBookExists(string $principal, string $uri, array $properties): ?array {
$book = $this->backend->getAddressBooksByUri($principal, $uri);
if (!is_null($book)) {
return $book;
}
$this->backend->createAddressBook($principal, $id, $properties);
// FIXME This might break in clustered DB setup
$this->backend->createAddressBook($principal, $uri, $properties);

return $this->backend->getAddressBooksByUri($principal, $id);
return $this->backend->getAddressBooksByUri($principal, $uri);
}

/**
* Check if there is a valid certPath we should use
*
* @return string
*/
protected function getCertPath() {
protected function getCertPath(): string {

// we already have a valid certPath
if ($this->certPath !== '') {
Expand All @@ -159,14 +131,7 @@ protected function getCertPath() {
return $this->certPath;
}

/**
* @param string $url
* @param string $userName
* @param string $addressBookUrl
* @param string $sharedSecret
* @return Client
*/
protected function getClient($url, $userName, $sharedSecret) {
protected function getClient(string $url, string $userName, string $sharedSecret): Client {
$settings = [
'baseUri' => $url . '/',
'userName' => $userName,
Expand All @@ -183,15 +148,7 @@ protected function getClient($url, $userName, $sharedSecret) {
return $client;
}

/**
* @param string $url
* @param string $userName
* @param string $addressBookUrl
* @param string $sharedSecret
* @param string $syncToken
* @return array
*/
protected function requestSyncReport($url, $userName, $addressBookUrl, $sharedSecret, $syncToken) {
protected function requestSyncReport(string $url, string $userName, string $addressBookUrl, string $sharedSecret, ?string $syncToken): array {
$client = $this->getClient($url, $userName, $sharedSecret);

$body = $this->buildSyncCollectionRequestBody($syncToken);
Expand All @@ -203,23 +160,12 @@ protected function requestSyncReport($url, $userName, $addressBookUrl, $sharedSe
return $this->parseMultiStatus($response['body']);
}

/**
* @param string $url
* @param string $userName
* @param string $sharedSecret
* @param string $resourcePath
* @return array
*/
protected function download($url, $userName, $sharedSecret, $resourcePath) {
protected function download(string $url, string $userName, string $sharedSecret, string $resourcePath): array {
$client = $this->getClient($url, $userName, $sharedSecret);
return $client->request('GET', $resourcePath);
}

/**
* @param string|null $syncToken
* @return string
*/
private function buildSyncCollectionRequestBody($syncToken) {
private function buildSyncCollectionRequestBody(?string $syncToken): string {
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$root = $dom->createElementNS('DAV:', 'd:sync-collection');
Expand Down
50 changes: 50 additions & 0 deletions apps/dav/lib/Listener/TrustedServerRemovedListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

/**
* @copyright 2022 Carl Schwan <[email protected]>
*
* @author Carl Schwan <[email protected]>
*
* @license AGPL-3.0-or-later
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\DAV\Listener;

use OCA\DAV\CardDAV\CardDavBackend;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Federation\Events\TrustedServerRemovedEvent;

class TrustedServerRemovedListener implements IEventListener {
private CardDavBackend $cardDavBackend;

public function __construct(CardDavBackend $cardDavBackend) {
$this->cardDavBackend = $cardDavBackend;
}

public function handle(Event $event): void {
if (!$event instanceof TrustedServerRemovedEvent) {
return;
}
$addressBookUri = $event->getUrlHash();
$addressBook = $this->cardDavBackend->getAddressBooksByUri('principals/system/system', $addressBookUri);
if (!is_null($addressBook)) {
$this->cardDavBackend->deleteAddressBook($addressBook['id']);
}
}
}
67 changes: 22 additions & 45 deletions apps/federation/lib/BackgroundJob/GetSharedSecret.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,59 +42,34 @@
use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\OCS\IDiscoveryService;
use Psr\Log\LoggerInterface;

/**
* Class GetSharedSecret
*
* request shared secret from remote Nextcloud
* Request shared secret from remote Nextcloud
*
* @package OCA\Federation\Backgroundjob
*/
class GetSharedSecret extends Job {
private IClient $httpClient;
private IJobList $jobList;
private IURLGenerator $urlGenerator;
private TrustedServers $trustedServers;
private IDiscoveryService $ocsDiscoveryService;
private LoggerInterface $logger;
protected bool $retainJob = false;
private string $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret';

/** 30 day = 2592000sec */
private int $maxLifespan = 2592000;

/** @var IClient */
private $httpClient;

/** @var IJobList */
private $jobList;

/** @var IURLGenerator */
private $urlGenerator;

/** @var TrustedServers */
private $trustedServers;

/** @var IDiscoveryService */
private $ocsDiscoveryService;

/** @var ILogger */
private $logger;

/** @var bool */
protected $retainJob = false;

private $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret';

/** @var int 30 day = 2592000sec */
private $maxLifespan = 2592000;

/**
* RequestSharedSecret constructor.
*
* @param IClientService $httpClientService
* @param IURLGenerator $urlGenerator
* @param IJobList $jobList
* @param TrustedServers $trustedServers
* @param ILogger $logger
* @param IDiscoveryService $ocsDiscoveryService
* @param ITimeFactory $timeFactory
*/
public function __construct(
IClientService $httpClientService,
IURLGenerator $urlGenerator,
IJobList $jobList,
TrustedServers $trustedServers,
ILogger $logger,
LoggerInterface $logger,
IDiscoveryService $ocsDiscoveryService,
ITimeFactory $timeFactory
) {
Expand Down Expand Up @@ -128,7 +103,7 @@ public function execute(IJobList $jobList, ILogger $logger = null) {
}

/**
* call execute() method of parent
* Call execute() method of parent
*
* @param IJobList $jobList
* @param ILogger $logger
Expand Down Expand Up @@ -185,14 +160,16 @@ protected function run($argument) {
}
} catch (RequestException $e) {
$status = -1; // There is no status code if we could not connect
$this->logger->logException($e, [
'message' => 'Could not connect to ' . $target,
'level' => ILogger::INFO,
$this->logger->info('Could not connect to ' . $target, [
'exception' => $e,
'app' => 'federation',
]);
} catch (\Throwable $e) {
$status = Http::STATUS_INTERNAL_SERVER_ERROR;
$this->logger->logException($e, ['app' => 'federation']);
$this->logger->error($e->getMessage(), [
'app' => 'federation',
'exception' => $e,
]);
}

// if we received a unexpected response we try again later
Expand Down Expand Up @@ -226,7 +203,7 @@ protected function run($argument) {
*
* @param array $argument
*/
protected function reAddJob(array $argument) {
protected function reAddJob(array $argument): void {
$url = $argument['url'];
$created = isset($argument['created']) ? (int)$argument['created'] : $this->time->getTime();
$token = $argument['token'];
Expand Down
Loading