diff options
Diffstat (limited to 'lib/private/Federation/CloudIdManager.php')
-rw-r--r-- | lib/private/Federation/CloudIdManager.php | 79 |
1 files changed, 73 insertions, 6 deletions
diff --git a/lib/private/Federation/CloudIdManager.php b/lib/private/Federation/CloudIdManager.php index 77bb9437ba2..e4e42cb1293 100644 --- a/lib/private/Federation/CloudIdManager.php +++ b/lib/private/Federation/CloudIdManager.php @@ -30,11 +30,17 @@ declare(strict_types=1); */ namespace OC\Federation; +use OCA\DAV\Events\CardUpdatedEvent; use OCP\Contacts\IManager; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Federation\ICloudId; use OCP\Federation\ICloudIdManager; +use OCP\ICache; +use OCP\ICacheFactory; use OCP\IURLGenerator; use OCP\IUserManager; +use OCP\User\Events\UserChangedEvent; class CloudIdManager implements ICloudIdManager { /** @var IManager */ @@ -43,11 +49,48 @@ class CloudIdManager implements ICloudIdManager { private $urlGenerator; /** @var IUserManager */ private $userManager; - - public function __construct(IManager $contactsManager, IURLGenerator $urlGenerator, IUserManager $userManager) { + private ICache $memCache; + /** @var array[] */ + private array $cache = []; + + public function __construct( + IManager $contactsManager, + IURLGenerator $urlGenerator, + IUserManager $userManager, + ICacheFactory $cacheFactory, + IEventDispatcher $eventDispatcher + ) { $this->contactsManager = $contactsManager; $this->urlGenerator = $urlGenerator; $this->userManager = $userManager; + $this->memCache = $cacheFactory->createDistributed('cloud_id_'); + $eventDispatcher->addListener(UserChangedEvent::class, [$this, 'handleUserEvent']); + $eventDispatcher->addListener(CardUpdatedEvent::class, [$this, 'handleCardEvent']); + } + + public function handleUserEvent(Event $event): void { + if ($event instanceof UserChangedEvent && $event->getFeature() === 'displayName') { + $userId = $event->getUser()->getUID(); + $key = $userId . '@local'; + unset($this->cache[$key]); + $this->memCache->remove($key); + } + } + + public function handleCardEvent(Event $event): void { + if ($event instanceof CardUpdatedEvent) { + $data = $event->getCardData()['carddata']; + foreach (explode("\r\n", $data) as $line) { + if (strpos($line, "CLOUD;") === 0) { + $parts = explode(':', $line, 2); + if (isset($parts[1])) { + $key = $parts[1]; + unset($this->cache[$key]); + $this->memCache->remove($key); + } + } + } + } } /** @@ -120,18 +163,42 @@ class CloudIdManager implements ICloudIdManager { * @return CloudId */ public function getCloudId(string $user, ?string $remote): ICloudId { - if ($remote === null) { + $isLocal = $remote === null; + if ($isLocal) { $remote = rtrim($this->removeProtocolFromUrl($this->urlGenerator->getAbsoluteURL('/')), '/'); $fixedRemote = $this->fixRemoteURL($remote); - $localUser = $this->userManager->get($user); - $displayName = !is_null($localUser) ? $localUser->getDisplayName() : ''; + $host = $fixedRemote; } else { - // TODO check what the correct url is for remote (asking the remote) + // note that for remote id's we don't strip the protocol for the remote we use to construct the CloudId + // this way if a user has an explicit non-https cloud id this will be preserved + // we do still use the version without protocol for looking up the display name $fixedRemote = $this->fixRemoteURL($remote); $host = $this->removeProtocolFromUrl($fixedRemote); + } + + $key = $user . '@' . ($isLocal ? 'local' : $host); + $cached = $this->cache[$key] ?? $this->memCache->get($key); + if ($cached) { + $this->cache[$key] = $cached; // put items from memcache into local cache + return new CloudId($cached['id'], $cached['user'], $cached['remote'], $cached['displayName']); + } + + if ($isLocal) { + $localUser = $this->userManager->get($user); + $displayName = $localUser ? $localUser->getDisplayName() : ''; + } else { $displayName = $this->getDisplayNameFromContact($user . '@' . $host); } $id = $user . '@' . $remote; + + $data = [ + 'id' => $id, + 'user' => $user, + 'remote' => $fixedRemote, + 'displayName' => $displayName, + ]; + $this->cache[$key] = $data; + $this->memCache->set($key, $data, 15 * 60); return new CloudId($id, $user, $fixedRemote, $displayName); } |