From 23c1e7abcd9dd0aa0a60d7d202fc51e5617aedb8 Mon Sep 17 00:00:00 2001 From: Kent Delante Date: Fri, 24 Jul 2026 15:13:15 +0800 Subject: [PATCH] feat(federation): implement minimal federation user backend Signed-off-by: Kent Delante --- .../composer/composer/autoload_classmap.php | 1 + .../composer/composer/autoload_static.php | 1 + apps/federation/lib/AppInfo/Application.php | 3 + apps/federation/lib/User/Backend.php | 59 +++++++++++++ apps/federation/tests/User/BackendTest.php | 82 +++++++++++++++++++ 5 files changed, 146 insertions(+) create mode 100644 apps/federation/lib/User/Backend.php create mode 100644 apps/federation/tests/User/BackendTest.php diff --git a/apps/federation/composer/composer/autoload_classmap.php b/apps/federation/composer/composer/autoload_classmap.php index deca7ce3f04c8..77e908261150b 100644 --- a/apps/federation/composer/composer/autoload_classmap.php +++ b/apps/federation/composer/composer/autoload_classmap.php @@ -23,4 +23,5 @@ 'OCA\\Federation\\SyncFederationAddressBooks' => $baseDir . '/../lib/SyncFederationAddressBooks.php', 'OCA\\Federation\\SyncJob' => $baseDir . '/../lib/SyncJob.php', 'OCA\\Federation\\TrustedServers' => $baseDir . '/../lib/TrustedServers.php', + 'OCA\\Federation\\User\\Backend' => $baseDir . '/../lib/User/Backend.php', ); diff --git a/apps/federation/composer/composer/autoload_static.php b/apps/federation/composer/composer/autoload_static.php index edae4c88ab97d..dd17e40afbe09 100644 --- a/apps/federation/composer/composer/autoload_static.php +++ b/apps/federation/composer/composer/autoload_static.php @@ -38,6 +38,7 @@ class ComposerStaticInitFederation 'OCA\\Federation\\SyncFederationAddressBooks' => __DIR__ . '/..' . '/../lib/SyncFederationAddressBooks.php', 'OCA\\Federation\\SyncJob' => __DIR__ . '/..' . '/../lib/SyncJob.php', 'OCA\\Federation\\TrustedServers' => __DIR__ . '/..' . '/../lib/TrustedServers.php', + 'OCA\\Federation\\User\\Backend' => __DIR__ . '/..' . '/../lib/User/Backend.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/apps/federation/lib/AppInfo/Application.php b/apps/federation/lib/AppInfo/Application.php index 7dde4b300557f..69568bf40c0e8 100644 --- a/apps/federation/lib/AppInfo/Application.php +++ b/apps/federation/lib/AppInfo/Application.php @@ -11,11 +11,13 @@ use OCA\DAV\Events\SabrePluginAuthInitEvent; use OCA\Federation\Listener\SabrePluginAuthInitListener; use OCA\Federation\Listener\TrustedServerRemovedListener; +use OCA\Federation\User\Backend; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\Federation\Events\TrustedServerRemovedEvent; +use OCP\IUserManager; class Application extends App implements IBootstrap { @@ -36,5 +38,6 @@ public function register(IRegistrationContext $context): void { #[\Override] public function boot(IBootContext $context): void { + $context->injectFn(fn (IUserManager $userManager, Backend $backend) => $userManager->registerBackend($backend)); } } diff --git a/apps/federation/lib/User/Backend.php b/apps/federation/lib/User/Backend.php new file mode 100644 index 0000000000000..8deb81facf604 --- /dev/null +++ b/apps/federation/lib/User/Backend.php @@ -0,0 +1,59 @@ +cloudIdManager->isValidCloudId($uid); + } + + #[\Override] + public function getDisplayName($uid): string { + return $this->cloudIdManager->resolveCloudId($uid)->getDisplayId(); + } + + #[\Override] + public function getDisplayNames($search = '', $limit = null, $offset = null) { + return []; + } + + #[\Override] + public function hasUserListings() { + return false; + } +} diff --git a/apps/federation/tests/User/BackendTest.php b/apps/federation/tests/User/BackendTest.php new file mode 100644 index 0000000000000..54b67698e79b5 --- /dev/null +++ b/apps/federation/tests/User/BackendTest.php @@ -0,0 +1,82 @@ +backend = Server::get(Backend::class); + $this->userId = 'foo@example.com'; + } + + protected function tearDown(): void { + parent::tearDown(); + } + + public function testGetBackendName(): void { + $this->assertEquals($this->backend->getBackendName(), 'federation'); + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestImplementsActions')] + public function testImplementsActions(int $action, bool $implemented): void { + $this->assertEquals($this->backend->implementsActions($action), $implemented); + } + + public static function dataTestImplementsActions(): array { + return [ + [Base::CREATE_USER, false], + [Base::SET_PASSWORD, false], + [Base::CHECK_PASSWORD, false], + [Base::GET_HOME, false], + [Base::GET_DISPLAYNAME, true], + [Base::SET_DISPLAYNAME, false], + [Base::PROVIDE_AVATAR, false], + [Base::COUNT_USERS, false], + ]; + } + + public function testDeleteUser(): void { + $this->assertFalse($this->backend->deleteUser($this->userId)); + } + + public function testGetUsers(): void { + $this->assertEquals($this->backend->getUsers(), []); + } + + public function testUserExists(): void { + $this->assertTrue($this->backend->userExists($this->userId)); + $this->assertFalse($this->backend->userExists('foo')); + } + + public function testGetDisplayName(): void { + $this->assertEquals($this->backend->getDisplayName($this->userId), $this->userId); + + $this->expectException(\InvalidArgumentException::class); + $this->backend->getDisplayName('foo'); + } + + public function testGetDisplayNames(): void { + $this->assertEquals($this->backend->getDisplayNames(), []); + } + + public function testHasUserListings(): void { + $this->assertFalse($this->backend->hasUserListings()); + } +}