diff options
Diffstat (limited to 'lib/private/Federation')
-rw-r--r-- | lib/private/Federation/CloudFederationFactory.php | 1 | ||||
-rw-r--r-- | lib/private/Federation/CloudFederationNotification.php | 1 | ||||
-rw-r--r-- | lib/private/Federation/CloudFederationProviderManager.php | 4 | ||||
-rw-r--r-- | lib/private/Federation/CloudFederationShare.php | 1 | ||||
-rw-r--r-- | lib/private/Federation/CloudId.php | 42 | ||||
-rw-r--r-- | lib/private/Federation/CloudIdManager.php | 73 |
6 files changed, 76 insertions, 46 deletions
diff --git a/lib/private/Federation/CloudFederationFactory.php b/lib/private/Federation/CloudFederationFactory.php index f5f25d14ea1..d06de0f2f58 100644 --- a/lib/private/Federation/CloudFederationFactory.php +++ b/lib/private/Federation/CloudFederationFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Federation/CloudFederationNotification.php b/lib/private/Federation/CloudFederationNotification.php index 855580843ba..6ae805df1d9 100644 --- a/lib/private/Federation/CloudFederationNotification.php +++ b/lib/private/Federation/CloudFederationNotification.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Federation/CloudFederationProviderManager.php b/lib/private/Federation/CloudFederationProviderManager.php index e9354294351..81b5d717a56 100644 --- a/lib/private/Federation/CloudFederationProviderManager.php +++ b/lib/private/Federation/CloudFederationProviderManager.php @@ -227,8 +227,8 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager private function prepareOcmPayload(string $uri, string $payload): array { $payload = array_merge($this->getDefaultRequestOptions(), ['body' => $payload]); - if ($this->appConfig->getValueBool('core', OCMSignatoryManager::APPCONFIG_SIGN_ENFORCED, lazy: true) && - $this->signatoryManager->getRemoteSignatory($this->signatureManager->extractIdentityFromUri($uri)) === null) { + if ($this->appConfig->getValueBool('core', OCMSignatoryManager::APPCONFIG_SIGN_ENFORCED, lazy: true) + && $this->signatoryManager->getRemoteSignatory($this->signatureManager->extractIdentityFromUri($uri)) === null) { return $payload; } diff --git a/lib/private/Federation/CloudFederationShare.php b/lib/private/Federation/CloudFederationShare.php index 3ec53d89ed3..2eb06b3acea 100644 --- a/lib/private/Federation/CloudFederationShare.php +++ b/lib/private/Federation/CloudFederationShare.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Federation/CloudId.php b/lib/private/Federation/CloudId.php index c20dbfc6418..b807c29d812 100644 --- a/lib/private/Federation/CloudId.php +++ b/lib/private/Federation/CloudId.php @@ -9,29 +9,15 @@ declare(strict_types=1); namespace OC\Federation; use OCP\Federation\ICloudId; +use OCP\Federation\ICloudIdManager; class CloudId implements ICloudId { - /** @var string */ - private $id; - /** @var string */ - private $user; - /** @var string */ - private $remote; - /** @var string|null */ - private $displayName; - - /** - * CloudId constructor. - * - * @param string $id - * @param string $user - * @param string $remote - */ - public function __construct(string $id, string $user, string $remote, ?string $displayName = null) { - $this->id = $id; - $this->user = $user; - $this->remote = $remote; - $this->displayName = $displayName; + public function __construct( + protected string $id, + protected string $user, + protected string $remote, + protected ?string $displayName = null, + ) { } /** @@ -44,12 +30,18 @@ class CloudId implements ICloudId { } public function getDisplayId(): string { + if ($this->displayName === null) { + /** @var CloudIdManager $cloudIdManager */ + $cloudIdManager = \OCP\Server::get(ICloudIdManager::class); + $this->displayName = $cloudIdManager->getDisplayNameFromContact($this->getId()); + } + + $atHost = str_replace(['http://', 'https://'], '', $this->getRemote()); + if ($this->displayName) { - $atPos = strrpos($this->getId(), '@'); - $atHost = substr($this->getId(), $atPos); - return $this->displayName . $atHost; + return $this->displayName . '@' . $atHost; } - return str_replace('https://', '', str_replace('http://', '', $this->getId())); + return $this->getUser() . '@' . $atHost; } /** diff --git a/lib/private/Federation/CloudIdManager.php b/lib/private/Federation/CloudIdManager.php index 1c808c03eda..c599d9046a6 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; @@ -21,27 +22,21 @@ 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; - /** @var array[] */ + private ICache $displayNameCache; 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']); $eventDispatcher->addListener(CardUpdatedEvent::class, [$this, 'handleCardEvent']); } @@ -79,6 +74,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'); } @@ -104,17 +105,28 @@ class CloudIdManager implements ICloudIdManager { $user = substr($id, 0, $lastValidAtPos); $remote = substr($id, $lastValidAtPos + 1); - $this->userManager->validateUserId($user); + // We accept slightly more chars when working with federationId than with a local userId. + // We remove those eventual chars from the UserId before using + // the IUserManager API to confirm its format. + $this->userManager->validateUserId(str_replace('=', '-', $user)); if (!empty($user) && !empty($remote)) { $remote = $this->ensureDefaultProtocol($remote); - return new CloudId($id, $user, $remote, $this->getDisplayNameFromContact($id)); + return new CloudId($id, $user, $remote, null); } } throw new \InvalidArgumentException('Invalid cloud id'); } - protected function getDisplayNameFromContact(string $cloudId): ?string { + public function getDisplayNameFromContact(string $cloudId): ?string { + $cachedName = $this->displayNameCache->get($cloudId); + if ($cachedName !== null) { + if ($cachedName === $cloudId) { + return null; + } + return $cachedName; + } + $addressBookEntries = $this->contactsManager->search($cloudId, ['CLOUD'], [ 'limit' => 1, 'enumeration' => false, @@ -128,14 +140,17 @@ class CloudIdManager implements ICloudIdManager { // Warning, if user decides to make their full name local only, // no FN is found on federated servers if (isset($entry['FN'])) { + $this->displayNameCache->set($cloudId, $entry['FN'], 15 * 60); return $entry['FN']; } else { - return $cloudID; + $this->displayNameCache->set($cloudId, $cloudId, 15 * 60); + return null; } } } } } + $this->displayNameCache->set($cloudId, $cloudId, 15 * 60); return null; } @@ -168,7 +183,7 @@ class CloudIdManager implements ICloudIdManager { $localUser = $this->userManager->get($user); $displayName = $localUser ? $localUser->getDisplayName() : ''; } else { - $displayName = $this->getDisplayNameFromContact($user . '@' . $host); + $displayName = null; } // For the visible cloudID we only strip away https @@ -235,6 +250,26 @@ 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; + } + + public function createCloudId(string $id, string $user, string $remote, ?string $displayName = null): ICloudId { + return new CloudId($id, $user, $remote, $displayName); + } + + public function registerCloudIdResolver(ICloudIdResolver $resolver): void { + array_unshift($this->cloudIdResolvers, $resolver); + } + + public function unregisterCloudIdResolver(ICloudIdResolver $resolver): void { + if (($key = array_search($resolver, $this->cloudIdResolvers)) !== false) { + array_splice($this->cloudIdResolvers, $key, 1); + } } } |