summaryrefslogtreecommitdiffstats
path: root/apps/user_ldap/user_ldap.php
diff options
context:
space:
mode:
authorArthur Schiwon <blizzz@owncloud.com>2014-08-21 17:59:13 +0200
committerArthur Schiwon <blizzz@owncloud.com>2014-12-19 19:47:54 +0100
commit4fa39250e714b3ee5aa16a5f9ce8c77daa44311b (patch)
tree5c21fabd2942fdc462750625cd29e544c708ac05 /apps/user_ldap/user_ldap.php
parent8164415b45386cb87e05e6e50cf4b8f3128b2e69 (diff)
downloadnextcloud-server-4fa39250e714b3ee5aa16a5f9ce8c77daa44311b.tar.gz
nextcloud-server-4fa39250e714b3ee5aa16a5f9ce8c77daa44311b.zip
LDAP User Cleanup: Port from stable7 without further adjustements
LDAP User Cleanup background job for user clean up adjust user backend for clean up register background job remove dead code dependency injection make Helper non-static for proper testing check whether it is OK to run clean up job. Do not forget to pass arguments. use correct method to get the config from server methods can be private, proper indirect testing is given no automatic user deletion make limit readable for test purposes make method less complex add first tests let preferences accept limit and offset for getUsersForValue DI via constructor does not work for background jobs after detecting, now we have retrieving deleted users and their details we need this method to be public for now finalize export method, add missing getter clean up namespaces and get rid of unnecessary files helper is not static anymore cleanup according to scrutinizer add cli tool to show deleted users uses are necessary after recent namespace change also remove user from mappings table on deletion add occ command to delete users fix use statement improve output big fixes / improvements PHP doc return true in userExists early for cleaning up deleted users bump version control state and interval with one config.php setting, now ldapUserCleanupInterval. 0 will disable it. enabled by default. improve doc rename cli method to be consistent with others introduce ldapUserCleanupInterval in sample config don't show last login as unix epoche start when no login happend less log output consistent namespace for OfflineUser rename GarbageCollector to DeletedUsersIndex and move it to user subdir fix unit tests add tests for deleteUser more test adjustements Conflicts: apps/user_ldap/ajax/clearMappings.php apps/user_ldap/appinfo/app.php apps/user_ldap/lib/access.php apps/user_ldap/lib/helper.php apps/user_ldap/tests/helper.php core/register_command.php lib/private/preferences.php lib/private/user.php add ldap:check-user to check user existance on the fly Conflicts: apps/user_ldap/lib/helper.php forgotten file PHPdoc fixes, no code change and don't forget to adjust tests
Diffstat (limited to 'apps/user_ldap/user_ldap.php')
-rw-r--r--apps/user_ldap/user_ldap.php116
1 files changed, 96 insertions, 20 deletions
diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php
index 482715b3686..2274e4156cc 100644
--- a/apps/user_ldap/user_ldap.php
+++ b/apps/user_ldap/user_ldap.php
@@ -26,16 +26,23 @@
namespace OCA\user_ldap;
use OCA\user_ldap\lib\BackendUtility;
+use OCA\user_ldap\lib\user\OfflineUser;
+use OCA\User_LDAP\lib\User\User;
class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserInterface {
/**
+ * @var string[] $homesToKill
+ */
+ protected $homesToKill = array();
+
+ /**
* checks whether the user is allowed to change his avatar in ownCloud
* @param string $uid the ownCloud user name
* @return boolean either the user can or cannot
*/
public function canChangeAvatar($uid) {
$user = $this->access->userManager->get($uid);
- if(is_null($user)) {
+ if(!$user instanceof User) {
return false;
}
if($user->getAvatarImage() === false) {
@@ -57,15 +64,17 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
$uid = $this->access->escapeFilterPart($uid);
//find out dn of the user name
+ $attrs = array($this->access->connection->ldapUserDisplayName, 'dn',
+ 'uid', 'samaccountname');
$filter = \OCP\Util::mb_str_replace(
'%uid', $uid, $this->access->connection->ldapLoginFilter, 'UTF-8');
- $ldap_users = $this->access->fetchListOfUsers($filter, 'dn');
- if(count($ldap_users) < 1) {
+ $users = $this->access->fetchListOfUsers($filter, $attrs);
+ if(count($users) < 1) {
return false;
}
- $dn = $ldap_users[0];
+ $dn = $users[0]['dn'];
$user = $this->access->userManager->get($dn);
- if(is_null($user)) {
+ if(!$user instanceof User) {
\OCP\Util::writeLog('user_ldap',
'LDAP Login: Could not get user object for DN ' . $dn .
'. Maybe the LDAP entry has no set display name attribute?',
@@ -79,6 +88,15 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
}
$user->markLogin();
+ if(isset($users[0][$this->access->connection->ldapUserDisplayName])) {
+ $dpn = $users[0][$this->access->connection->ldapUserDisplayName];
+ $user->storeDisplayName($dpn);
+ }
+ if(isset($users[0]['uid'])) {
+ $user->storeLDAPUserName($users[0]['uid']);
+ } else if(isset($users[0]['samaccountname'])) {
+ $user->storeLDAPUserName($users[0]['samaccountname']);
+ }
return $user->getUsername();
}
@@ -128,6 +146,33 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
}
/**
+ * checks whether a user is still available on LDAP
+ * @param string|\OCA\User_LDAP\lib\user\User $user either the ownCloud user
+ * name or an instance of that user
+ * @return bool
+ */
+ public function userExistsOnLDAP($user) {
+ if(is_string($user)) {
+ $user = $this->access->userManager->get($user);
+ }
+ if(!$user instanceof User) {
+ return false;
+ }
+
+ $dn = $user->getDN();
+ //check if user really still exists by reading its entry
+ if(!is_array($this->access->readAttribute($dn, ''))) {
+ $lcr = $this->access->connection->getConnectionResource();
+ if(is_null($lcr)) {
+ throw new \Exception('No LDAP Connection to server ' . $this->access->connection->ldapHost);
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
* check if a user exists
* @param string $uid the username
* @return boolean
@@ -143,36 +188,56 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
$this->access->connection->ldapHost, \OCP\Util::DEBUG);
$this->access->connection->writeToCache('userExists'.$uid, false);
return false;
+ } else if($user instanceof OfflineUser) {
+ //express check for users marked as deleted. Returning true is
+ //necessary for cleanup
+ return true;
}
- $dn = $user->getDN();
- //check if user really still exists by reading its entry
- if(!is_array($this->access->readAttribute($dn, ''))) {
- \OCP\Util::writeLog('user_ldap', 'LDAP says no user '.$dn.' on '.
- $this->access->connection->ldapHost, \OCP\Util::DEBUG);
- $this->access->connection->writeToCache('userExists'.$uid, false);
+
+ try {
+ $result = $this->userExistsOnLDAP($user);
+ $this->access->connection->writeToCache('userExists'.$uid, $result);
+ if($result === true) {
+ $user->update();
+ }
+ return $result;
+ } catch (\Exception $e) {
+ \OCP\Util::writeLog('user_ldap', $e->getMessage(), \OCP\Util::WARN);
return false;
}
-
- $this->access->connection->writeToCache('userExists'.$uid, true);
- $user->update();
- return true;
}
/**
- * delete a user
+ * returns whether a user was deleted in LDAP
+ *
* @param string $uid The username of the user to delete
* @return bool
- *
- * Deletes a user
*/
public function deleteUser($uid) {
- return false;
+ $pref = \OC::$server->getConfig();
+ $marked = $pref->getUserValue($uid, 'user_ldap', 'isDeleted', 0);
+ if(intval($marked) === 0) {
+ \OC::$server->getLogger()->notice(
+ 'User '.$uid . ' is not marked as deleted, not cleaning up.',
+ array('app' => 'user_ldap'));
+ return false;
+ }
+ \OC::$server->getLogger()->info('Cleaning up after user ' . $uid,
+ array('app' => 'user_ldap'));
+
+ //Get Home Directory out of user preferences so we can return it later,
+ //necessary for removing directories as done by OC_User.
+ $home = $pref->getUserValue($uid, 'user_ldap', 'homePath', '');
+ $this->homesToKill[$uid] = $home;
+ $this->access->unmapUser($uid);
+
+ return true;
}
/**
* get the user's home directory
* @param string $uid the username
- * @return boolean
+ * @return string|bool
*/
public function getHome($uid) {
// user Exists check required as it is not done in user proxy!
@@ -180,10 +245,16 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
return false;
}
+ if(isset($this->homesToKill[$uid]) && !empty($this->homesToKill[$uid])) {
+ //a deleted user who needs some clean up
+ return $this->homesToKill[$uid];
+ }
+
$cacheKey = 'getHome'.$uid;
if($this->access->connection->isCached($cacheKey)) {
return $this->access->connection->getFromCache($cacheKey);
}
+ $pref = \OC::$server->getConfig();
if(strpos($this->access->connection->homeFolderNamingRule, 'attr:') === 0) {
$attr = substr($this->access->connection->homeFolderNamingRule, strlen('attr:'));
$homedir = $this->access->readAttribute(
@@ -203,12 +274,17 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
\OC::$SERVERROOT.'/data' ) . '/' . $homedir[0];
}
$this->access->connection->writeToCache($cacheKey, $homedir);
+ //we need it to store it in the DB as well in case a user gets
+ //deleted so we can clean up afterwards
+ $pref->setUserValue($uid, 'user_ldap', 'homePath', $homedir);
+ //TODO: if home directory changes, the old one needs to be removed.
return $homedir;
}
}
//false will apply default behaviour as defined and done by OC_User
$this->access->connection->writeToCache($cacheKey, false);
+ $pref->setUserValue($uid, 'user_ldap', 'homePath', '');
return false;
}