diff options
author | Robin Appelman <robin@icewind.nl> | 2022-08-30 18:14:45 +0200 |
---|---|---|
committer | Robin Appelman <robin@icewind.nl> | 2022-08-31 13:33:33 +0200 |
commit | d3743392e0087c267d20db14210acba17a3ec6d2 (patch) | |
tree | 6970249ad2b6c1fa64740a0394339ba1e245c485 | |
parent | f56ecf92426026c913497bea9f7ca99e8d3ac631 (diff) | |
download | nextcloud-server-d3743392e0087c267d20db14210acba17a3ec6d2.tar.gz nextcloud-server-d3743392e0087c267d20db14210acba17a3ec6d2.zip |
cache cloud id data in CloudIdManager
Signed-off-by: Robin Appelman <robin@icewind.nl>
-rw-r--r-- | lib/private/Federation/CloudIdManager.php | 79 | ||||
-rw-r--r-- | lib/private/Server.php | 8 |
2 files changed, 80 insertions, 7 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); } diff --git a/lib/private/Server.php b/lib/private/Server.php index 09074e39046..0b9957659a5 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -1361,7 +1361,13 @@ class Server extends ServerContainer implements IServerContainer { }); $this->registerService(ICloudIdManager::class, function (ContainerInterface $c) { - return new CloudIdManager($c->get(\OCP\Contacts\IManager::class), $c->get(IURLGenerator::class), $c->get(IUserManager::class)); + return new CloudIdManager( + $c->get(\OCP\Contacts\IManager::class), + $c->get(IURLGenerator::class), + $c->get(IUserManager::class), + $c->get(ICacheFactory::class), + $c->get(EventDispatcherInterface::class), + ); }); $this->registerAlias(\OCP\GlobalScale\IConfig::class, \OC\GlobalScale\Config::class); |