Skip to content

Commit 5d044e6

Browse files
Merge pull request #2108 from nextcloud/feat/noid/cache-user-single-id
feat: caching user single id in preferences
2 parents 8751a66 + 8de3a62 commit 5d044e6

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

lib/AppInfo/Application.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace OCA\Circles\AppInfo;
1313

1414
use Closure;
15+
use OCA\Circles\ConfigLexicon;
1516
use OCA\Circles\Dashboard\TeamDashboardWidget;
1617
use OCA\Circles\Events\AddingCircleMemberEvent;
1718
use OCA\Circles\Events\CircleMemberAddedEvent;
@@ -122,6 +123,8 @@ public function register(IRegistrationContext $context): void {
122123

123124
$context->registerDashboardWidget(TeamDashboardWidget::class);
124125
$context->registerTeamResourceProvider(FileSharingTeamResourceProvider::class);
126+
127+
$context->registerConfigLexicon(ConfigLexicon::class);
125128
}
126129

127130

lib/ConfigLexicon.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
6+
* SPDX-License-Identifier: AGPL-3.0-or-later
7+
*/
8+
9+
namespace OCA\Circles;
10+
11+
use OCP\Config\IUserConfig;
12+
use OCP\Config\Lexicon\Entry;
13+
use OCP\Config\Lexicon\ILexicon;
14+
use OCP\Config\Lexicon\Strictness;
15+
use OCP\Config\ValueType;
16+
17+
/**
18+
* Config Lexicon for circles/teams.
19+
*
20+
* Please Add & Manage your Config Keys in that file and keep the Lexicon up to date!
21+
*/
22+
class ConfigLexicon implements ILexicon {
23+
public const USER_SINGLE_ID = 'userSingleId';
24+
25+
public function getStrictness(): Strictness {
26+
return Strictness::IGNORE;
27+
}
28+
29+
public function getAppConfigs(): array {
30+
return [
31+
];
32+
}
33+
34+
public function getUserConfigs(): array {
35+
return [
36+
new Entry(key: self::USER_SINGLE_ID, type: ValueType::STRING, defaultRaw: '', definition: 'caching singleId for each local account', lazy: false, flags: IUserConfig::FLAG_INDEXED),
37+
];
38+
}
39+
}

lib/Service/FederatedUserService.php

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Exception;
1515
use OC;
1616
use OCA\Circles\AppInfo\Application;
17+
use OCA\Circles\ConfigLexicon;
1718
use OCA\Circles\Db\AccountsRequest;
1819
use OCA\Circles\Db\CircleRequest;
1920
use OCA\Circles\Db\MemberRequest;
@@ -54,6 +55,7 @@
5455
use OCA\Circles\Tools\Traits\TDeserialize;
5556
use OCA\Circles\Tools\Traits\TNCLogger;
5657
use OCA\Circles\Tools\Traits\TStringTools;
58+
use OCP\Config\IUserConfig;
5759
use OCP\ICache;
5860
use OCP\ICacheFactory;
5961
use OCP\IGroupManager;
@@ -177,6 +179,7 @@ public function __construct(
177179
ContactService $contactService,
178180
InterfaceService $interfaceService,
179181
ConfigService $configService,
182+
private readonly IUserConfig $userConfig,
180183
) {
181184
$this->userSession = $userSession;
182185
$this->userManager = $userManager;
@@ -520,11 +523,44 @@ public function getLocalFederatedUser(string $userId, bool $check = true, bool $
520523

521524
$federatedUser = new FederatedUser();
522525
$federatedUser->set($userId, '', Member::TYPE_USER, $displayName);
523-
$this->fillSingleCircleId($federatedUser, ($check || $generate));
526+
527+
$cached = $this->getCachedLocalFederatedUser($federatedUser);
528+
if (!$cached) {
529+
$this->fillSingleCircleId($federatedUser, ($check || $generate));
530+
$this->userConfig->setValueString($userId, Application::APP_ID, ConfigLexicon::USER_SINGLE_ID, $federatedUser->getSingleId());
531+
}
524532

525533
return $federatedUser;
526534
}
527535

536+
/**
537+
* get singleId from UserConfig (already loaded from database)
538+
* and emulate FederatedUser for local accounts.
539+
*/
540+
private function getCachedLocalFederatedUser(IFederatedUser $federatedUser): bool {
541+
if ($federatedUser->getUserType() !== Member::TYPE_USER || !$federatedUser->isLocal()) {
542+
return false;
543+
}
544+
545+
$userSingleId = $this->userConfig->getValueString($federatedUser->getUserId(), Application::APP_ID, ConfigLexicon::USER_SINGLE_ID);
546+
if ($userSingleId === '') {
547+
return false;
548+
}
549+
550+
$federatedUser->setSingleId($userSingleId);
551+
// setBasedOn() should be useless, but we want to keep backward compatibility
552+
$federatedUser->setBasedOn(
553+
(new Circle())->import([
554+
'id' => $userSingleId,
555+
'name' => 'user:' . $federatedUser->getUserId() . ':' . $userSingleId,
556+
'displayName' => $federatedUser->getDisplayName(),
557+
'source' => 1,
558+
'config' => 1,
559+
])
560+
);
561+
562+
return true;
563+
}
528564

529565
/**
530566
* Get the full FederatedUser for a local user.

0 commit comments

Comments
 (0)