Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
25 changes: 23 additions & 2 deletions apps/dav/lib/CalDAV/Federation/CalendarFederationConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,36 @@

namespace OCA\DAV\CalDAV\Federation;

use OCP\AppFramework\Services\IAppConfig;
use OCP\IAppConfig;

class CalendarFederationConfig {
public function __construct(
private readonly IAppConfig $appConfig,
private \OCP\GlobalScale\IConfig $gsConfig,
) {
}

public function isFederationEnabled(): bool {
return $this->appConfig->getAppValueBool('enableCalendarFederation', true);
return $this->appConfig->getValueBool('dav', 'enableCalendarFederation', true);
}

/**
* Check if users are allowed to create federated shares
*/
public function isOutgoingServer2serverShareEnabled(): bool {
if ($this->gsConfig->onlyInternalFederation()) {
return false;
}
return $this->appConfig->getValueBool('files_sharing', 'outgoing_server2server_share_enabled', true);
}

/**
* Check if users are allowed to receive federated shares
*/
public function isIncomingServer2serverShareEnabled(): bool {
if ($this->gsConfig->onlyInternalFederation()) {
return false;
}
return $this->appConfig->getValueBool('files_sharing', 'incoming_server2server_share_enabled', true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ public function shareReceived(ICloudFederationShare $share): string {
);
}

if (!$this->calendarFederationConfig->isIncomingServer2serverShareEnabled()) {
$this->logger->debug('Received a federated calendar share which is not allowed on this instance');
throw new ProviderCouldNotAddShareException(
'Instance does not support receiving federated calendar shares',
'',
Http::STATUS_SERVICE_UNAVAILABLE,
);
}

if (!in_array($share->getShareType(), $this->getSupportedShareTypes(), true)) {
$this->logger->debug('Received a federation invite for invalid share type');
throw new ProviderCouldNotAddShareException(
Expand Down
9 changes: 9 additions & 0 deletions apps/dav/lib/CalDAV/Federation/FederationSharingService.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public function __construct(
private readonly LoggerInterface $logger,
private readonly ISecureRandom $random,
private readonly SharingMapper $sharingMapper,
private readonly CalendarFederationConfig $config,
) {
}

Expand Down Expand Up @@ -70,6 +71,14 @@ private function decodeRemoteUserPrincipal(string $principal): ?string {
public function shareWith(IShareable $shareable, string $principal, int $access): void {
$baseError = 'Failed to create federated calendar share: ';

if (!$this->config->isOutgoingServer2serverShareEnabled()) {
$this->logger->error('cannot share with remote user because federated sharing is disabled on this instance', [
'shareable' => $shareable->getName(),
'encodedShareWith' => $principal,
]);
return;
}

// 1. Validate share data
$shareWith = $this->decodeRemoteUserPrincipal($principal);
if ($shareWith === null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
namespace OCA\DAV\Tests\unit\CalDAV\Federation;

use OCA\DAV\CalDAV\Federation\CalendarFederationConfig;
use OCP\AppFramework\Services\IAppConfig;
use OCP\GlobalScale\IConfig;
use OCP\IAppConfig;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
Expand All @@ -19,14 +20,17 @@ class CalendarFederationConfigTest extends TestCase {
private CalendarFederationConfig $config;

private IAppConfig&MockObject $appConfig;
private IConfig&MockObject $gsConfig;

protected function setUp(): void {
parent::setUp();

$this->appConfig = $this->createMock(IAppConfig::class);
$this->gsConfig = $this->createMock(IConfig::class);

$this->config = new CalendarFederationConfig(
$this->appConfig,
$this->gsConfig,
);
}

Expand All @@ -40,10 +44,74 @@ public static function provideIsFederationEnabledData(): array {
#[DataProvider(methodName: 'provideIsFederationEnabledData')]
public function testIsFederationEnabled(bool $configValue): void {
$this->appConfig->expects(self::once())
->method('getAppValueBool')
->with('enableCalendarFederation', true)
->method('getValueBool')
->with('dav', 'enableCalendarFederation', true)
->willReturn($configValue);

$this->assertEquals($configValue, $this->config->isFederationEnabled());
}

public static function provideIsOutgoingServer2serverShareEnabledData(): array {
return [
[false, false, false],
[false, true, true],
[true, false, false],
[true, false, false],
];
}

#[DataProvider(methodName: 'provideIsOutgoingServer2serverShareEnabledData')]
public function testIsOutgoingServer2serverShareEnabled(
bool $globalScaleEnabled,
bool $expected,
bool $configValue,
): void {
$this->gsConfig->expects(self::once())
->method('onlyInternalFederation')
->willReturn($globalScaleEnabled);

if (!$globalScaleEnabled) {
$this->appConfig->expects(self::once())
->method('getValueBool')
->with('files_sharing', 'outgoing_server2server_share_enabled', true)
->willReturn($configValue);
} else {
$this->appConfig->expects(self::never())
->method('getValueBool');
}

$this->assertEquals($expected, $this->config->isOutgoingServer2serverShareEnabled());
}

public static function provideIsIncomingServer2serverShareEnabledData(): array {
return [
[false, false, false],
[false, true, true],
[true, false, false],
[true, false, true],
];
}

#[DataProvider(methodName: 'provideIsIncomingServer2serverShareEnabledData')]
public function testIsIncomingServer2serverShareEnabled(
bool $globalScaleEnabled,
bool $expected,
bool $configValue,
): void {
$this->gsConfig->expects(self::once())
->method('onlyInternalFederation')
->willReturn($globalScaleEnabled);

if (!$globalScaleEnabled) {
$this->appConfig->expects(self::once())
->method('getValueBool')
->with('files_sharing', 'incoming_server2server_share_enabled', true)
->willReturn($configValue);
} else {
$this->appConfig->expects(self::never())
->method('getValueBool');
}

$this->assertEquals($expected, $this->config->isIncomingServer2serverShareEnabled());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ public function testShareReceived(): void {
->method('isFederationEnabled')
->willReturn(true);

$this->calendarFederationConfig->expects(self::once())
->method('isIncomingServer2serverShareEnabled')
->willReturn(true);

$this->federatedCalendarMapper->expects(self::once())
->method('findByUri')
->with(
Expand Down Expand Up @@ -150,6 +154,10 @@ public function testShareReceivedWithExistingCalendar(): void {
->method('isFederationEnabled')
->willReturn(true);

$this->calendarFederationConfig->expects(self::once())
->method('isIncomingServer2serverShareEnabled')
->willReturn(true);

$existingCalendar = new FederatedCalendarEntity();
$existingCalendar->setId(10);
$existingCalendar->setPrincipaluri('principals/users/sharee1');
Expand Down Expand Up @@ -204,6 +212,10 @@ public function testShareReceivedWithInvalidProtocolVersion(): void {
->method('isFederationEnabled')
->willReturn(true);

$this->calendarFederationConfig->expects(self::once())
->method('isIncomingServer2serverShareEnabled')
->willReturn(true);

$this->federatedCalendarMapper->expects(self::never())
->method('insert');
$this->jobList->expects(self::never())
Expand Down Expand Up @@ -232,6 +244,10 @@ public function testShareReceivedWithoutProtocolVersion(): void {
->method('isFederationEnabled')
->willReturn(true);

$this->calendarFederationConfig->expects(self::once())
->method('isIncomingServer2serverShareEnabled')
->willReturn(true);

$this->federatedCalendarMapper->expects(self::never())
->method('insert');
$this->jobList->expects(self::never())
Expand Down Expand Up @@ -261,6 +277,30 @@ public function testShareReceivedWithDisabledConfig(): void {
$this->calendarFederationProvider->shareReceived($share);
}

public function testShareReceivedWithIncomingServer2serverShareDisabled(): void {
$share = $this->createMock(ICloudFederationShare::class);
$share->method('getShareType')
->willReturn('user');

$this->calendarFederationConfig->expects(self::once())
->method('isFederationEnabled')
->willReturn(true);

$this->calendarFederationConfig->expects(self::once())
->method('isIncomingServer2serverShareEnabled')
->willReturn(false);

$this->federatedCalendarMapper->expects(self::never())
->method('insert');
$this->jobList->expects(self::never())
->method('add');

$this->expectException(ProviderCouldNotAddShareException::class);
$this->expectExceptionMessage('Instance does not support receiving federated calendar shares');
$this->expectExceptionCode(503);
$this->calendarFederationProvider->shareReceived($share);
}

public function testShareReceivedWithUnsupportedShareType(): void {
$share = $this->createMock(ICloudFederationShare::class);
$share->method('getShareType')
Expand All @@ -270,6 +310,10 @@ public function testShareReceivedWithUnsupportedShareType(): void {
->method('isFederationEnabled')
->willReturn(true);

$this->calendarFederationConfig->expects(self::once())
->method('isIncomingServer2serverShareEnabled')
->willReturn(true);

$this->federatedCalendarMapper->expects(self::never())
->method('insert');
$this->jobList->expects(self::never())
Expand Down Expand Up @@ -322,6 +366,10 @@ public function testShareReceivedWithIncompleteProtocolData(array $protocol): vo
->method('isFederationEnabled')
->willReturn(true);

$this->calendarFederationConfig->expects(self::once())
->method('isIncomingServer2serverShareEnabled')
->willReturn(true);

$this->federatedCalendarMapper->expects(self::never())
->method('insert');
$this->jobList->expects(self::never())
Expand Down Expand Up @@ -359,6 +407,10 @@ public function testShareReceivedWithReadWriteAccess(): void {
->method('isFederationEnabled')
->willReturn(true);

$this->calendarFederationConfig->expects(self::once())
->method('isIncomingServer2serverShareEnabled')
->willReturn(true);

$this->federatedCalendarMapper->expects(self::once())
->method('findByUri')
->with(
Expand Down Expand Up @@ -418,6 +470,10 @@ public function testShareReceivedWithUnsupportedAccess(): void {
->method('isFederationEnabled')
->willReturn(true);

$this->calendarFederationConfig->expects(self::once())
->method('isIncomingServer2serverShareEnabled')
->willReturn(true);

$this->federatedCalendarMapper->expects(self::never())
->method('insert');
$this->jobList->expects(self::never())
Expand Down
Loading
Loading