From: Arthur Schiwon Date: Tue, 8 Oct 2013 21:47:57 +0000 (+0200) Subject: Ldap Wizard: Login filter UI, detection of username attribute, composing of login... X-Git-Tag: v6.0.0beta2~46^2~18 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7c6a9c22562f03eefb6730fc53afeed360c0171e;p=nextcloud-server.git Ldap Wizard: Login filter UI, detection of username attribute, composing of login filter --- diff --git a/apps/user_ldap/ajax/wizard.php b/apps/user_ldap/ajax/wizard.php index 27359b908f6..7af879c99a5 100644 --- a/apps/user_ldap/ajax/wizard.php +++ b/apps/user_ldap/ajax/wizard.php @@ -48,7 +48,9 @@ switch($action) { case 'guessBaseDN': case 'determineObjectClasses': case 'determineGroups': + case 'determineAttributes': case 'getUserListFilter': + case 'getUserLoginFilter': case 'countUsers': try { $result = $wizard->$action(); diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index d3c7aeea4f7..ba000c200f5 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -210,6 +210,8 @@ var LdapWizard = { composeFilter: function(type) { if(type == 'user') { action = 'getUserListFilter'; + } else if(type == 'login') { + action = 'getUserLoginFilter'; } param = 'action='+action+ @@ -241,6 +243,32 @@ var LdapWizard = { ); }, + findAttributes: function() { + param = 'action=determineAttributes'+ + '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); + + LdapWizard.ajax(param, + function(result) { + $('#ldap_loginfilter_attributes').find('option').remove(); + for (i in result.options['ldap_loginfilter_attributes']) { + //FIXME: move HTML into template + attr = result.options['ldap_loginfilter_attributes'][i]; + $('#ldap_loginfilter_attributes').append( + ""); + } + LdapWizard.applyChanges(result); + $('#ldap_loginfilter_attributes').multiselect('refresh'); + $('#ldap_loginfilter_attributes').multiselect('enable'); + }, + function (result) { + //deactivate if no attributes found + $('#ldap_loginfilter_attributes').multiselect( + {noneSelectedText : 'No attributes found'}); + $('#ldap_loginfilter_attributes').multiselect('disable'); + } + ); + }, + findAvailableGroups: function() { param = 'action=determineGroups'+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); @@ -297,6 +325,10 @@ var LdapWizard = { } }, + initLoginFilter: function() { + LdapWizard.findAttributes(); + }, + initMultiSelect: function(object, id, caption) { object.multiselect({ header: false, @@ -318,6 +350,8 @@ var LdapWizard = { onTabChange: function(event, ui) { if(ui.newTab[0].id === '#ldapWizard2') { LdapWizard.initUserFilter(); + } else if(ui.newTab[0].id === '#ldapWizard3') { + LdapWizard.initLoginFilter(); } }, @@ -333,6 +367,11 @@ var LdapWizard = { if(triggerObj.id == 'ldap_userlist_filter') { LdapWizard.countUsers(); } + + if(triggerObj.id == 'ldap_loginfilter_username' + || triggerObj.id == 'ldap_loginfilter_email') { + LdapWizard.composeFilter('login'); + } }, save: function(inputObj) { @@ -340,7 +379,13 @@ var LdapWizard = { delete LdapWizard.saveBlacklist[inputObj.id]; return; } - LdapWizard._save(inputObj, $(inputObj).val()); + if($(inputObj).is('input[type=checkbox]') + && !$(inputObj).is(':checked')) { + val = 0; + } else { + val = $(inputObj).val(); + } + LdapWizard._save(inputObj, val); }, saveMultiSelect: function(originalObj, resultObj) { @@ -352,7 +397,10 @@ var LdapWizard = { if(originalObj == 'ldap_userfilter_objectclass' || originalObj == 'ldap_userfilter_groups') { LdapWizard.composeFilter('user'); + } else if(originalObj == 'ldap_loginfilter_attributes') { + LdapWizard.composeFilter('login'); } + }, _save: function(object, value) { @@ -410,6 +458,9 @@ $(document).ready(function() { LdapWizard.initMultiSelect($('#ldap_userfilter_objectclass'), 'ldap_userfilter_objectclass', t('user_ldap', 'Select object classes')); + LdapWizard.initMultiSelect($('#ldap_loginfilter_attributes'), + 'ldap_loginfilter_attributes', + t('user_ldap', 'Select attributes')); $('.lwautosave').change(function() { LdapWizard.save(this); }); $('#toggleRawUserFilter').click(LdapWizard.toggleRawUserFilter); LdapConfiguration.refreshConfig(); diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index 70c55458895..205f9b517a2 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -51,6 +51,9 @@ class Configuration { 'ldapGroupDisplayName' => null, 'ldapGroupMemberAssocAttr' => null, 'ldapLoginFilter' => null, + 'ldapLoginFilterEmail' => null, + 'ldapLoginFilterUsername' => null, + 'ldapLoginFilterAttributes' => null, 'ldapQuotaAttribute' => null, 'ldapQuotaDefault' => null, 'ldapEmailAttribute' => null, @@ -126,6 +129,7 @@ class Configuration { case 'ldapAttributesForGroupSearch': case 'ldapUserFilterObjectclass': case 'ldapUserFilterGroups': + case 'ldapLoginFilterAttributes': $setMethod = 'setMultiLine'; default: $this->$setMethod($key, $val); @@ -154,6 +158,7 @@ class Configuration { case 'ldapAttributesForGroupSearch': case 'ldapUserFilterObjectclass': case 'ldapUserFilterGroups': + case 'ldapLoginFilterAttributes': $readMethod = 'getMultiLine'; break; case 'ldapIgnoreNamingRules': @@ -194,6 +199,7 @@ class Configuration { case 'ldapAttributesForGroupSearch': case 'ldapUserFilterObjectclass': case 'ldapUserFilterGroups': + case 'ldapLoginFilterAttributes': if(is_array($value)) { $value = implode("\n", $value); } @@ -286,6 +292,9 @@ class Configuration { 'ldap_userfilter_objectclass' => '', 'ldap_userfilter_groups' => '', 'ldap_login_filter' => 'uid=%uid', + 'ldap_loginfilter_email' => 0, + 'ldap_loginfilter_username' => 1, + 'ldap_loginfilter_attributes' => '', 'ldap_group_filter' => 'objectClass=posixGroup', 'ldap_display_name' => 'cn', 'ldap_group_display_name' => 'cn', @@ -329,6 +338,9 @@ class Configuration { 'ldap_userfilter_groups' => 'ldapUserFilterGroups', 'ldap_userlist_filter' => 'ldapUserFilter', 'ldap_login_filter' => 'ldapLoginFilter', + 'ldap_loginfilter_email' => 'ldapLoginFilterEmail', + 'ldap_loginfilter_username' => 'ldapLoginFilterUsername', + 'ldap_loginfilter_attributes' => 'ldapLoginFilterAttributes', 'ldap_group_filter' => 'ldapGroupFilter', 'ldap_display_name' => 'ldapUserDisplayName', 'ldap_group_display_name' => 'ldapGroupDisplayName', diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index e85c7460748..3cbca172515 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -30,13 +30,13 @@ class Wizard extends LDAPUtility { protected $result; protected $resultCache = array(); - const LRESULT_PROCESSED_OK = 0; - const LRESULT_PROCESSED_INVALID = 1; - const LRESULT_PROCESSED_SKIP = 2; + const LRESULT_PROCESSED_OK = 2; + const LRESULT_PROCESSED_INVALID = 3; + const LRESULT_PROCESSED_SKIP = 4; - const LFILTER_LOGIN = 0; - const LFILTER_USER_LIST = 1; - const LFILTER_GROUP_LIST = 2; + const LFILTER_LOGIN = 2; + const LFILTER_USER_LIST = 3; + const LFILTER_GROUP_LIST = 4; /** * @brief Constructor @@ -87,6 +87,67 @@ class Wizard extends LDAPUtility { return $this->result; } + public function determineAttributes() { + if(!$this->checkRequirements(array('ldapHost', + 'ldapPort', + 'ldapAgentName', + 'ldapAgentPassword', + 'ldapBase', + 'ldapUserFilter', + ))) { + return false; + } + + $attributes = $this->getUserAttributes(); + + natcasesort($attributes); + $attributes = array_values($attributes); + + $this->result->addOptions('ldap_loginfilter_attributes', $attributes); + + $selected = $this->configuration->ldapLoginFilterAttributes; + if(is_array($selected) && !empty($selected)) { + $this->result->addChange('ldap_loginfilter_attributes', $selected); + } + + return $this->result; + } + + /** + * @brief detects the available LDAP attributes + * @returns the instance's WizardResult instance + */ + private function getUserAttributes() { + if(!$this->checkRequirements(array('ldapHost', + 'ldapPort', + 'ldapAgentName', + 'ldapAgentPassword', + 'ldapBase', + 'ldapUserFilter', + ))) { + return false; + } + $cr = $this->getConnection(); + if(!$cr) { + throw new \Excpetion('Could not connect to LDAP'); + } + + $base = $this->configuration->ldapBase[0]; + $filter = $this->configuration->ldapUserFilter; + $rr = $this->ldap->search($cr, $base, $filter, array(), 1, 1); + if(!$this->ldap->isResource($rr)) { + return false; + } + $er = $this->ldap->firstEntry($cr, $rr); + $attributes = $this->ldap->getAttributes($cr, $er); + $pureAttributes = array(); + for($i = 0; $i < $attributes['count']; $i++) { + $pureAttributes[] = $attributes[$i]; + } + + return $pureAttributes; + } + /** * @brief detects the available LDAP groups * @returns the instance's WizardResult instance @@ -167,6 +228,25 @@ class Wizard extends LDAPUtility { return $this->result; } + public function getUserLoginFilter() { + if(!$this->checkRequirements(array('ldapHost', + 'ldapPort', + 'ldapAgentName', + 'ldapAgentPassword', + 'ldapBase', + 'ldapUserFilter', + ))) { + return false; + } + $filter = $this->composeLdapFilter(self::LFILTER_LOGIN); + if(!$filter) { + throw new \Exception('Cannot create filter'); + } + + $this->applyFind('ldap_login_filter', $filter); + return $this->result; + } + /** * Tries to determine the port, requires given Host, User DN and Password * @returns mixed WizardResult on success, false otherwise @@ -361,10 +441,8 @@ class Wizard extends LDAPUtility { switch ($filterType) { case self::LFILTER_USER_LIST: $objcs = $this->configuration->ldapUserFilterObjectclass; - \OCP\Util::writeLog('user_ldap', 'Wiz: '.print_r($objcs, true), \OCP\Util::DEBUG); //glue objectclasses if(is_array($objcs) && count($objcs) > 0) { - \OCP\Util::writeLog('user_ldap', 'Wiz: Processing objectclasses', \OCP\Util::DEBUG); $filter .= '(|'; foreach($objcs as $objc) { $filter .= '(objectclass=' . $objc . ')'; @@ -372,13 +450,10 @@ class Wizard extends LDAPUtility { $filter .= ')'; $parts++; } - \OCP\Util::writeLog('user_ldap', 'Wiz: Intermediate filter '.$filter, \OCP\Util::DEBUG); //glue group memberships if($this->configuration->hasMemberOfFilterSupport) { $cns = $this->configuration->ldapUserFilterGroups; - \OCP\Util::writeLog('user_ldap', 'Wiz: '.print_r($cns, true), \OCP\Util::DEBUG); if(is_array($cns) && count($cns) > 0) { - \OCP\Util::writeLog('user_ldap', 'Wiz: Processing groups', \OCP\Util::DEBUG); $filter .= '(|'; $cr = $this->getConnection(); if(!$cr) { @@ -397,15 +472,70 @@ class Wizard extends LDAPUtility { $filter .= ')'; } $parts++; - \OCP\Util::writeLog('user_ldap', 'Wiz: Intermediate filter '.$filter, \OCP\Util::DEBUG); } //wrap parts in AND condition if($parts > 1) { $filter = '(&' . $filter . ')'; } if(empty($filter)) { - $filter = 'objectclass=*'; + $filter = '(objectclass=*)'; + } + break; + + case self::LFILTER_LOGIN: + $ulf = $this->configuration->ldapUserFilter; + $loginpart = '=%uid'; + $filterUsername = ''; + $userAttributes = $this->getUserAttributes(); + $userAttributes = array_change_key_case(array_flip($userAttributes)); + $parts = 0; + + $x = $this->configuration->ldapLoginFilterUsername; + if($this->configuration->ldapLoginFilterUsername === '1') { + $attr = ''; + if(isset($userAttributes['uid'])) { + $attr = 'uid'; + } else if(isset($userAttributes['samaccountname'])) { + $attr = 'samaccountname'; + } else if(isset($userAttributes['cn'])) { + //fallback + $attr = 'cn'; + } + if(!empty($attr)) { + $filterUsername = '(' . $attr . $loginpart . ')'; + $parts++; + } } + + $filterEmail = ''; + if($this->configuration->ldapLoginFilterEmail === '1') { + $filterEmail = '(|(mailPrimaryAddress=%uid)(mail=%uid))'; + $parts++; + } + + $filterAttributes = ''; + $attrsToFilter = $this->configuration->ldapLoginFilterAttributes; + if(is_array($attrsToFilter) && count($attrsToFilter) > 0) { + $filterAttributes = '(|'; + foreach($attrsToFilter as $attribute) { + $filterAttributes .= '(' . $attribute . $loginpart . ')'; + } + $filterAttributes .= ')'; + $parts++; + } + + $filterLogin = ''; + if($parts > 1) { + $filterLogin = '(|'; + } + $filterLogin .= $filterUsername; + $filterLogin .= $filterEmail; + $filterLogin .= $filterAttributes; + if($parts > 1) { + $filterLogin .= ')'; + } + + $filter = '(&'.$ulf.$filterLogin.')'; break; } diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index ebba1dbd3a6..299e98fe090 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -57,6 +57,11 @@ $wizard2->assign('wizardControls', $wControls); $wizardHtml .= $wizard2->fetchPage(); $toc['#ldapWizard2'] = 'User Filter'; +$wizard3 = new OCP\Template('user_ldap', 'part.wizard-loginfilter'); +$wizard3->assign('wizardControls', $wControls); +$wizardHtml .= $wizard3->fetchPage(); +$toc['#ldapWizard3'] = 'Login Filter'; + $tmpl->assign('tabs', $wizardHtml); $tmpl->assign('toc', $toc);