diff options
author | Arthur Schiwon <blizzz@owncloud.com> | 2014-08-21 17:59:13 +0200 |
---|---|---|
committer | Arthur Schiwon <blizzz@owncloud.com> | 2014-12-19 19:47:54 +0100 |
commit | 4fa39250e714b3ee5aa16a5f9ce8c77daa44311b (patch) | |
tree | 5c21fabd2942fdc462750625cd29e544c708ac05 /apps/user_ldap/user_ldap.php | |
parent | 8164415b45386cb87e05e6e50cf4b8f3128b2e69 (diff) | |
download | nextcloud-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.php | 116 |
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; } |