Skip to content

Commit af8e175

Browse files
committed
fix(federation): remove background jobs when removing trusted servers
Add event listener to remove matching background jobs for trusted server url. Signed-off-by: Daniel Kesselberg <[email protected]>
1 parent 5d14f87 commit af8e175

File tree

7 files changed

+137
-4
lines changed

7 files changed

+137
-4
lines changed

apps/federation/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
'OCA\\Federation\\DAV\\FedAuth' => $baseDir . '/../lib/DAV/FedAuth.php',
1717
'OCA\\Federation\\DbHandler' => $baseDir . '/../lib/DbHandler.php',
1818
'OCA\\Federation\\Listener\\SabrePluginAuthInitListener' => $baseDir . '/../lib/Listener/SabrePluginAuthInitListener.php',
19+
'OCA\\Federation\\Listener\\TrustedServerRemovedListener' => $baseDir . '/../lib/Listener/TrustedServerRemovedListener.php',
1920
'OCA\\Federation\\Migration\\Version1010Date20200630191302' => $baseDir . '/../lib/Migration/Version1010Date20200630191302.php',
2021
'OCA\\Federation\\Settings\\Admin' => $baseDir . '/../lib/Settings/Admin.php',
2122
'OCA\\Federation\\SyncFederationAddressBooks' => $baseDir . '/../lib/SyncFederationAddressBooks.php',

apps/federation/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class ComposerStaticInitFederation
3131
'OCA\\Federation\\DAV\\FedAuth' => __DIR__ . '/..' . '/../lib/DAV/FedAuth.php',
3232
'OCA\\Federation\\DbHandler' => __DIR__ . '/..' . '/../lib/DbHandler.php',
3333
'OCA\\Federation\\Listener\\SabrePluginAuthInitListener' => __DIR__ . '/..' . '/../lib/Listener/SabrePluginAuthInitListener.php',
34+
'OCA\\Federation\\Listener\\TrustedServerRemovedListener' => __DIR__ . '/..' . '/../lib/Listener/TrustedServerRemovedListener.php',
3435
'OCA\\Federation\\Migration\\Version1010Date20200630191302' => __DIR__ . '/..' . '/../lib/Migration/Version1010Date20200630191302.php',
3536
'OCA\\Federation\\Settings\\Admin' => __DIR__ . '/..' . '/../lib/Settings/Admin.php',
3637
'OCA\\Federation\\SyncFederationAddressBooks' => __DIR__ . '/..' . '/../lib/SyncFederationAddressBooks.php',

apps/federation/lib/AppInfo/Application.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99

1010
use OCA\DAV\Events\SabrePluginAuthInitEvent;
1111
use OCA\Federation\Listener\SabrePluginAuthInitListener;
12+
use OCA\Federation\Listener\TrustedServerRemovedListener;
1213
use OCP\AppFramework\App;
1314
use OCP\AppFramework\Bootstrap\IBootContext;
1415
use OCP\AppFramework\Bootstrap\IBootstrap;
1516
use OCP\AppFramework\Bootstrap\IRegistrationContext;
17+
use OCP\Federation\Events\TrustedServerRemovedEvent;
1618

1719
class Application extends App implements IBootstrap {
1820

@@ -25,6 +27,7 @@ public function __construct($urlParams = []) {
2527

2628
public function register(IRegistrationContext $context): void {
2729
$context->registerEventListener(SabrePluginAuthInitEvent::class, SabrePluginAuthInitListener::class);
30+
$context->registerEventListener(TrustedServerRemovedEvent::class, TrustedServerRemovedListener::class);
2831
}
2932

3033
public function boot(IBootContext $context): void {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCA\Federation\Listener;
11+
12+
use OCA\Federation\BackgroundJob\GetSharedSecret;
13+
use OCA\Federation\BackgroundJob\RequestSharedSecret;
14+
use OCP\BackgroundJob\IJobList;
15+
use OCP\EventDispatcher\Event;
16+
use OCP\EventDispatcher\IEventListener;
17+
use OCP\Federation\Events\TrustedServerRemovedEvent;
18+
19+
/** @template-implements IEventListener<TrustedServerRemovedEvent> */
20+
class TrustedServerRemovedListener implements IEventListener {
21+
public function __construct(
22+
private readonly IJobList $jobList,
23+
) {
24+
}
25+
26+
public function handle(Event $event): void {
27+
if (!$event instanceof TrustedServerRemovedEvent) {
28+
return;
29+
}
30+
31+
$this->removeJobsByUrl(RequestSharedSecret::class, $event->getUrl());
32+
$this->removeJobsByUrl(GetSharedSecret::class, $event->getUrl());
33+
}
34+
35+
private function removeJobsByUrl(string $class, string $url): void {
36+
foreach ($this->jobList->getJobsIterator($class, null, 0) as $job) {
37+
$arguments = $job->getArgument();
38+
if (isset($arguments['url']) && $arguments['url'] === $url) {
39+
try {
40+
$this->jobList->removeById($job->getId());
41+
} catch (\Exception) {
42+
// Removing the background jobs is optional because they will expire sometime.
43+
// Therefore, we are using catch and ignore.
44+
}
45+
}
46+
}
47+
}
48+
}

apps/federation/lib/TrustedServers.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public function addSharedSecret(string $url, string $sharedSecret): void {
8888
public function removeServer(int $id): void {
8989
$server = $this->dbHandler->getServerById($id);
9090
$this->dbHandler->removeServer($id);
91-
$this->dispatcher->dispatchTyped(new TrustedServerRemovedEvent($server['url_hash']));
91+
$this->dispatcher->dispatchTyped(new TrustedServerRemovedEvent($server['url'], $server['url_hash']));
9292

9393
}
9494

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCA\Federation\Tests\Listener;
11+
12+
use OC\AppFramework\Utility\TimeFactory;
13+
use OCA\Federation\BackgroundJob\GetSharedSecret;
14+
use OCA\Federation\Listener\TrustedServerRemovedListener;
15+
use OCA\Federation\TrustedServers;
16+
use OCP\BackgroundJob\IJobList;
17+
use OCP\Federation\Events\TrustedServerRemovedEvent;
18+
use OCP\Http\Client\IClientService;
19+
use OCP\IConfig;
20+
use OCP\IURLGenerator;
21+
use OCP\OCS\IDiscoveryService;
22+
use Psr\Log\NullLogger;
23+
use Test\BackgroundJob\DummyJobList;
24+
use Test\TestCase;
25+
26+
class TrustedServerRemovedListenerTest extends TestCase {
27+
28+
private IJobList $jobList;
29+
private TrustedServerRemovedListener $listener;
30+
31+
protected function setUp(): void {
32+
parent::setUp();
33+
34+
$this->jobList = new DummyJobList();
35+
$this->listener = new TrustedServerRemovedListener($this->jobList);
36+
}
37+
38+
public function testHandle(): void {
39+
// Arrange
40+
$url = 'https://example.com';
41+
$event = new TrustedServerRemovedEvent($url, md5($url)); // we are using a different hashing in the tests.
42+
$job1 = $this->createGetSharedSecretMock();
43+
$job2 = $this->createGetSharedSecretMock();
44+
$job3 = $this->createGetSharedSecretMock();
45+
$job4 = $this->createGetSharedSecretMock();
46+
$this->jobList->add($job1, ['url' => 'https://example.org']);
47+
$this->jobList->add($job2, ['url' => 'https://example.net']);
48+
$this->jobList->add($job3, ['url' => $url]);
49+
$this->jobList->add($job4, ['url' => $url]);
50+
51+
// Act
52+
$this->listener->handle($event);
53+
$jobs = iterator_to_array($this->jobList->getJobsIterator(GetSharedSecret::class, null, 0), false);
54+
55+
// Assert
56+
$this->assertCount(2, $jobs);
57+
}
58+
59+
private function createGetSharedSecretMock(): GetSharedSecret {
60+
return new GetSharedSecret(
61+
$this->createMock(IClientService::class),
62+
$this->createMock(IURLGenerator::class),
63+
$this->jobList,
64+
$this->createMock(TrustedServers::class),
65+
new NullLogger(),
66+
$this->createMock(IDiscoveryService::class),
67+
new TimeFactory(),
68+
$this->createMock(IConfig::class),
69+
);
70+
}
71+
}

lib/public/Federation/Events/TrustedServerRemovedEvent.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,23 @@
1414
* @since 25.0.0
1515
*/
1616
class TrustedServerRemovedEvent extends Event {
17-
private string $urlHash;
1817

1918
/**
2019
* @since 25.0.0
20+
* @since 32.0.0 Added $url argument
2121
*/
22-
public function __construct(string $urlHash) {
22+
public function __construct(
23+
private readonly string $url,
24+
private readonly string $urlHash
25+
) {
2326
parent::__construct();
24-
$this->urlHash = $urlHash;
27+
}
28+
29+
/**
30+
* @since 32.0.0
31+
*/
32+
public function getUrl(): string {
33+
return $this->url;
2534
}
2635

2736
/**

0 commit comments

Comments
 (0)