Fix LDAP LoginListener by adding new group relationships to caches before firing the event

Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
This commit is contained in:
Côme Chilliet 2023-09-12 12:15:30 +02:00
parent 800b1b7031
commit 05efbf11d9
No known key found for this signature in database
GPG key ID: A3E2F658B28C760A
3 changed files with 38 additions and 3 deletions

View file

@ -56,9 +56,9 @@ use Psr\Log\LoggerInterface;
class Group_LDAP extends ABackend implements GroupInterface, IGroupLDAP, IGetDisplayNameBackend, IDeleteGroupBackend {
protected bool $enabled = false;
/** @var CappedMemoryCache<string[]> $cachedGroupMembers array of users with gid as key */
/** @var CappedMemoryCache<string[]> $cachedGroupMembers array of user DN with gid as key */
protected CappedMemoryCache $cachedGroupMembers;
/** @var CappedMemoryCache<array[]> $cachedGroupsByMember array of groups with uid as key */
/** @var CappedMemoryCache<array[]> $cachedGroupsByMember array of groups with user DN as key */
protected CappedMemoryCache $cachedGroupsByMember;
/** @var CappedMemoryCache<string[]> $cachedNestedGroups array of groups with gid (DN) as key */
protected CappedMemoryCache $cachedNestedGroups;
@ -1357,4 +1357,35 @@ class Group_LDAP extends ABackend implements GroupInterface, IGroupLDAP, IGetDis
public function dn2GroupName(string $dn): string|false {
return $this->access->dn2groupname($dn);
}
public function addRelationshipToCaches(string $uid, ?string $dnUser, string $gid): void {
$dnGroup = $this->access->groupname2dn($gid);
$dnUser ??= $this->access->username2dn($uid);
if ($dnUser === false || $dnGroup === false) {
return;
}
if (isset($this->cachedGroupMembers[$gid])) {
$this->cachedGroupMembers[$gid] = array_merge($this->cachedGroupMembers[$gid], [$dnUser]);
}
unset($this->cachedGroupsByMember[$dnUser]);
unset($this->cachedNestedGroups[$gid]);
$cacheKey = 'inGroup' . $uid . ':' . $gid;
$this->access->connection->writeToCache($cacheKey, true);
$cacheKeyMembers = 'inGroup-members:' . $gid;
if (!is_null($data = $this->access->connection->getFromCache($cacheKeyMembers))) {
$this->access->connection->writeToCache($cacheKeyMembers, array_merge($data, [$dnUser]));
}
$cacheKey = '_groupMembers' . $dnGroup;
if (!is_null($data = $this->access->connection->getFromCache($cacheKey))) {
$this->access->connection->writeToCache($cacheKey, array_merge($data, [$dnUser]));
}
$cacheKey = 'getUserGroups' . $uid;
if (!is_null($data = $this->access->connection->getFromCache($cacheKey))) {
$this->access->connection->writeToCache($cacheKey, array_merge($data, [$gid]));
}
// These cache keys cannot be easily updated:
// $cacheKey = 'usersInGroup-' . $gid . '-' . $search . '-' . $limit . '-' . $offset;
// $cacheKey = 'usersInGroup-' . $gid . '-' . $search;
// $cacheKey = 'countUsersInGroup-' . $gid . '-' . $search;
}
}

View file

@ -384,4 +384,8 @@ class Group_Proxy extends Proxy implements \OCP\GroupInterface, IGroupLDAP, IGet
public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array {
return $this->handleRequest($gid, 'searchInGroup', [$gid, $search, $limit, $offset]);
}
public function addRelationshipToCaches(string $uid, ?string $dnUser, string $gid): void {
$this->handleRequest($gid, 'addRelationshipToCaches', [$uid, $dnUser, $gid]);
}
}

View file

@ -93,7 +93,7 @@ class LoginListener implements IEventListener {
continue;
}
$this->groupMembershipMapper->insert(GroupMembership::fromParams(['groupid' => $groupId,'userid' => $userId]));
// TODO: empty cache to avoid crash
$this->groupBackend->addRelationshipToCaches($userId, null, $groupId);
$this->dispatcher->dispatchTyped(new UserAddedEvent($groupObject, $userObject));
$this->logger->info(
__CLASS__ . ' {user} added to {group}',