decouple userExists from userExistsOnLDAP check

allows to mark users as offline right away, avoids a gap of being not a
user and causing weird side effects

Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
This commit is contained in:
Arthur Schiwon 2019-11-29 13:21:45 +01:00 committed by Christoph Wurst
parent 411a47cadb
commit 5cae135b94
No known key found for this signature in database
GPG Key ID: CC42AC2A7F0E56D8
3 changed files with 57 additions and 15 deletions

View File

@ -175,6 +175,21 @@ class User {
} }
} }
/**
* marks a user as deleted
*
* @throws \OCP\PreConditionNotMetException
*/
public function markUser() {
$curValue = $this->config->getUserValue($this->getUsername(), 'user_ldap', 'isDeleted', '0');
if($curValue === '1') {
// the user is already marked, do not write to DB again
return;
}
$this->config->setUserValue($this->getUsername(), 'user_ldap', 'isDeleted', '1');
$this->config->setUserValue($this->getUsername(), 'user_ldap', 'foundDeleted', (string)time());
}
/** /**
* processes results from LDAP for attributes as returned by getAttributesToRead() * processes results from LDAP for attributes as returned by getAttributesToRead()
* @param array $ldapEntry the user entry as retrieved from LDAP * @param array $ldapEntry the user entry as retrieved from LDAP

View File

@ -297,6 +297,12 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
if(is_null($user)) { if(is_null($user)) {
return false; return false;
} }
$uid = $user instanceof User ? $user->getUsername() : $user->getOCName();
$cacheKey = 'userExistsOnLDAP' . $uid;
$userExists = $this->access->connection->getFromCache($cacheKey);
if(!is_null($userExists)) {
return (bool)$userExists;
}
$dn = $user->getDN(); $dn = $user->getDN();
//check if user really still exists by reading its entry //check if user really still exists by reading its entry
@ -304,18 +310,22 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
try { try {
$uuid = $this->access->getUserMapper()->getUUIDByDN($dn); $uuid = $this->access->getUserMapper()->getUUIDByDN($dn);
if (!$uuid) { if (!$uuid) {
$this->access->connection->writeToCache($cacheKey, false);
return false; return false;
} }
$newDn = $this->access->getUserDnByUuid($uuid); $newDn = $this->access->getUserDnByUuid($uuid);
//check if renamed user is still valid by reapplying the ldap filter //check if renamed user is still valid by reapplying the ldap filter
if ($newDn === $dn || !is_array($this->access->readAttribute($newDn, '', $this->access->connection->ldapUserFilter))) { if ($newDn === $dn || !is_array($this->access->readAttribute($newDn, '', $this->access->connection->ldapUserFilter))) {
$this->access->connection->writeToCache($cacheKey, false);
return false; return false;
} }
$this->access->getUserMapper()->setDNbyUUID($newDn, $uuid); $this->access->getUserMapper()->setDNbyUUID($newDn, $uuid);
$this->access->connection->writeToCache($cacheKey, true);
return true; return true;
} catch (ServerNotAvailableException $e) { } catch (ServerNotAvailableException $e) {
throw $e; throw $e;
} catch (\Exception $e) { } catch (\Exception $e) {
$this->access->connection->writeToCache($cacheKey, false);
return false; return false;
} }
} }
@ -324,6 +334,7 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
$user->unmark(); $user->unmark();
} }
$this->access->connection->writeToCache($cacheKey, true);
return true; return true;
} }
@ -346,15 +357,10 @@ class User_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
$this->access->connection->ldapHost, ILogger::DEBUG); $this->access->connection->ldapHost, ILogger::DEBUG);
$this->access->connection->writeToCache('userExists'.$uid, false); $this->access->connection->writeToCache('userExists'.$uid, false);
return false; return false;
} else if($user instanceof OfflineUser) {
//express check for users marked as deleted. Returning true is
//necessary for cleanup
return true;
} }
$result = $this->userExistsOnLDAP($user); $this->access->connection->writeToCache('userExists'.$uid, true);
$this->access->connection->writeToCache('userExists'.$uid, $result); return true;
return $result;
} }
/** /**

View File

@ -37,7 +37,8 @@ use OCP\IUserSession;
use OCP\Notification\IManager as INotificationManager; use OCP\Notification\IManager as INotificationManager;
class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface, IUserLDAP { class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface, IUserLDAP {
private $backends = array(); private $backends = [];
/** @var User_LDAP */
private $refBackend = null; private $refBackend = null;
/** /**
@ -49,9 +50,14 @@ class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface,
* @param INotificationManager $notificationManager * @param INotificationManager $notificationManager
* @param IUserSession $userSession * @param IUserSession $userSession
*/ */
public function __construct(array $serverConfigPrefixes, ILDAPWrapper $ldap, IConfig $ocConfig, public function __construct(
INotificationManager $notificationManager, IUserSession $userSession, array $serverConfigPrefixes,
UserPluginManager $userPluginManager) { ILDAPWrapper $ldap,
IConfig $ocConfig,
INotificationManager $notificationManager,
IUserSession $userSession,
UserPluginManager $userPluginManager
) {
parent::__construct($ldap); parent::__construct($ldap);
foreach($serverConfigPrefixes as $configPrefix) { foreach($serverConfigPrefixes as $configPrefix) {
$this->backends[$configPrefix] = $this->backends[$configPrefix] =
@ -105,13 +111,13 @@ class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface,
&& method_exists($this->getAccess($prefix), $method)) { && method_exists($this->getAccess($prefix), $method)) {
$instance = $this->getAccess($prefix); $instance = $this->getAccess($prefix);
} }
$result = call_user_func_array(array($instance, $method), $parameters); $result = call_user_func_array([$instance, $method], $parameters);
if($result === $passOnWhen) { if($result === $passOnWhen) {
//not found here, reset cache to null if user vanished //not found here, reset cache to null if user vanished
//because sometimes methods return false with a reason //because sometimes methods return false with a reason
$userExists = call_user_func_array( $userExists = call_user_func_array(
array($this->backends[$prefix], 'userExists'), [$this->backends[$prefix], 'userExistsOnLDAP'],
array($uid) [$uid]
); );
if(!$userExists) { if(!$userExists) {
$this->writeToCache($cacheKey, null); $this->writeToCache($cacheKey, null);
@ -170,7 +176,22 @@ class User_Proxy extends Proxy implements \OCP\IUserBackend, \OCP\UserInterface,
* @return boolean * @return boolean
*/ */
public function userExists($uid) { public function userExists($uid) {
return $this->handleRequest($uid, 'userExists', array($uid)); $existsOnLDAP = false;
$existsLocally = $this->handleRequest($uid, 'userExists', array($uid));
if($existsLocally) {
$existsOnLDAP = $this->userExistsOnLDAP($uid);
}
if($existsLocally && !$existsOnLDAP) {
try {
$user = $this->getLDAPAccess($uid)->userManager->get($uid);
if($user instanceof User) {
$user->markUser();
}
} catch (\Exception $e) {
// ignore
}
}
return $existsLocally;
} }
/** /**