From bffac23322a7ca1f3f1aae279c10b5f807c47ae2 Mon Sep 17 00:00:00 2001 From: Sandro Mesterheide Date: Mon, 20 Feb 2023 03:36:17 +0100 Subject: [PATCH 1/2] feat: Add cloud id resolver interface Co-authored-by: Dirk Olbertz Signed-off-by: Sandro Mesterheide --- lib/composer/composer/autoload_classmap.php | 1 + lib/composer/composer/autoload_static.php | 1 + lib/private/Federation/CloudIdManager.php | 50 ++++++++++++++++++++- lib/public/Federation/ICloudIdManager.php | 25 +++++++++++ lib/public/Federation/ICloudIdResolver.php | 35 +++++++++++++++ 5 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 lib/public/Federation/ICloudIdResolver.php diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 16926e77775..bfaec47a26e 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -367,6 +367,7 @@ return array( 'OCP\\Federation\\ICloudFederationShare' => $baseDir . '/lib/public/Federation/ICloudFederationShare.php', 'OCP\\Federation\\ICloudId' => $baseDir . '/lib/public/Federation/ICloudId.php', 'OCP\\Federation\\ICloudIdManager' => $baseDir . '/lib/public/Federation/ICloudIdManager.php', + 'OCP\\Federation\\ICloudIdResolver' => $baseDir . '/lib/public/Federation/ICloudIdResolver.php', 'OCP\\Files' => $baseDir . '/lib/public/Files.php', 'OCP\\FilesMetadata\\AMetadataEvent' => $baseDir . '/lib/public/FilesMetadata/AMetadataEvent.php', 'OCP\\FilesMetadata\\Event\\MetadataBackgroundEvent' => $baseDir . '/lib/public/FilesMetadata/Event/MetadataBackgroundEvent.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index daa1a1940dd..0e54745e110 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -408,6 +408,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Federation\\ICloudFederationShare' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudFederationShare.php', 'OCP\\Federation\\ICloudId' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudId.php', 'OCP\\Federation\\ICloudIdManager' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudIdManager.php', + 'OCP\\Federation\\ICloudIdResolver' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudIdResolver.php', 'OCP\\Files' => __DIR__ . '/../../..' . '/lib/public/Files.php', 'OCP\\FilesMetadata\\AMetadataEvent' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/AMetadataEvent.php', 'OCP\\FilesMetadata\\Event\\MetadataBackgroundEvent' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/Event/MetadataBackgroundEvent.php', diff --git a/lib/private/Federation/CloudIdManager.php b/lib/private/Federation/CloudIdManager.php index 7e7adda3d39..edd5be3cae6 100644 --- a/lib/private/Federation/CloudIdManager.php +++ b/lib/private/Federation/CloudIdManager.php @@ -14,6 +14,7 @@ use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventDispatcher; use OCP\Federation\ICloudId; use OCP\Federation\ICloudIdManager; +use OCP\Federation\ICloudIdResolver; use OCP\ICache; use OCP\ICacheFactory; use OCP\IURLGenerator; @@ -31,6 +32,8 @@ class CloudIdManager implements ICloudIdManager { private ICache $displayNameCache; /** @var array[] */ private array $cache = []; + /** @var ICloudIdResolver[] */ + private array $cloudIdResolvers = []; public function __construct( IManager $contactsManager, @@ -80,6 +83,12 @@ class CloudIdManager implements ICloudIdManager { */ public function resolveCloudId(string $cloudId): ICloudId { // TODO magic here to get the url and user instead of just splitting on @ + + foreach ($this->cloudIdResolvers as $resolver) { + if ($resolver->isValidCloudId($cloudId)) { + return $resolver->resolveCloudId($cloudId); + } + } if (!$this->isValidCloudId($cloudId)) { throw new \InvalidArgumentException('Invalid cloud id'); @@ -251,6 +260,45 @@ class CloudIdManager implements ICloudIdManager { * @return bool */ public function isValidCloudId(string $cloudId): bool { - return str_contains($cloudId, '@'); + foreach ($this->cloudIdResolvers as $resolver) { + if ($resolver->isValidCloudId($cloudId)) { + return true; + } + } + + return strpos($cloudId, '@') !== false; + } + + /** + * @param string $id, + * @param string $user + * @param string $remote + * @param ?string $displayName + * @return ICloudId + * + * @since 32.0.0 + */ + public function createCloudId(string $id, string $user, string $remote, ?string $displayName = null): ICloudId { + return new CloudId($id, $user, $remote, $displayName); + } + + /** + * @param ICloudIdResolver $resolver + * + * @since 32.0.0 + */ + public function registerCloudIdResolver(ICloudIdResolver $resolver) { + array_unshift($this->cloudIdResolvers, $resolver); + } + + /** + * @param ICloudIdResolver $resolver + * + * @since 32.0.0 + */ + public function unregisterCloudIdResolver(ICloudIdResolver $resolver) { + if (($key = array_search($resolver, $this->cloudIdResolvers)) !== false) { + array_splice($this->cloudIdResolvers, $key, 1); + } } } diff --git a/lib/public/Federation/ICloudIdManager.php b/lib/public/Federation/ICloudIdManager.php index 03b6ced18f5..00c7e40da4c 100644 --- a/lib/public/Federation/ICloudIdManager.php +++ b/lib/public/Federation/ICloudIdManager.php @@ -55,4 +55,29 @@ interface ICloudIdManager { * @since 30.0.0 - Optional parameter $httpsOnly was added */ public function removeProtocolFromUrl(string $url, bool $httpsOnly = false): string; + + /** + * @param string $id, + * @param string $user + * @param string $remote + * @param ?string $displayName + * @return ICloudId + * + * @since 32.0.0 + */ + public function createCloudId(string $id, string $user, string $remote, ?string $displayName = null): ICloudId; + + /** + * @param ICloudIdResolver $resolver + * + * @since 32.0.0 + */ + public function registerCloudIdResolver(ICloudIdResolver $resolver); + + /** + * @param ICloudIdResolver $resolver + * + * @since 32.0.0 + */ + public function unregisterCloudIdResolver(ICloudIdResolver $resolver); } diff --git a/lib/public/Federation/ICloudIdResolver.php b/lib/public/Federation/ICloudIdResolver.php new file mode 100644 index 00000000000..59dc0eb095c --- /dev/null +++ b/lib/public/Federation/ICloudIdResolver.php @@ -0,0 +1,35 @@ + Date: Mon, 21 Jul 2025 15:51:58 +0200 Subject: [PATCH 2/2] refactor: remove duplicated types and add return types Signed-off-by: Ferdinand Thiessen --- .../tests/AddressHandlerTest.php | 4 +- .../MountPublicLinkControllerTest.php | 4 +- .../tests/FederatedShareProviderTest.php | 4 +- .../tests/External/CacheTest.php | 4 +- .../tests/External/ManagerTest.php | 4 +- lib/private/Federation/CloudIdManager.php | 41 +++---------------- lib/private/Server.php | 4 +- lib/public/Federation/ICloudIdManager.php | 20 +++++---- lib/public/Federation/ICloudIdResolver.php | 5 +++ .../Collaborators/MailPluginTest.php | 4 +- .../Collaborators/RemotePluginTest.php | 4 +- tests/lib/Federation/CloudIdManagerTest.php | 4 +- 12 files changed, 40 insertions(+), 62 deletions(-) diff --git a/apps/federatedfilesharing/tests/AddressHandlerTest.php b/apps/federatedfilesharing/tests/AddressHandlerTest.php index 9b67e3e1848..279bf485145 100644 --- a/apps/federatedfilesharing/tests/AddressHandlerTest.php +++ b/apps/federatedfilesharing/tests/AddressHandlerTest.php @@ -34,11 +34,11 @@ class AddressHandlerTest extends \Test\TestCase { $this->contactsManager = $this->createMock(IManager::class); $this->cloudIdManager = new CloudIdManager( + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), $this->contactsManager, $this->urlGenerator, $this->createMock(IUserManager::class), - $this->createMock(ICacheFactory::class), - $this->createMock(IEventDispatcher::class) ); $this->addressHandler = new AddressHandler($this->urlGenerator, $this->il10n, $this->cloudIdManager); diff --git a/apps/federatedfilesharing/tests/Controller/MountPublicLinkControllerTest.php b/apps/federatedfilesharing/tests/Controller/MountPublicLinkControllerTest.php index cb890417d0b..e99b59e82b8 100644 --- a/apps/federatedfilesharing/tests/Controller/MountPublicLinkControllerTest.php +++ b/apps/federatedfilesharing/tests/Controller/MountPublicLinkControllerTest.php @@ -64,11 +64,11 @@ class MountPublicLinkControllerTest extends \Test\TestCase { $this->clientService = $this->createMock(IClientService::class); $this->contactsManager = $this->createMock(IContactsManager::class); $this->cloudIdManager = new CloudIdManager( + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), $this->contactsManager, $this->createMock(IURLGenerator::class), $this->userManager, - $this->createMock(ICacheFactory::class), - $this->createMock(IEventDispatcher::class) ); $this->controller = new MountPublicLinkController( diff --git a/apps/federatedfilesharing/tests/FederatedShareProviderTest.php b/apps/federatedfilesharing/tests/FederatedShareProviderTest.php index 4d6add962fe..7e97510af22 100644 --- a/apps/federatedfilesharing/tests/FederatedShareProviderTest.php +++ b/apps/federatedfilesharing/tests/FederatedShareProviderTest.php @@ -74,11 +74,11 @@ class FederatedShareProviderTest extends \Test\TestCase { $this->addressHandler = $this->createMock(AddressHandler::class); $this->contactsManager = $this->createMock(IContactsManager::class); $this->cloudIdManager = new CloudIdManager( + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), $this->contactsManager, $this->createMock(IURLGenerator::class), $this->userManager, - $this->createMock(ICacheFactory::class), - $this->createMock(IEventDispatcher::class) ); $this->gsConfig = $this->createMock(\OCP\GlobalScale\IConfig::class); diff --git a/apps/files_sharing/tests/External/CacheTest.php b/apps/files_sharing/tests/External/CacheTest.php index 60820013f11..39e2057a24c 100644 --- a/apps/files_sharing/tests/External/CacheTest.php +++ b/apps/files_sharing/tests/External/CacheTest.php @@ -54,11 +54,11 @@ class CacheTest extends TestCase { $this->contactsManager = $this->createMock(IManager::class); $this->cloudIdManager = new CloudIdManager( + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), $this->contactsManager, $this->createMock(IURLGenerator::class), $this->createMock(IUserManager::class), - $this->createMock(ICacheFactory::class), - $this->createMock(IEventDispatcher::class) ); $this->remoteUser = $this->getUniqueID('remoteuser'); diff --git a/apps/files_sharing/tests/External/ManagerTest.php b/apps/files_sharing/tests/External/ManagerTest.php index fbe6eb1e85b..14c6afec4d8 100644 --- a/apps/files_sharing/tests/External/ManagerTest.php +++ b/apps/files_sharing/tests/External/ManagerTest.php @@ -90,11 +90,11 @@ class ManagerTest extends TestCase { $this->testMountProvider = new MountProvider(Server::get(IDBConnection::class), function () { return $this->manager; }, new CloudIdManager( + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), $this->contactsManager, $this->createMock(IURLGenerator::class), $this->userManager, - $this->createMock(ICacheFactory::class), - $this->createMock(IEventDispatcher::class) )); $group1 = $this->createMock(IGroup::class); diff --git a/lib/private/Federation/CloudIdManager.php b/lib/private/Federation/CloudIdManager.php index edd5be3cae6..c599d9046a6 100644 --- a/lib/private/Federation/CloudIdManager.php +++ b/lib/private/Federation/CloudIdManager.php @@ -22,29 +22,19 @@ use OCP\IUserManager; use OCP\User\Events\UserChangedEvent; class CloudIdManager implements ICloudIdManager { - /** @var IManager */ - private $contactsManager; - /** @var IURLGenerator */ - private $urlGenerator; - /** @var IUserManager */ - private $userManager; private ICache $memCache; private ICache $displayNameCache; - /** @var array[] */ private array $cache = []; /** @var ICloudIdResolver[] */ private array $cloudIdResolvers = []; public function __construct( - IManager $contactsManager, - IURLGenerator $urlGenerator, - IUserManager $userManager, ICacheFactory $cacheFactory, IEventDispatcher $eventDispatcher, + private IManager $contactsManager, + private IURLGenerator $urlGenerator, + private IUserManager $userManager, ) { - $this->contactsManager = $contactsManager; - $this->urlGenerator = $urlGenerator; - $this->userManager = $userManager; $this->memCache = $cacheFactory->createDistributed('cloud_id_'); $this->displayNameCache = $cacheFactory->createDistributed('cloudid_name_'); $eventDispatcher->addListener(UserChangedEvent::class, [$this, 'handleUserEvent']); @@ -83,7 +73,7 @@ class CloudIdManager implements ICloudIdManager { */ public function resolveCloudId(string $cloudId): ICloudId { // TODO magic here to get the url and user instead of just splitting on @ - + foreach ($this->cloudIdResolvers as $resolver) { if ($resolver->isValidCloudId($cloudId)) { return $resolver->resolveCloudId($cloudId); @@ -269,34 +259,15 @@ class CloudIdManager implements ICloudIdManager { return strpos($cloudId, '@') !== false; } - /** - * @param string $id, - * @param string $user - * @param string $remote - * @param ?string $displayName - * @return ICloudId - * - * @since 32.0.0 - */ public function createCloudId(string $id, string $user, string $remote, ?string $displayName = null): ICloudId { return new CloudId($id, $user, $remote, $displayName); } - /** - * @param ICloudIdResolver $resolver - * - * @since 32.0.0 - */ - public function registerCloudIdResolver(ICloudIdResolver $resolver) { + public function registerCloudIdResolver(ICloudIdResolver $resolver): void { array_unshift($this->cloudIdResolvers, $resolver); } - /** - * @param ICloudIdResolver $resolver - * - * @since 32.0.0 - */ - public function unregisterCloudIdResolver(ICloudIdResolver $resolver) { + public function unregisterCloudIdResolver(ICloudIdResolver $resolver): void { if (($key = array_search($resolver, $this->cloudIdResolvers)) !== false) { array_splice($this->cloudIdResolvers, $key, 1); } diff --git a/lib/private/Server.php b/lib/private/Server.php index 1e1ba2a1ad3..8e105ba6b1c 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -1161,11 +1161,11 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService(ICloudIdManager::class, function (ContainerInterface $c) { return new CloudIdManager( + $c->get(ICacheFactory::class), + $c->get(IEventDispatcher::class), $c->get(\OCP\Contacts\IManager::class), $c->get(IURLGenerator::class), $c->get(IUserManager::class), - $c->get(ICacheFactory::class), - $c->get(IEventDispatcher::class), ); }); diff --git a/lib/public/Federation/ICloudIdManager.php b/lib/public/Federation/ICloudIdManager.php index 00c7e40da4c..29e261ab3af 100644 --- a/lib/public/Federation/ICloudIdManager.php +++ b/lib/public/Federation/ICloudIdManager.php @@ -8,11 +8,14 @@ declare(strict_types=1); */ namespace OCP\Federation; +use OCP\AppFramework\Attribute\Consumable; + /** * Interface for resolving federated cloud ids * * @since 12.0.0 */ +#[Consumable(since: '12.0.0')] interface ICloudIdManager { /** * @param string $cloudId @@ -57,27 +60,26 @@ interface ICloudIdManager { public function removeProtocolFromUrl(string $url, bool $httpsOnly = false): string; /** - * @param string $id, - * @param string $user - * @param string $remote - * @param ?string $displayName - * @return ICloudId + * @param string $id The remote cloud id + * @param string $user The user id on the remote server + * @param string $remote The base address of the remote server + * @param ?string $displayName The displayname of the remote user * * @since 32.0.0 */ public function createCloudId(string $id, string $user, string $remote, ?string $displayName = null): ICloudId; /** - * @param ICloudIdResolver $resolver + * @param $resolver The cloud id resolver to register * * @since 32.0.0 */ - public function registerCloudIdResolver(ICloudIdResolver $resolver); + public function registerCloudIdResolver(ICloudIdResolver $resolver): void; /** - * @param ICloudIdResolver $resolver + * @param $resolver The cloud id resolver to unregister * * @since 32.0.0 */ - public function unregisterCloudIdResolver(ICloudIdResolver $resolver); + public function unregisterCloudIdResolver(ICloudIdResolver $resolver): void; } diff --git a/lib/public/Federation/ICloudIdResolver.php b/lib/public/Federation/ICloudIdResolver.php index 59dc0eb095c..79f9ed11dd7 100644 --- a/lib/public/Federation/ICloudIdResolver.php +++ b/lib/public/Federation/ICloudIdResolver.php @@ -8,11 +8,16 @@ declare(strict_types=1); */ namespace OCP\Federation; +use OCP\AppFramework\Attribute\Consumable; +use OCP\AppFramework\Attribute\Implementable; + /** * Interface for resolving federated cloud ids * * @since 32.0.0 */ +#[Consumable(since: '32.0.0')] +#[Implementable(since: '32.0.0')] interface ICloudIdResolver { /** * @param string $cloudId diff --git a/tests/lib/Collaboration/Collaborators/MailPluginTest.php b/tests/lib/Collaboration/Collaborators/MailPluginTest.php index 502b7844a2a..b38b961a512 100644 --- a/tests/lib/Collaboration/Collaborators/MailPluginTest.php +++ b/tests/lib/Collaboration/Collaborators/MailPluginTest.php @@ -64,11 +64,11 @@ class MailPluginTest extends TestCase { $this->userSession = $this->createMock(IUserSession::class); $this->mailer = $this->createMock(IMailer::class); $this->cloudIdManager = new CloudIdManager( + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), $this->contactsManager, $this->createMock(IURLGenerator::class), $this->createMock(IUserManager::class), - $this->createMock(ICacheFactory::class), - $this->createMock(IEventDispatcher::class) ); $this->searchResult = new SearchResult(); diff --git a/tests/lib/Collaboration/Collaborators/RemotePluginTest.php b/tests/lib/Collaboration/Collaborators/RemotePluginTest.php index ea81b1cbcdc..a9a5e05dfe4 100644 --- a/tests/lib/Collaboration/Collaborators/RemotePluginTest.php +++ b/tests/lib/Collaboration/Collaborators/RemotePluginTest.php @@ -49,11 +49,11 @@ class RemotePluginTest extends TestCase { $this->config = $this->createMock(IConfig::class); $this->contactsManager = $this->createMock(IManager::class); $this->cloudIdManager = new CloudIdManager( + $this->createMock(ICacheFactory::class), + $this->createMock(IEventDispatcher::class), $this->contactsManager, $this->createMock(IURLGenerator::class), $this->createMock(IUserManager::class), - $this->createMock(ICacheFactory::class), - $this->createMock(IEventDispatcher::class) ); $this->searchResult = new SearchResult(); } diff --git a/tests/lib/Federation/CloudIdManagerTest.php b/tests/lib/Federation/CloudIdManagerTest.php index 3bd3cf6149d..cf97c895dc1 100644 --- a/tests/lib/Federation/CloudIdManagerTest.php +++ b/tests/lib/Federation/CloudIdManagerTest.php @@ -47,11 +47,11 @@ class CloudIdManagerTest extends TestCase { ->willReturn(new ArrayCache('')); $this->cloudIdManager = new CloudIdManager( + $this->cacheFactory, + $this->createMock(IEventDispatcher::class), $this->contactsManager, $this->urlGenerator, $this->userManager, - $this->cacheFactory, - $this->createMock(IEventDispatcher::class) ); $this->overwriteService(ICloudIdManager::class, $this->cloudIdManager); }