Skip to content

Commit c387d6d

Browse files
committed
feat(federation): Add accept/decline mechanism for federated calendars
feat(federation): Add accept/decline mechanism for federated calendars Signed-off-by: David Dreschner <david.dreschner@nextcloud.com> [skip ci]
1 parent 09dc693 commit c387d6d

18 files changed

Lines changed: 855 additions & 30 deletions

apps/dav/appinfo/routes.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
],
1616
'ocs' => [
1717
['name' => 'direct#getUrl', 'url' => '/api/v1/direct', 'verb' => 'POST'],
18+
['name' => 'federated_calendar#getPending', 'url' => '/api/v1/federated_calendars/pending', 'verb' => 'GET'],
19+
['name' => 'federated_calendar#accept', 'url' => '/api/v1/federated_calendars/pending/{id}', 'verb' => 'POST'],
20+
['name' => 'federated_calendar#decline', 'url' => '/api/v1/federated_calendars/pending/{id}', 'verb' => 'DELETE'],
1821
['name' => 'upcoming_events#getEvents', 'url' => '/api/v1/events/upcoming', 'verb' => 'GET'],
1922
['name' => 'out_of_office#getCurrentOutOfOfficeData', 'url' => '/api/v1/outOfOffice/{userId}/now', 'verb' => 'GET'],
2023
['name' => 'out_of_office#getOutOfOffice', 'url' => '/api/v1/outOfOffice/{userId}', 'verb' => 'GET'],

apps/dav/composer/composer/autoload_classmap.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@
7676
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarEntity' => $baseDir . '/../lib/CalDAV/Federation/FederatedCalendarEntity.php',
7777
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarFactory' => $baseDir . '/../lib/CalDAV/Federation/FederatedCalendarFactory.php',
7878
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarImpl' => $baseDir . '/../lib/CalDAV/Federation/FederatedCalendarImpl.php',
79+
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarInvitationService' => $baseDir . '/../lib/CalDAV/Federation/FederatedCalendarInvitationService.php',
80+
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarInviteNotifier' => $baseDir . '/../lib/CalDAV/Federation/FederatedCalendarInviteNotifier.php',
7981
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarMapper' => $baseDir . '/../lib/CalDAV/Federation/FederatedCalendarMapper.php',
8082
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarSyncService' => $baseDir . '/../lib/CalDAV/Federation/FederatedCalendarSyncService.php',
8183
'OCA\\DAV\\CalDAV\\Federation\\FederationSharingService' => $baseDir . '/../lib/CalDAV/Federation/FederationSharingService.php',
@@ -259,6 +261,7 @@
259261
'OCA\\DAV\\Controller\\BirthdayCalendarController' => $baseDir . '/../lib/Controller/BirthdayCalendarController.php',
260262
'OCA\\DAV\\Controller\\DirectController' => $baseDir . '/../lib/Controller/DirectController.php',
261263
'OCA\\DAV\\Controller\\ExampleContentController' => $baseDir . '/../lib/Controller/ExampleContentController.php',
264+
'OCA\\DAV\\Controller\\FederatedCalendarController' => $baseDir . '/../lib/Controller/FederatedCalendarController.php',
262265
'OCA\\DAV\\Controller\\InvitationResponseController' => $baseDir . '/../lib/Controller/InvitationResponseController.php',
263266
'OCA\\DAV\\Controller\\OutOfOfficeController' => $baseDir . '/../lib/Controller/OutOfOfficeController.php',
264267
'OCA\\DAV\\Controller\\UpcomingEventsController' => $baseDir . '/../lib/Controller/UpcomingEventsController.php',
@@ -388,6 +391,7 @@
388391
'OCA\\DAV\\Migration\\Version1031Date20240610134258' => $baseDir . '/../lib/Migration/Version1031Date20240610134258.php',
389392
'OCA\\DAV\\Migration\\Version1034Date20250605132605' => $baseDir . '/../lib/Migration/Version1034Date20250605132605.php',
390393
'OCA\\DAV\\Migration\\Version1034Date20250813093701' => $baseDir . '/../lib/Migration/Version1034Date20250813093701.php',
394+
'OCA\\DAV\\Migration\\Version1040Date20260805000000' => $baseDir . '/../lib/Migration/Version1040Date20260805000000.php',
391395
'OCA\\DAV\\Model\\ExampleEvent' => $baseDir . '/../lib/Model/ExampleEvent.php',
392396
'OCA\\DAV\\Paginate\\LimitedCopyIterator' => $baseDir . '/../lib/Paginate/LimitedCopyIterator.php',
393397
'OCA\\DAV\\Paginate\\PaginateCache' => $baseDir . '/../lib/Paginate/PaginateCache.php',

apps/dav/composer/composer/autoload_static.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ class ComposerStaticInitDAV
9191
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarEntity' => __DIR__ . '/..' . '/../lib/CalDAV/Federation/FederatedCalendarEntity.php',
9292
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarFactory' => __DIR__ . '/..' . '/../lib/CalDAV/Federation/FederatedCalendarFactory.php',
9393
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarImpl' => __DIR__ . '/..' . '/../lib/CalDAV/Federation/FederatedCalendarImpl.php',
94+
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarInvitationService' => __DIR__ . '/..' . '/../lib/CalDAV/Federation/FederatedCalendarInvitationService.php',
95+
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarInviteNotifier' => __DIR__ . '/..' . '/../lib/CalDAV/Federation/FederatedCalendarInviteNotifier.php',
9496
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarMapper' => __DIR__ . '/..' . '/../lib/CalDAV/Federation/FederatedCalendarMapper.php',
9597
'OCA\\DAV\\CalDAV\\Federation\\FederatedCalendarSyncService' => __DIR__ . '/..' . '/../lib/CalDAV/Federation/FederatedCalendarSyncService.php',
9698
'OCA\\DAV\\CalDAV\\Federation\\FederationSharingService' => __DIR__ . '/..' . '/../lib/CalDAV/Federation/FederationSharingService.php',
@@ -274,6 +276,7 @@ class ComposerStaticInitDAV
274276
'OCA\\DAV\\Controller\\BirthdayCalendarController' => __DIR__ . '/..' . '/../lib/Controller/BirthdayCalendarController.php',
275277
'OCA\\DAV\\Controller\\DirectController' => __DIR__ . '/..' . '/../lib/Controller/DirectController.php',
276278
'OCA\\DAV\\Controller\\ExampleContentController' => __DIR__ . '/..' . '/../lib/Controller/ExampleContentController.php',
279+
'OCA\\DAV\\Controller\\FederatedCalendarController' => __DIR__ . '/..' . '/../lib/Controller/FederatedCalendarController.php',
277280
'OCA\\DAV\\Controller\\InvitationResponseController' => __DIR__ . '/..' . '/../lib/Controller/InvitationResponseController.php',
278281
'OCA\\DAV\\Controller\\OutOfOfficeController' => __DIR__ . '/..' . '/../lib/Controller/OutOfOfficeController.php',
279282
'OCA\\DAV\\Controller\\UpcomingEventsController' => __DIR__ . '/..' . '/../lib/Controller/UpcomingEventsController.php',
@@ -403,6 +406,7 @@ class ComposerStaticInitDAV
403406
'OCA\\DAV\\Migration\\Version1031Date20240610134258' => __DIR__ . '/..' . '/../lib/Migration/Version1031Date20240610134258.php',
404407
'OCA\\DAV\\Migration\\Version1034Date20250605132605' => __DIR__ . '/..' . '/../lib/Migration/Version1034Date20250605132605.php',
405408
'OCA\\DAV\\Migration\\Version1034Date20250813093701' => __DIR__ . '/..' . '/../lib/Migration/Version1034Date20250813093701.php',
409+
'OCA\\DAV\\Migration\\Version1040Date20260805000000' => __DIR__ . '/..' . '/../lib/Migration/Version1040Date20260805000000.php',
406410
'OCA\\DAV\\Model\\ExampleEvent' => __DIR__ . '/..' . '/../lib/Model/ExampleEvent.php',
407411
'OCA\\DAV\\Paginate\\LimitedCopyIterator' => __DIR__ . '/..' . '/../lib/Paginate/LimitedCopyIterator.php',
408412
'OCA\\DAV\\Paginate\\PaginateCache' => __DIR__ . '/..' . '/../lib/Paginate/PaginateCache.php',

apps/dav/lib/AppInfo/Application.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use OCA\DAV\CalDAV\CalendarManager;
1515
use OCA\DAV\CalDAV\CalendarProvider;
1616
use OCA\DAV\CalDAV\Federation\CalendarFederationProvider;
17+
use OCA\DAV\CalDAV\Federation\FederatedCalendarInviteNotifier;
1718
use OCA\DAV\CalDAV\Reminder\NotificationProvider\AudioProvider;
1819
use OCA\DAV\CalDAV\Reminder\NotificationProvider\EmailProvider;
1920
use OCA\DAV\CalDAV\Reminder\NotificationProvider\PushProvider;
@@ -212,6 +213,7 @@ public function register(IRegistrationContext $context): void {
212213
$context->registerEventListener(CalendarObjectDeletedEvent::class, CalendarFederationNotificationListener::class);
213214

214215
$context->registerNotifierService(Notifier::class);
216+
$context->registerNotifierService(FederatedCalendarInviteNotifier::class);
215217

216218
$context->registerCalendarProvider(CalendarProvider::class);
217219
$context->registerCalendarProvider(CachedSubscriptionProvider::class);

apps/dav/lib/BackgroundJob/FederatedCalendarSyncJob.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
namespace OCA\DAV\BackgroundJob;
1111

1212
use OCA\DAV\CalDAV\Federation\CalendarFederationConfig;
13+
use OCA\DAV\CalDAV\Federation\FederatedCalendarEntity;
1314
use OCA\DAV\CalDAV\Federation\FederatedCalendarMapper;
1415
use OCA\DAV\CalDAV\Federation\FederatedCalendarSyncService;
1516
use OCP\AppFramework\Db\DoesNotExistException;
@@ -50,6 +51,11 @@ protected function run($argument): void {
5051
return;
5152
}
5253

54+
// Never fetch data for invitations the sharee did not accept (yet)
55+
if ($calendar->getState() !== FederatedCalendarEntity::STATE_ACCEPTED) {
56+
return;
57+
}
58+
5359
try {
5460
$this->syncService->syncOne($calendar);
5561
} catch (ClientExceptionInterface $e) {

apps/dav/lib/CalDAV/CalDavBackend.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4049,7 +4049,10 @@ public function unshare(IShareable $shareable, string $principal): void {
40494049
* @return array<string, mixed>[]
40504050
*/
40514051
public function getFederatedCalendarsForUser(string $principalUri): array {
4052-
$federatedCalendars = $this->federatedCalendarMapper->findByPrincipalUri($principalUri);
4052+
$federatedCalendars = $this->federatedCalendarMapper->findByPrincipalUri(
4053+
$principalUri,
4054+
FederatedCalendarEntity::STATE_ACCEPTED,
4055+
);
40534056
return array_map(
40544057
static fn (FederatedCalendarEntity $entity) => $entity->toCalendarInfo(),
40554058
$federatedCalendars,
@@ -4058,6 +4061,10 @@ public function getFederatedCalendarsForUser(string $principalUri): array {
40584061

40594062
public function getFederatedCalendarByUri(string $principalUri, string $uri): ?array {
40604063
$federatedCalendar = $this->federatedCalendarMapper->findByUri($principalUri, $uri);
4061-
return $federatedCalendar?->toCalendarInfo();
4064+
if ($federatedCalendar === null
4065+
|| $federatedCalendar->getState() !== FederatedCalendarEntity::STATE_ACCEPTED) {
4066+
return null;
4067+
}
4068+
return $federatedCalendar->toCalendarInfo();
40624069
}
40634070
}

apps/dav/lib/CalDAV/Federation/CalendarFederationConfig.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,11 @@ public function isIncomingServer2serverShareEnabled(): bool {
4141
}
4242
return $this->appConfig->getValueBool('files_sharing', 'incoming_server2server_share_enabled', true);
4343
}
44+
45+
/**
46+
* Check if incoming shares from trusted servers are accepted automatically
47+
*/
48+
public function isTrustedShareAutoAcceptEnabled(): bool {
49+
return $this->appConfig->getValueBool('files_sharing', 'federatedTrustedShareAutoAccept', true);
50+
}
4451
}

apps/dav/lib/CalDAV/Federation/CalendarFederationProvider.php

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public function __construct(
3535
private readonly CalendarFederationConfig $calendarFederationConfig,
3636
private readonly IJobList $jobList,
3737
private readonly ICloudIdManager $cloudIdManager,
38+
private readonly FederatedCalendarInvitationService $invitationService,
3839
) {
3940
}
4041

@@ -122,25 +123,49 @@ public function shareReceived(ICloudFederationShare $share): string {
122123

123124
$sharedWithPrincipal = 'principals/users/' . $share->getShareWith();
124125

125-
// Delete existing incoming federated share first
126-
$this->federatedCalendarMapper->deleteByUri($sharedWithPrincipal, $calendarUri);
127-
128-
$calendar = new FederatedCalendarEntity();
129-
$calendar->setPrincipaluri($sharedWithPrincipal);
130-
$calendar->setUri($calendarUri);
131-
$calendar->setRemoteUrl($calendarUrl);
132-
$calendar->setDisplayName($displayName);
133-
$calendar->setColor($color);
134-
$calendar->setToken($share->getShareSecret());
135-
$calendar->setSharedBy($share->getSharedBy());
136-
$calendar->setSharedByDisplayName($share->getSharedByDisplayName());
137-
$calendar->setPermissions($permissions);
138-
$calendar->setComponents($components);
139-
$calendar = $this->federatedCalendarMapper->insert($calendar);
140-
141-
$this->jobList->add(FederatedCalendarSyncJob::class, [
142-
FederatedCalendarSyncJob::ARGUMENT_ID => $calendar->getId(),
143-
]);
126+
$calendar = $this->federatedCalendarMapper->findByUri($sharedWithPrincipal, $calendarUri);
127+
$isNew = $calendar === null;
128+
129+
if ($calendar === null) {
130+
$calendar = new FederatedCalendarEntity();
131+
$calendar->setPrincipaluri($sharedWithPrincipal);
132+
$calendar->setUri($calendarUri);
133+
$calendar->setRemoteUrl($calendarUrl);
134+
$calendar->setDisplayName($displayName);
135+
$calendar->setColor($color);
136+
$calendar->setToken($share->getShareSecret());
137+
$calendar->setSharedBy($share->getSharedBy());
138+
$calendar->setSharedByDisplayName($share->getSharedByDisplayName());
139+
$calendar->setPermissions($permissions);
140+
$calendar->setComponents($components);
141+
$calendar->setState(FederatedCalendarEntity::STATE_PENDING);
142+
$calendar = $this->federatedCalendarMapper->insert($calendar);
143+
} else {
144+
$calendar->setToken($share->getShareSecret());
145+
$calendar->setPermissions($permissions);
146+
$calendar->setComponents($components);
147+
if ($calendar->getState() === FederatedCalendarEntity::STATE_PENDING) {
148+
// The open invitation shows the sharer's metadata, keep it
149+
// fresh. Accepted calendars are not touched as the sharee owns
150+
// the display name and color from that point on.
151+
$calendar->setDisplayName($displayName);
152+
$calendar->setColor($color);
153+
$calendar->setSharedByDisplayName($share->getSharedByDisplayName());
154+
}
155+
$this->federatedCalendarMapper->update($calendar);
156+
}
157+
158+
if ($calendar->getState() === FederatedCalendarEntity::STATE_ACCEPTED) {
159+
// Re-share of an already accepted calendar: just refresh the data
160+
$this->jobList->add(FederatedCalendarSyncJob::class, [
161+
FederatedCalendarSyncJob::ARGUMENT_ID => $calendar->getId(),
162+
]);
163+
} elseif ($this->invitationService->shouldAutoAccept($share->getOwner(), $calendar->getRemoteUrl())) {
164+
$this->invitationService->accept($calendar);
165+
} elseif ($isNew) {
166+
// A re-shared pending calendar keeps its original invitation
167+
$this->invitationService->notifyAboutNewShare($calendar);
168+
}
144169

145170
return (string)$calendar->getId();
146171
}
@@ -196,6 +221,7 @@ private function handleSyncCalendarNotification(array $notification): array {
196221
$calendarUrl,
197222
'principals/users/' . $shareWith->getUser(),
198223
$sharedSecret,
224+
FederatedCalendarEntity::STATE_ACCEPTED,
199225
);
200226
if (empty($calendars)) {
201227
throw new ShareNotFound('Calendar is not shared with the sharee');

apps/dav/lib/CalDAV/Federation/FederatedCalendarEntity.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,13 @@
3939
* @method void setSharedByDisplayName(string $sharedByDisplayName)
4040
* @method string getComponents()
4141
* @method void setComponents(string $components)
42+
* @method int getState()
43+
* @method void setState(int $state)
4244
*/
4345
class FederatedCalendarEntity extends Entity {
46+
public const STATE_PENDING = 0;
47+
public const STATE_ACCEPTED = 1;
48+
4449
protected string $principaluri = '';
4550
protected string $uri = '';
4651
protected string $displayName = '';
@@ -53,6 +58,7 @@ class FederatedCalendarEntity extends Entity {
5358
protected string $sharedBy = '';
5459
protected string $sharedByDisplayName = '';
5560
protected string $components = '';
61+
protected int $state = self::STATE_PENDING;
5662

5763
public function __construct() {
5864
$this->addType('principaluri', Types::STRING);
@@ -67,6 +73,7 @@ public function __construct() {
6773
$this->addType('sharedBy', Types::STRING);
6874
$this->addType('sharedByDisplayName', Types::STRING);
6975
$this->addType('components', Types::STRING);
76+
$this->addType('state', Types::INTEGER);
7077
}
7178

7279
public function getSyncTokenForSabre(): string {
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCA\DAV\CalDAV\Federation;
11+
12+
use OCA\DAV\AppInfo\Application;
13+
use OCA\DAV\BackgroundJob\FederatedCalendarSyncJob;
14+
use OCA\Federation\TrustedServers;
15+
use OCP\App\IAppManager;
16+
use OCP\BackgroundJob\IJobList;
17+
use OCP\Federation\ICloudIdManager;
18+
use OCP\IURLGenerator;
19+
use OCP\Notification\IManager as INotificationManager;
20+
use OCP\Server;
21+
use Psr\Log\LoggerInterface;
22+
23+
class FederatedCalendarInvitationService {
24+
public const NOTIFICATION_OBJECT_TYPE = 'federated_calendar_share';
25+
public const NOTIFICATION_SUBJECT_NEW_SHARE = 'federated_calendar_share';
26+
27+
private const PRINCIPAL_PREFIX = 'principals/users/';
28+
29+
public function __construct(
30+
private readonly FederatedCalendarMapper $mapper,
31+
private readonly IJobList $jobList,
32+
private readonly INotificationManager $notificationManager,
33+
private readonly IURLGenerator $url,
34+
private readonly ICloudIdManager $cloudIdManager,
35+
private readonly CalendarFederationConfig $config,
36+
private readonly IAppManager $appManager,
37+
private readonly LoggerInterface $logger,
38+
) {
39+
}
40+
41+
public function accept(FederatedCalendarEntity $calendar): void {
42+
$calendar->setState(FederatedCalendarEntity::STATE_ACCEPTED);
43+
$this->mapper->update($calendar);
44+
45+
$this->jobList->add(FederatedCalendarSyncJob::class, [
46+
FederatedCalendarSyncJob::ARGUMENT_ID => $calendar->getId(),
47+
]);
48+
49+
$this->dismissNotification($calendar);
50+
}
51+
52+
public function decline(FederatedCalendarEntity $calendar): void {
53+
// Dismiss first: a leftover bell notification would offer actions for
54+
// a share that no longer exists
55+
$this->dismissNotification($calendar);
56+
$this->mapper->deleteById($calendar->getId());
57+
}
58+
59+
public function notifyAboutNewShare(FederatedCalendarEntity $calendar): void {
60+
$notification = $this->notificationManager->createNotification();
61+
$notification->setApp(Application::APP_ID)
62+
->setUser($this->getUserId($calendar))
63+
->setDateTime(new \DateTime())
64+
->setObject(self::NOTIFICATION_OBJECT_TYPE, (string)$calendar->getId())
65+
->setSubject(self::NOTIFICATION_SUBJECT_NEW_SHARE, [
66+
'sharedBy' => $calendar->getSharedBy(),
67+
'sharedByDisplayName' => $calendar->getSharedByDisplayName(),
68+
'calendarName' => $calendar->getDisplayName(),
69+
]);
70+
71+
$endpointUrl = $this->url->linkToOCSRouteAbsolute('dav.federated_calendar.accept', [
72+
'id' => $calendar->getId(),
73+
]);
74+
75+
$declineAction = $notification->createAction();
76+
$declineAction->setLabel('decline')
77+
->setLink($endpointUrl, 'DELETE');
78+
$notification->addAction($declineAction);
79+
80+
$acceptAction = $notification->createAction();
81+
$acceptAction->setLabel('accept')
82+
->setLink($endpointUrl, 'POST');
83+
$notification->addAction($acceptAction);
84+
85+
$this->notificationManager->notify($notification);
86+
}
87+
88+
public function dismissNotification(FederatedCalendarEntity $calendar): void {
89+
$notification = $this->notificationManager->createNotification();
90+
$notification->setApp(Application::APP_ID)
91+
->setUser($this->getUserId($calendar))
92+
->setObject(self::NOTIFICATION_OBJECT_TYPE, (string)$calendar->getId());
93+
$this->notificationManager->markProcessed($notification);
94+
}
95+
96+
public function shouldAutoAccept(?string $ownerCloudId, string $remoteUrl): bool {
97+
if ($ownerCloudId === null || $ownerCloudId === '') {
98+
return false;
99+
}
100+
101+
if (!$this->config->isTrustedShareAutoAcceptEnabled()) {
102+
return false;
103+
}
104+
105+
$trustedServers = $this->getTrustedServers();
106+
if ($trustedServers === null) {
107+
return false;
108+
}
109+
110+
try {
111+
$remote = $this->cloudIdManager->resolveCloudId($ownerCloudId)->getRemote();
112+
} catch (\InvalidArgumentException) {
113+
return false;
114+
}
115+
116+
if (!$trustedServers->isTrustedServer($remote)) {
117+
return false;
118+
}
119+
120+
return $this->isSameHost($remote, $remoteUrl);
121+
}
122+
123+
private function isSameHost(string $remote, string $remoteUrl): bool {
124+
$remoteParts = parse_url(str_contains($remote, '://') ? $remote : '//' . $remote);
125+
$urlParts = parse_url($remoteUrl);
126+
if (!is_array($remoteParts) || !is_array($urlParts)
127+
|| !isset($remoteParts['host'], $urlParts['host'])) {
128+
return false;
129+
}
130+
131+
return strcasecmp($remoteParts['host'], $urlParts['host']) === 0
132+
&& ($remoteParts['port'] ?? null) === ($urlParts['port'] ?? null);
133+
}
134+
135+
protected function getTrustedServers(): ?TrustedServers {
136+
if (!$this->appManager->isEnabledForAnyone('federation')
137+
|| !class_exists(TrustedServers::class)) {
138+
return null;
139+
}
140+
141+
try {
142+
return Server::get(TrustedServers::class);
143+
} catch (\Throwable $e) {
144+
$this->logger->debug('Failed to create TrustedServers', ['exception' => $e]);
145+
return null;
146+
}
147+
}
148+
149+
private function getUserId(FederatedCalendarEntity $calendar): string {
150+
return substr($calendar->getPrincipaluri(), strlen(self::PRINCIPAL_PREFIX));
151+
}
152+
}

0 commit comments

Comments
 (0)