mirror of
https://github.com/nextcloud/server.git
synced 2026-06-13 18:50:47 -04:00
fix(LDAP): unblock a cached id from a deleted user or group
As of 155b75027c we cache the user id and
LDAP DN for a month, because they are highly requested, but rarely change
and we have a working repair mechanism.
But if an LDAP user is deleted, the information is still cached. So a user
that is being regenerated with the same target user ID will get a _xxxx
suffix, when the data is still in local cache.
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
This commit is contained in:
parent
d14cf6a8be
commit
5ce8e06add
3 changed files with 32 additions and 7 deletions
|
|
@ -57,6 +57,7 @@ class Access extends LDAPUtility {
|
|||
private Helper $helper,
|
||||
private IConfig $config,
|
||||
private IUserManager $ncUserManager,
|
||||
private IGroupManager $ncGroupManager,
|
||||
private LoggerInterface $logger,
|
||||
private IAppConfig $appConfig,
|
||||
private IEventDispatcher $dispatcher,
|
||||
|
|
@ -595,18 +596,35 @@ class Access extends LDAPUtility {
|
|||
$originalTTL = $this->connection->ldapCacheTTL;
|
||||
$this->connection->setConfiguration(['ldapCacheTTL' => 0]);
|
||||
if ($intName !== ''
|
||||
&& (($isUser && !$this->ncUserManager->userExists($intName))
|
||||
|| (!$isUser && !Server::get(IGroupManager::class)->groupExists($intName))
|
||||
&& (($isUser
|
||||
&& (
|
||||
!$this->ncUserManager->userExists($intName)
|
||||
// DN might be cached if the user was deleted within last month.
|
||||
// If it was a valid user we would have returned earlier at the
|
||||
// $mapper->getNameByDN($fdn) call, which does not run against the cache.
|
||||
|| $this->ncUserManager->get($intName)?->getBackendClassName() === 'LDAP'
|
||||
))
|
||||
|| (!$isUser
|
||||
&& (
|
||||
// DN might be cached if the group was deleted within last month.
|
||||
// If it was a valid group we would have returned earlier at the
|
||||
// $mapper->getNameByDN($fdn) call, which does not run against the cache.
|
||||
!$this->ncGroupManager->groupExists($intName)
|
||||
|| in_array('LDAP', $this->ncGroupManager->get($intName)?->getBackendNames() ?? [], true)
|
||||
))
|
||||
)
|
||||
) {
|
||||
$this->connection->setConfiguration(['ldapCacheTTL' => $originalTTL]);
|
||||
$newlyMapped = $this->mapAndAnnounceIfApplicable($mapper, $fdn, $intName, $uuid, $isUser);
|
||||
if ($newlyMapped) {
|
||||
$this->logger->debug('Mapped {fdn} as {name}', ['fdn' => $fdn,'name' => $intName]);
|
||||
$this->logger->debug('Mapped {fdn} as {name}', ['fdn' => $fdn, 'name' => $intName]);
|
||||
return $intName;
|
||||
}
|
||||
}
|
||||
|
||||
$dude = $this->ncUserManager->get($intName);
|
||||
$dude->getBackendClassName() === 'LDAP';
|
||||
|
||||
$this->connection->setConfiguration(['ldapCacheTTL' => $originalTTL]);
|
||||
$altName = $this->createAltInternalOwnCloudName($intName, $isUser);
|
||||
if (is_string($altName)) {
|
||||
|
|
@ -830,7 +848,7 @@ class Access extends LDAPUtility {
|
|||
// Check to be really sure it is unique
|
||||
// while loop is just a precaution. If a name is not generated within
|
||||
// 20 attempts, something else is very wrong. Avoids infinite loop.
|
||||
if (!Server::get(IGroupManager::class)->groupExists($altName)) {
|
||||
if (!$this->ncGroupManager->groupExists($altName)) {
|
||||
return $altName;
|
||||
}
|
||||
$altName = $name . '_' . ($lastNo + $attempts);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use OCA\User_LDAP\User\Manager;
|
|||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\IAppConfig;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Server;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
|
@ -22,6 +23,7 @@ class AccessFactory {
|
|||
private IConfig $config,
|
||||
private IAppConfig $appConfig,
|
||||
private IUserManager $ncUserManager,
|
||||
private IGroupManager $ncGroupManager,
|
||||
private LoggerInterface $logger,
|
||||
private IEventDispatcher $dispatcher,
|
||||
) {
|
||||
|
|
@ -36,6 +38,7 @@ class AccessFactory {
|
|||
$this->helper,
|
||||
$this->config,
|
||||
$this->ncUserManager,
|
||||
$this->ncGroupManager,
|
||||
$this->logger,
|
||||
$this->appConfig,
|
||||
$this->dispatcher,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ use OCP\HintException;
|
|||
use OCP\IAppConfig;
|
||||
use OCP\IAvatarManager;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\Image;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Notification\IManager as INotificationManager;
|
||||
|
|
@ -51,6 +52,7 @@ class AccessTest extends TestCase {
|
|||
private Helper&MockObject $helper;
|
||||
private IConfig&MockObject $config;
|
||||
private IUserManager&MockObject $ncUserManager;
|
||||
private IGroupManager&MockObject $ncGroupManager;
|
||||
private LoggerInterface&MockObject $logger;
|
||||
private IAppConfig&MockObject $appConfig;
|
||||
private IEventDispatcher&MockObject $dispatcher;
|
||||
|
|
@ -67,6 +69,7 @@ class AccessTest extends TestCase {
|
|||
$this->userMapper = $this->createMock(UserMapping::class);
|
||||
$this->groupMapper = $this->createMock(GroupMapping::class);
|
||||
$this->ncUserManager = $this->createMock(IUserManager::class);
|
||||
$this->ncGroupManager = $this->createMock(IGroupManager::class);
|
||||
$this->shareManager = $this->createMock(IManager::class);
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
$this->appConfig = $this->createMock(IAppConfig::class);
|
||||
|
|
@ -79,6 +82,7 @@ class AccessTest extends TestCase {
|
|||
$this->helper,
|
||||
$this->config,
|
||||
$this->ncUserManager,
|
||||
$this->ncGroupManager,
|
||||
$this->logger,
|
||||
$this->appConfig,
|
||||
$this->dispatcher,
|
||||
|
|
@ -224,7 +228,7 @@ class AccessTest extends TestCase {
|
|||
[$lw, $con, $um, $helper] = $this->getConnectorAndLdapMock();
|
||||
/** @var IConfig&MockObject $config */
|
||||
$config = $this->createMock(IConfig::class);
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->logger, $this->appConfig, $this->dispatcher);
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->ncGroupManager, $this->logger, $this->appConfig, $this->dispatcher);
|
||||
|
||||
$lw->expects($this->exactly(1))
|
||||
->method('explodeDN')
|
||||
|
|
@ -244,7 +248,7 @@ class AccessTest extends TestCase {
|
|||
/** @var IConfig&MockObject $config */
|
||||
$config = $this->createMock(IConfig::class);
|
||||
$lw = new LDAP();
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->logger, $this->appConfig, $this->dispatcher);
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->ncGroupManager, $this->logger, $this->appConfig, $this->dispatcher);
|
||||
|
||||
if (!function_exists('ldap_explode_dn')) {
|
||||
$this->markTestSkipped('LDAP Module not available');
|
||||
|
|
@ -427,7 +431,7 @@ class AccessTest extends TestCase {
|
|||
$attribute => ['count' => 1, $dnFromServer]
|
||||
]);
|
||||
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->logger, $this->appConfig, $this->dispatcher);
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->ncGroupManager, $this->logger, $this->appConfig, $this->dispatcher);
|
||||
$values = $access->readAttribute('uid=whoever,dc=example,dc=org', $attribute);
|
||||
$this->assertSame($values[0], strtolower($dnFromServer));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue