From: Arthur Schiwon Date: Wed, 9 Oct 2013 20:00:36 +0000 (+0200) Subject: Ldap Wizard: Group Filter configuration X-Git-Tag: v6.0.0beta2~46^2~17 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b2ccb712e26de6922e09d7500a01041814e6bd74;p=nextcloud-server.git Ldap Wizard: Group Filter configuration --- diff --git a/apps/user_ldap/ajax/wizard.php b/apps/user_ldap/ajax/wizard.php index 7af879c99a5..ebeedaee959 100644 --- a/apps/user_ldap/ajax/wizard.php +++ b/apps/user_ldap/ajax/wizard.php @@ -46,12 +46,16 @@ $wizard = new \OCA\user_ldap\lib\Wizard($configuration, $ldapWrapper); switch($action) { case 'guessPortAndTLS': case 'guessBaseDN': - case 'determineObjectClasses': - case 'determineGroups': + case 'determineUserObjectClasses': + case 'determineGroupObjectClasses': + case 'determineGroupsForUsers': + case 'determineGroupsForGroups': case 'determineAttributes': case 'getUserListFilter': case 'getUserLoginFilter': + case 'getGroupFilter': case 'countUsers': + case 'countGroups': try { $result = $wizard->$action(); if($result !== false) { diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index ba000c200f5..049df9b8b17 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -212,6 +212,8 @@ var LdapWizard = { action = 'getUserListFilter'; } else if(type == 'login') { action = 'getUserLoginFilter'; + } else if(type == 'group') { + action = 'getGroupFilter'; } param = 'action='+action+ @@ -220,7 +222,11 @@ var LdapWizard = { LdapWizard.ajax(param, function(result) { LdapWizard.applyChanges(result); - LdapWizard.countUsers(); + if(type == 'user') { + LdapWizard.countUsers(); + } else if(type == 'group') { + LdapWizard.countGroups(); + } }, function (result) { // error handling @@ -228,14 +234,13 @@ var LdapWizard = { ); }, - countUsers: function() { - param = 'action=countUsers'+ + _countThings: function(method) { + param = 'action='+method+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); LdapWizard.ajax(param, function(result) { LdapWizard.applyChanges(result); -// alert(result.changes['ldap_user_count']); }, function (result) { // error handling @@ -243,6 +248,14 @@ var LdapWizard = { ); }, + countGroups: function() { + LdapWizard._countThings('countGroups'); + }, + + countUsers: function() { + LdapWizard._countThings('countUsers'); + }, + findAttributes: function() { param = 'action=determineAttributes'+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); @@ -269,42 +282,48 @@ var LdapWizard = { ); }, - findAvailableGroups: function() { - param = 'action=determineGroups'+ + findAvailableGroups: function(multisel, type) { + if(type != 'Users' && type != 'Groups') { + return false; + } + param = 'action=determineGroupsFor'+type+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); LdapWizard.ajax(param, function(result) { - $('#ldap_userfilter_groups').find('option').remove(); - for (i in result.options['ldap_userfilter_groups']) { + $('#'+multisel).find('option').remove(); + for (i in result.options[multisel]) { //FIXME: move HTML into template - objc = result.options['ldap_userfilter_groups'][i]; - $('#ldap_userfilter_groups').append(""); + objc = result.options[multisel][i]; + $('#'+multisel).append(""); } LdapWizard.applyChanges(result); - $('#ldap_userfilter_groups').multiselect('refresh'); - $('#ldap_userfilter_groups').multiselect('enable'); + $('#'+multisel).multiselect('refresh'); + $('#'+multisel).multiselect('enable'); }, function (result) { - $('#ldap_userfilter_groups').multiselect('disable'); + $('#'+multisel).multiselect('disable'); } ); }, - findObjectClasses: function() { - param = 'action=determineObjectClasses'+ + findObjectClasses: function(multisel, type) { + if(type != 'User' && type != 'Group') { + return false; + } + param = 'action=determine'+type+'ObjectClasses'+ '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val(); LdapWizard.ajax(param, function(result) { - $('#ldap_userfilter_objectclass').find('option').remove(); - for (i in result.options['ldap_userfilter_objectclass']) { + $('#'+multisel).find('option').remove(); + for (i in result.options[multisel]) { //FIXME: move HTML into template - objc = result.options['ldap_userfilter_objectclass'][i]; - $('#ldap_userfilter_objectclass').append(""); + objc = result.options[multisel][i]; + $('#'+multisel).append(""); } LdapWizard.applyChanges(result); - $('#ldap_userfilter_objectclass').multiselect('refresh'); + $('#'+multisel).multiselect('refresh'); }, function (result) { //TODO: error handling @@ -325,6 +344,12 @@ var LdapWizard = { } }, + initGroupFilter: function() { + LdapWizard.findObjectClasses('ldap_groupfilter_objectclass', 'Group'); + LdapWizard.findAvailableGroups('ldap_groupfilter_groups', 'Groups'); + LdapWizard.countGroups(); + }, + initLoginFilter: function() { LdapWizard.findAttributes(); }, @@ -342,8 +367,8 @@ var LdapWizard = { }, initUserFilter: function() { - LdapWizard.findObjectClasses(); - LdapWizard.findAvailableGroups(); + LdapWizard.findObjectClasses('ldap_userfilter_objectclass', 'User'); + LdapWizard.findAvailableGroups('ldap_userfilter_groups', 'Users'); LdapWizard.countUsers(); }, @@ -352,6 +377,8 @@ var LdapWizard = { LdapWizard.initUserFilter(); } else if(ui.newTab[0].id === '#ldapWizard3') { LdapWizard.initLoginFilter(); + } else if(ui.newTab[0].id === '#ldapWizard4') { + LdapWizard.initGroupFilter(); } }, @@ -366,6 +393,8 @@ var LdapWizard = { if(triggerObj.id == 'ldap_userlist_filter') { LdapWizard.countUsers(); + } else if(triggerObj.id == 'ldap_group_filter') { + LdapWizard.countGroups(); } if(triggerObj.id == 'ldap_loginfilter_username' @@ -399,8 +428,10 @@ var LdapWizard = { LdapWizard.composeFilter('user'); } else if(originalObj == 'ldap_loginfilter_attributes') { LdapWizard.composeFilter('login'); + } else if(originalObj == 'ldap_groupfilter_objectclass' + || originalObj == 'ldap_groupfilter_groups') { + LdapWizard.composeFilter('group'); } - }, _save: function(object, value) { @@ -428,21 +459,37 @@ var LdapWizard = { LdapWizard.checkInfoShown = true; }, - toggleRawUserFilter: function() { - if($('#rawUserFilterContainer').hasClass('invisible')) { - $('#rawUserFilterContainer').removeClass('invisible'); - $('#ldap_userfilter_objectclass').multiselect('disable'); - if($('#ldap_userfilter_groups').multiselect().attr('disabled') == 'disabled') { - userFilterGroupSelectState = 'disable'; + toggleRawFilter: function(container, moc, mg, stateVar) { + if($(container).hasClass('invisible')) { + $(container).removeClass('invisible'); + $(moc).multiselect('disable'); + if($(mg).multiselect().attr('disabled') == 'disabled') { + LdapWizard[stateVar] = 'disable'; } else { - userFilterGroupSelectState = 'enable'; + LdapWizard[stateVar] = 'enable'; } - $('#ldap_userfilter_groups').multiselect('disable'); + $(mg).multiselect('disable'); } else { - $('#rawUserFilterContainer').addClass('invisible'); - $('#ldap_userfilter_group').multiselect(userFilterGroupSelectState); - $('#ldap_userfilter_objectclass').multiselect('enable'); + $(container).addClass('invisible'); + $(mg).multiselect(LdapWizard[stateVar]); + $(moc).multiselect('enable'); } + }, + + toggleRawGroupFilter: function() { + LdapWizard.toggleRawFilter('#rawGroupFilterContainer', + '#ldap_groupfilter_objectclass', + '#ldap_groupfilter_groups', + 'groupFilterGroupSelectState' + ); + }, + + toggleRawUserFilter: function() { + LdapWizard.toggleRawFilter('#rawUserFilterContainer', + '#ldap_userfilter_objectclass', + '#ldap_userfilter_groups', + 'userFilterGroupSelectState' + ); } }; @@ -461,8 +508,15 @@ $(document).ready(function() { LdapWizard.initMultiSelect($('#ldap_loginfilter_attributes'), 'ldap_loginfilter_attributes', t('user_ldap', 'Select attributes')); + LdapWizard.initMultiSelect($('#ldap_groupfilter_groups'), + 'ldap_groupfilter_groups', + t('user_ldap', 'Select groups')); + LdapWizard.initMultiSelect($('#ldap_groupfilter_objectclass'), + 'ldap_groupfilter_objectclass', + t('user_ldap', 'Select object classes')); $('.lwautosave').change(function() { LdapWizard.save(this); }); $('#toggleRawUserFilter').click(LdapWizard.toggleRawUserFilter); + $('#toggleRawGroupFilter').click(LdapWizard.toggleRawGroupFilter); LdapConfiguration.refreshConfig(); $('#ldap_action_test_connection').click(function(event){ event.preventDefault(); diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index 205f9b517a2..14a14890bd1 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -48,6 +48,8 @@ class Configuration { 'ldapUserFilterGroups' => null, 'ldapUserFilter' => null, 'ldapGroupFilter' => null, + 'ldapGroupFilterObjectclass' => null, + 'ldapGroupFilterGroups' => null, 'ldapGroupDisplayName' => null, 'ldapGroupMemberAssocAttr' => null, 'ldapLoginFilter' => null, @@ -129,6 +131,8 @@ class Configuration { case 'ldapAttributesForGroupSearch': case 'ldapUserFilterObjectclass': case 'ldapUserFilterGroups': + case 'ldapGroupFilterObjectclass': + case 'ldapGroupFilterGroups': case 'ldapLoginFilterAttributes': $setMethod = 'setMultiLine'; default: @@ -158,6 +162,8 @@ class Configuration { case 'ldapAttributesForGroupSearch': case 'ldapUserFilterObjectclass': case 'ldapUserFilterGroups': + case 'ldapGroupFilterObjectclass': + case 'ldapGroupFilterGroups': case 'ldapLoginFilterAttributes': $readMethod = 'getMultiLine'; break; @@ -199,6 +205,8 @@ class Configuration { case 'ldapAttributesForGroupSearch': case 'ldapUserFilterObjectclass': case 'ldapUserFilterGroups': + case 'ldapGroupFilterObjectclass': + case 'ldapGroupFilterGroups': case 'ldapLoginFilterAttributes': if(is_array($value)) { $value = implode("\n", $value); @@ -296,6 +304,8 @@ class Configuration { 'ldap_loginfilter_username' => 1, 'ldap_loginfilter_attributes' => '', 'ldap_group_filter' => 'objectClass=posixGroup', + 'ldap_groupfilter_objectclass' => '', + 'ldap_groupfilter_groups' => '', 'ldap_display_name' => 'cn', 'ldap_group_display_name' => 'cn', 'ldap_tls' => 1, @@ -342,6 +352,8 @@ class Configuration { 'ldap_loginfilter_username' => 'ldapLoginFilterUsername', 'ldap_loginfilter_attributes' => 'ldapLoginFilterAttributes', 'ldap_group_filter' => 'ldapGroupFilter', + 'ldap_groupfilter_objectclass' => 'ldapGroupFilterObjectclass', + 'ldap_groupfilter_groups' => 'ldapGroupFilterGroups', 'ldap_display_name' => 'ldapUserDisplayName', 'ldap_group_display_name' => 'ldapGroupDisplayName', 'ldap_tls' => 'ldapTLS', diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index 3cbca172515..86cf8d75af6 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -58,6 +58,38 @@ class Wizard extends LDAPUtility { } } + public function countGroups() { + if(!$this->checkRequirements(array('ldapHost', + 'ldapPort', + 'ldapAgentName', + 'ldapAgentPassword', + 'ldapBase', + ))) { + return false; + } + + $base = $this->configuration->ldapBase[0]; + $filter = $this->configuration->ldapGroupFilter; + \OCP\Util::writeLog('user_ldap', 'Wiz: g filter '. print_r($filter, true), \OCP\Util::DEBUG); + if(empty($filter)) { + $this->result->addChange('ldap_group_count', 0); + return $this->result; + } + $cr = $this->getConnection(); + if(!$cr) { + throw new \Excpetion('Could not connect to LDAP'); + } + $rr = $this->ldap->search($cr, $base, $filter, array('dn')); + if(!$this->ldap->isResource($rr)) { + return false; + } + $entries = $this->ldap->countEntries($cr, $rr); + $entries = ($entries !== false) ? $entries : 0; + $this->result->addChange('ldap_group_count', $entries); + + return $this->result; + } + public function countUsers() { if(!$this->checkRequirements(array('ldapHost', 'ldapPort', @@ -152,7 +184,26 @@ class Wizard extends LDAPUtility { * @brief detects the available LDAP groups * @returns the instance's WizardResult instance */ - public function determineGroups() { + public function determineGroupsForGroups() { + return $this->determineGroups('ldap_groupfilter_groups', + 'ldapGroupFilterGroups', + false); + } + + /** + * @brief detects the available LDAP groups + * @returns the instance's WizardResult instance + */ + public function determineGroupsForUsers() { + return $this->determineGroups('ldap_userfilter_groups', + 'ldapUserFilterGroups'); + } + + /** + * @brief detects the available LDAP groups + * @returns the instance's WizardResult instance + */ + private function determineGroups($dbkey, $confkey, $testMemberOf = true) { if(!$this->checkRequirements(array('ldapHost', 'ldapPort', 'ldapAgentName', @@ -167,15 +218,13 @@ class Wizard extends LDAPUtility { } $obclasses = array('posixGroup', 'group', '*'); - $this->determineFeature($obclasses, - 'cn', - 'ldap_userfilter_groups', - 'ldapUserFilterGroups'); + $this->determineFeature($obclasses, 'cn', $dbkey, $confkey); - $this->configuration->hasMemberOfFilterSupport = $this->testMemberOf(); - $filter = $this->composeLdapFilter(self::LFILTER_USER_LIST); - if(!$this->configuration->hasMemberOfFilterSupport) { - throw new \Exception('memberOf is not supported by the server'); + if($testMemberOf) { + $this->configuration->hasMemberOfFilterSupport = $this->testMemberOf(); + if(!$this->configuration->hasMemberOfFilterSupport) { + throw new \Exception('memberOf is not supported by the server'); + } } return $this->result; @@ -185,7 +234,35 @@ class Wizard extends LDAPUtility { * @brief detects the available object classes * @returns the instance's WizardResult instance */ - public function determineObjectClasses() { + public function determineGroupObjectClasses() { + if(!$this->checkRequirements(array('ldapHost', + 'ldapPort', + 'ldapAgentName', + 'ldapAgentPassword', + 'ldapBase', + ))) { + return false; + } + $cr = $this->getConnection(); + if(!$cr) { + throw new \Excpetion('Could not connect to LDAP'); + } + + $obclasses = array('group', 'posixGroup', '*'); + $this->determineFeature($obclasses, + 'objectclass', + 'ldap_groupfilter_objectclass', + 'ldapGroupFilterObjectclass', + false); + + return $this->result; + } + + /** + * @brief detects the available object classes + * @returns the instance's WizardResult instance + */ + public function determineUserObjectClasses() { if(!$this->checkRequirements(array('ldapHost', 'ldapPort', 'ldapAgentName', @@ -201,12 +278,30 @@ class Wizard extends LDAPUtility { $obclasses = array('inetOrgPerson', 'person', 'organizationalPerson', 'user', 'posixAccount', '*'); + $filter = $this->configuration->ldapUserFilter; + //if filter is empty, it is probably the first time the wizard is called + //then, apply suggestions. $this->determineFeature($obclasses, 'objectclass', 'ldap_userfilter_objectclass', 'ldapUserFilterObjectclass', - true); + empty($filter)); + + return $this->result; + } + + public function getGroupFilter() { + if(!$this->checkRequirements(array('ldapHost', + 'ldapPort', + 'ldapAgentName', + 'ldapAgentPassword', + 'ldapBase', + ))) { + return false; + } + $filter = $this->composeLdapFilter(self::LFILTER_GROUP_LIST); + $this->applyFind('ldap_group_filter', $filter); return $this->result; } @@ -482,6 +577,34 @@ class Wizard extends LDAPUtility { } break; + case self::LFILTER_GROUP_LIST: + $objcs = $this->configuration->ldapGroupFilterObjectclass; + //glue objectclasses + if(is_array($objcs) && count($objcs) > 0) { + $filter .= '(|'; + foreach($objcs as $objc) { + $filter .= '(objectclass=' . $objc . ')'; + } + $filter .= ')'; + $parts++; + } + //glue group memberships + $cns = $this->configuration->ldapGroupFilterGroups; + if(is_array($cns) && count($cns) > 0) { + $filter .= '(|'; + $base = $this->configuration->ldapBase[0]; + foreach($cns as $cn) { + $filter .= '(cn=' . $cn . ')'; + } + $filter .= ')'; + } + $parts++; + //wrap parts in AND condition + if($parts > 1) { + $filter = '(&' . $filter . ')'; + } + break; + case self::LFILTER_LOGIN: $ulf = $this->configuration->ldapUserFilter; $loginpart = '=%uid'; @@ -541,7 +664,7 @@ class Wizard extends LDAPUtility { \OCP\Util::writeLog('user_ldap', 'Wiz: Final filter '.$filter, \OCP\Util::DEBUG); - return empty($filter) ? false : $filter; + return $filter; } /** @@ -730,7 +853,8 @@ class Wizard extends LDAPUtility { } else if($po && !empty($maxEntryObjC)) { //pre-select objectclass with most result entries $maxEntryObjC = str_replace($p, '', $maxEntryObjC); - $this->result->addChange($dbkey, $maxEntryObjC); + $this->applyFind($dbkey, $maxEntryObjC); +// $this->result->addChange($dbkey, $maxEntryObjC); } return $availableFeatures; diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index 299e98fe090..77bd26a52d9 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -45,22 +45,22 @@ $wControls = $wControls->fetchPage(); $sControls = new OCP\Template('user_ldap', 'part.settingcontrols'); $sControls = $sControls->fetchPage(); -$wizard1 = new OCP\Template('user_ldap', 'part.wizard-server'); -$wizard1->assign('serverConfigurationPrefixes', $prefixes); -$wizard1->assign('serverConfigurationHosts', $hosts); -$wizard1->assign('wizardControls', $wControls); -$wizardHtml .= $wizard1->fetchPage(); -$toc['#ldapWizard1'] = 'Server'; +$wizTabs = array(); +$wizTabs[] = array('tpl' => 'part.wizard-server', 'cap' => 'Server'); +$wizTabs[] = array('tpl' => 'part.wizard-userfilter', 'cap' => 'User Filter'); +$wizTabs[] = array('tpl' => 'part.wizard-loginfilter', 'cap' => 'Login Filter'); +$wizTabs[] = array('tpl' => 'part.wizard-groupfilter', 'cap' => 'Group Filter'); -$wizard2 = new OCP\Template('user_ldap', 'part.wizard-userfilter'); -$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'; +for($i = 0; $i < count($wizTabs); $i++) { + $tab = new OCP\Template('user_ldap', $wizTabs[$i]['tpl']); + if($i === 0) { + $tab->assign('serverConfigurationPrefixes', $prefixes); + $tab->assign('serverConfigurationHosts', $hosts); + } + $tab->assign('wizardControls', $wControls); + $wizardHtml .= $tab->fetchPage(); + $toc['#ldapWizard'.($i+1)] = $wizTabs[$i]['cap']; +} $tmpl->assign('tabs', $wizardHtml); $tmpl->assign('toc', $toc);