From 6141dcfe675514fd51f72b5a6ca91995240f374a Mon Sep 17 00:00:00 2001 From: Cameron Ball Date: Fri, 11 Mar 2016 16:44:53 +0800 Subject: [PATCH] MDL-52386 auth_ldap: Add support for disabled accounts --- auth/ldap/auth.php | 37 +++++++++++++++++++++++++++++++++ auth/ldap/config.html | 29 ++++++++++++++++++++++++++ auth/ldap/lang/en/auth_ldap.php | 2 ++ lang/en/auth.php | 2 ++ 4 files changed, 70 insertions(+) diff --git a/auth/ldap/auth.php b/auth/ldap/auth.php index 7098223be34..30536e6bca7 100644 --- a/auth/ldap/auth.php +++ b/auth/ldap/auth.php @@ -849,6 +849,9 @@ class auth_plugin_ldap extends auth_plugin_base { } } } + if ($this->config->suspended_attribute && $this->config->sync_suspended) { + $updatekeys[] = 'suspended'; + } unset($all_keys); unset($key); } else { @@ -931,6 +934,10 @@ class auth_plugin_ldap extends auth_plugin_base { // get_userinfo_asobj() might have replaced $user->username with the value // from the LDAP server (which can be mixed-case). Make sure it's lowercase $user->username = trim(core_text::strtolower($user->username)); + // It isn't possible to just rely on the configured suspension attribute since + // things like active directory use bit masks, other things using LDAP might + // do different stuff as well. + $user->suspended = $this->is_user_suspended($user); if (empty($user->lang)) { $user->lang = $CFG->lang; } @@ -1005,6 +1012,7 @@ class auth_plugin_ldap extends auth_plugin_base { if (!empty($updatekeys)) { $newuser = new stdClass(); $newuser->id = $userid; + $newuser->suspended = $this->is_user_suspended((object) $newinfo); foreach ($updatekeys as $key) { if (isset($newinfo[$key])) { @@ -1504,6 +1512,7 @@ class auth_plugin_ldap extends auth_plugin_base { } } $moodleattributes['username'] = core_text::strtolower(trim($this->config->user_attribute)); + $moodleattributes['suspended'] = core_text::strtolower(trim($this->config->suspended_attribute)); return $moodleattributes; } @@ -1848,6 +1857,12 @@ class auth_plugin_ldap extends auth_plugin_base { if (!isset($config->user_attribute)) { $config->user_attribute = ''; } + if (!isset($config->suspended_attribute)) { + $config->suspended_attribute = ''; + } + if (!isset($config->sync_suspended)) { + $config->sync_suspended = false; + } if (!isset($config->search_sub)) { $config->search_sub = ''; } @@ -1944,6 +1959,8 @@ class auth_plugin_ldap extends auth_plugin_base { set_config('contexts', $config->contexts, $this->pluginconfig); set_config('user_type', core_text::strtolower(trim($config->user_type)), $this->pluginconfig); set_config('user_attribute', core_text::strtolower(trim($config->user_attribute)), $this->pluginconfig); + set_config('suspended_attribute', core_text::strtolower(trim($config->suspended_attribute)), $this->pluginconfig); + set_config('sync_suspended', $config->sync_suspended, $this->pluginconfig); set_config('search_sub', $config->search_sub, $this->pluginconfig); set_config('opt_deref', $config->opt_deref, $this->pluginconfig); set_config('preventpassindb', $config->preventpassindb, $this->pluginconfig); @@ -2272,4 +2289,24 @@ class auth_plugin_ldap extends auth_plugin_base { return false; } + /** + * Check if a user is suspended. This function is intended to be used after calling + * get_userinfo_asobj. This is needed because LDAP doesn't have a notion of disabled + * users, however things like MS Active Directory support it and expose information + * through a field. + * + * @param object $user the user object returned by get_userinfo_asobj + * @return boolean + */ + protected function is_user_suspended($user) { + if (!$this->config->suspended_attribute || !isset($user->suspended)) { + return false; + } + if ($this->config->suspended_attribute == 'useraccountcontrol' && $this->config->user_type == 'ad') { + return (bool)($user->suspended & AUTH_AD_ACCOUNTDISABLE); + } + + return (bool)$user->suspended; + } + } // End of the class diff --git a/auth/ldap/config.html b/auth/ldap/config.html index 7c0593773d0..3afd2f03ac7 100644 --- a/auth/ldap/config.html +++ b/auth/ldap/config.html @@ -22,6 +22,12 @@ if (!isset($config->user_type)) { if (!isset($config->user_attribute)) { $config->user_attribute = ''; } +if (!isset($config->suspended_attribute)) { + $config->suspended_attribute = ''; +} +if (!isset($config->sync_suspended)) { + $config->sync_suspended = ''; +} if (!isset($config->search_sub)) { $config->search_sub = ''; } @@ -305,6 +311,18 @@ if (!ldap_paged_results_supported($config->ldap_version)) { + + + + + + + error_text($err['suspended_attribute']); } ?> + + + + + @@ -534,6 +552,17 @@ if (!ldap_paged_results_supported($config->ldap_version)) { + + + + + + sync_suspended, false); ?> + + + + +

diff --git a/auth/ldap/lang/en/auth_ldap.php b/auth/ldap/lang/en/auth_ldap.php index 6812abee565..349dd13d81c 100644 --- a/auth/ldap/lang/en/auth_ldap.php +++ b/auth/ldap/lang/en/auth_ldap.php @@ -87,6 +87,8 @@ $string['auth_ldap_unsupportedusertype'] = 'auth: ldap user_create() does not su $string['auth_ldap_update_userinfo'] = 'Update user information (firstname, lastname, address..) from LDAP to Moodle. Specify "Data mapping" settings as you need.'; $string['auth_ldap_user_attribute'] = 'Optional: Overrides the attribute used to name/search users. Usually \'cn\'.'; $string['auth_ldap_user_attribute_key'] = 'User attribute'; +$string['auth_ldap_suspended_attribute'] = 'Optional: When provided this attribute will be used to enable/suspend the locally created user account.'; +$string['auth_ldap_suspended_attribute_key'] = 'Suspended attribute'; $string['auth_ldap_user_exists'] = 'LDAP username already exists.'; $string['auth_ldap_user_settings'] = 'User lookup settings'; $string['auth_ldap_user_type'] = 'Select how users are stored in LDAP. This setting also specifies how login expiration, grace logins and user creation will work.'; diff --git a/lang/en/auth.php b/lang/en/auth.php index c7944d1b1ee..19eea47555b 100644 --- a/lang/en/auth.php +++ b/lang/en/auth.php @@ -49,6 +49,8 @@ $string['auth_remove_keep'] = 'Keep internal'; $string['auth_remove_suspend'] = 'Suspend internal'; $string['auth_remove_user'] = 'Specify what to do with internal user account during mass synchronization when user was removed from external source. Only suspended users are automatically revived if they reappear in ext source.'; $string['auth_remove_user_key'] = 'Removed ext user'; +$string['auth_sync_suspended'] = 'When enabled, the suspended attribute will be used to update the local user account\'s suspension status.'; +$string['auth_sync_suspended_key'] = 'Synchronize local user suspension status'; $string['auth_sync_script'] = 'User account syncronisation'; $string['auth_updatelocal'] = 'Update local'; $string['auth_updatelocal_expl'] = '

Update local: If enabled, the field will be updated (from external auth) every time the user logs in or there is a user synchronization. Fields set to update locally should be locked.

';