summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/user_ldap/ajax/getNewServerConfigPrefix.php15
-rw-r--r--apps/user_ldap/ajax/wizard.php23
-rw-r--r--apps/user_ldap/appinfo/version2
-rw-r--r--apps/user_ldap/css/settings.css62
-rw-r--r--apps/user_ldap/img/copy.pngbin0 -> 346 bytes
-rw-r--r--apps/user_ldap/img/copy.svg120
-rw-r--r--apps/user_ldap/js/experiencedAdmin.js92
-rw-r--r--apps/user_ldap/js/ldapFilter.js193
-rw-r--r--apps/user_ldap/js/settings.js1205
-rw-r--r--apps/user_ldap/js/wizard/configModel.js606
-rw-r--r--apps/user_ldap/js/wizard/controller.js56
-rw-r--r--apps/user_ldap/js/wizard/view.js433
-rw-r--r--apps/user_ldap/js/wizard/wizard.js80
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorAvailableAttributes.js59
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorBaseDN.js52
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorClearGroupMappings.js30
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorClearUserMappings.js30
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorEmailAttribute.js38
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorFeatureAbstract.js52
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorFilterGroup.js31
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorFilterLogin.js32
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorFilterUser.js31
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorGeneric.js117
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorGroupCount.js27
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorGroupObjectClasses.js29
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorGroupsForGroups.js29
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorGroupsForUsers.js29
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorPort.js44
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorQueue.js89
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorSimpleRequestAbstract.js44
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorTestAbstract.js63
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorTestBaseDN.js29
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorTestConfiguration.js31
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorTestLoginName.js30
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorUserCount.js26
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorUserDisplayNameAttribute.js39
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorUserGroupAssociation.js40
-rw-r--r--apps/user_ldap/js/wizard/wizardDetectorUserObjectClasses.js29
-rw-r--r--apps/user_ldap/js/wizard/wizardFilterOnType.js76
-rw-r--r--apps/user_ldap/js/wizard/wizardFilterOnTypeFactory.js27
-rw-r--r--apps/user_ldap/js/wizard/wizardObject.js60
-rw-r--r--apps/user_ldap/js/wizard/wizardTabAbstractFilter.js373
-rw-r--r--apps/user_ldap/js/wizard/wizardTabAdvanced.js330
-rw-r--r--apps/user_ldap/js/wizard/wizardTabElementary.js346
-rw-r--r--apps/user_ldap/js/wizard/wizardTabExpert.js130
-rw-r--r--apps/user_ldap/js/wizard/wizardTabGeneric.js547
-rw-r--r--apps/user_ldap/js/wizard/wizardTabGroupFilter.js124
-rw-r--r--apps/user_ldap/js/wizard/wizardTabLoginFilter.js235
-rw-r--r--apps/user_ldap/js/wizard/wizardTabUserFilter.js136
-rw-r--r--apps/user_ldap/lib/access.php27
-rw-r--r--apps/user_ldap/lib/configuration.php5
-rw-r--r--apps/user_ldap/lib/wizard.php143
-rw-r--r--apps/user_ldap/settings.php55
-rw-r--r--apps/user_ldap/templates/part.settingcontrols.php1
-rw-r--r--apps/user_ldap/templates/part.wizard-groupfilter.php42
-rw-r--r--apps/user_ldap/templates/part.wizard-loginfilter.php40
-rw-r--r--apps/user_ldap/templates/part.wizard-server.php31
-rw-r--r--apps/user_ldap/templates/part.wizard-userfilter.php53
-rw-r--r--apps/user_ldap/templates/settings.php3
-rw-r--r--apps/user_ldap/templates/wizard-container.php3
-rw-r--r--apps/user_ldap/user_ldap.php6
61 files changed, 5110 insertions, 1620 deletions
diff --git a/apps/user_ldap/ajax/getNewServerConfigPrefix.php b/apps/user_ldap/ajax/getNewServerConfigPrefix.php
index 7d1434a8fb4..d0135917886 100644
--- a/apps/user_ldap/ajax/getNewServerConfigPrefix.php
+++ b/apps/user_ldap/ajax/getNewServerConfigPrefix.php
@@ -32,4 +32,17 @@ sort($serverConnections);
$lk = array_pop($serverConnections);
$ln = intval(str_replace('s', '', $lk));
$nk = 's'.str_pad($ln+1, 2, '0', STR_PAD_LEFT);
-OCP\JSON::success(array('configPrefix' => $nk));
+
+$resultData = array('configPrefix' => $nk);
+
+if(isset($_POST['copyConfig'])) {
+ $originalConfig = new \OCA\user_ldap\lib\Configuration($_POST['copyConfig']);
+ $newConfig = new \OCA\user_ldap\lib\Configuration($nk, false);
+ $newConfig->setConfiguration($originalConfig->getConfiguration());
+ $newConfig->saveConfiguration();
+} else {
+ $configuration = new \OCA\user_ldap\lib\Configuration($nk, false);
+ $resultData['defaults'] = $configuration->getDefaults();
+}
+
+OCP\JSON::success($resultData);
diff --git a/apps/user_ldap/ajax/wizard.php b/apps/user_ldap/ajax/wizard.php
index ab521b5bf0e..267b9568a28 100644
--- a/apps/user_ldap/ajax/wizard.php
+++ b/apps/user_ldap/ajax/wizard.php
@@ -72,13 +72,11 @@ switch($action) {
case 'determineGroupsForGroups':
case 'determineAttributes':
case 'getUserListFilter':
- case 'getLoginFilterMode':
case 'getUserLoginFilter':
- case 'getUserFilterMode':
case 'getGroupFilter':
- case 'getGroupFilterMode':
case 'countUsers':
case 'countGroups':
+ case 'countInBaseDN':
try {
$result = $wizard->$action();
if($result !== false) {
@@ -93,6 +91,23 @@ switch($action) {
exit;
break;
+ case 'testLoginName': {
+ try {
+ $loginName = $_POST['ldap_test_loginname'];
+ $result = $wizard->$action($loginName);
+ if($result !== false) {
+ OCP\JSON::success($result->getResultArray());
+ exit;
+ }
+ } catch (\Exception $e) {
+ \OCP\JSON::error(array('message' => $e->getMessage()));
+ exit;
+ }
+ \OCP\JSON::error();
+ exit;
+ break;
+ }
+
case 'save':
$key = isset($_POST['cfgkey']) ? $_POST['cfgkey'] : false;
$val = isset($_POST['cfgval']) ? $_POST['cfgval'] : null;
@@ -115,6 +130,6 @@ switch($action) {
OCP\JSON::success();
break;
default:
- //TODO: return 4xx error
+ \OCP\JSON::error(array('message' => $l->t('Action does not exist')));
break;
}
diff --git a/apps/user_ldap/appinfo/version b/apps/user_ldap/appinfo/version
index 8f0916f768f..a918a2aa18d 100644
--- a/apps/user_ldap/appinfo/version
+++ b/apps/user_ldap/appinfo/version
@@ -1 +1 @@
-0.5.0
+0.6.0
diff --git a/apps/user_ldap/css/settings.css b/apps/user_ldap/css/settings.css
index 8f339451c64..b351f9ae2af 100644
--- a/apps/user_ldap/css/settings.css
+++ b/apps/user_ldap/css/settings.css
@@ -1,6 +1,6 @@
.table {
display: table;
- width: 60%;
+ width: 85%;
}
.tablerow {
@@ -21,10 +21,18 @@
margin-left: 3px;
}
+.ldapIconCopy {
+ background-image: url('../img/copy.svg');
+}
+
.invisible {
visibility: hidden;
}
+.forceHidden {
+ display: none !important;
+}
+
.ldapSettingsTabs {
float: right !important;
}
@@ -49,13 +57,16 @@
}
#ldapWizard1 .hostPortCombinator div span {
- width: 7%;
- display: table-cell;
+ width: 14.5%;
+ display: inline-block;
text-align: right;
}
#ldapWizard1 .host {
- width: 96.5% !important;
+ width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ border: 0;
}
.tableCellInput {
@@ -77,7 +88,7 @@
color: #FF3B3B;
}
-.wizSpinner {
+.ldapSpinner {
height: 15px;
margin: 5px;
}
@@ -104,10 +115,51 @@
width: auto;
}
+.ldapManyGroupsSupport span {
+ display: inline-block;
+ vertical-align: top;
+ height: 150px;
+}
+
+.ldapManyGroupsSupport span button {
+ margin-top: 35px;
+}
+
+.ldapManyGroupsSearch {
+ width: 425px !important;
+}
+
+.ldapGroupList {
+ height: 150px;
+ width: 200px;
+}
+
#ldap fieldset input, #ldap fieldset textarea {
width: 60%;
}
+#ldap fieldset textarea ~ button {
+ vertical-align: text-bottom;
+}
+
+input.ldapVerifyInput {
+ width: 150px !important;
+}
+
+.ldapInputColElement {
+ width: 35%;
+ display: inline-block;
+ padding-left: 10px;
+}
+
+.ldapToggle {
+ text-decoration: underline;
+}
+
+span.ldapInputColElement {
+ margin-top: 9px;
+}
+
#ldap fieldset p input[type=checkbox] {
vertical-align: bottom;
}
diff --git a/apps/user_ldap/img/copy.png b/apps/user_ldap/img/copy.png
new file mode 100644
index 00000000000..283d627a5a7
--- /dev/null
+++ b/apps/user_ldap/img/copy.png
Binary files differ
diff --git a/apps/user_ldap/img/copy.svg b/apps/user_ldap/img/copy.svg
new file mode 100644
index 00000000000..2e19d8066e3
--- /dev/null
+++ b/apps/user_ldap/img/copy.svg
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:ns1="http://sozi.baierouge.fr"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ id="svg1"
+ sodipodi:docname="copy.svg"
+ viewBox="0 0 60 60"
+ sodipodi:version="0.32"
+ _SVGFile__filename="oldscale/actions/copy.svg"
+ version="1.0"
+ y="0"
+ x="0"
+ inkscape:version="0.40"
+ sodipodi:docbase="/home/danny/work/flat/SVG/mono/scalable/actions"
+ >
+ <sodipodi:namedview
+ id="base"
+ bordercolor="#666666"
+ inkscape:pageshadow="2"
+ inkscape:window-y="0"
+ pagecolor="#ffffff"
+ inkscape:window-height="699"
+ inkscape:zoom="4.9119411"
+ inkscape:window-x="0"
+ borderopacity="1.0"
+ inkscape:current-layer="svg1"
+ inkscape:cx="60.290892"
+ inkscape:cy="24.030855"
+ inkscape:window-width="1024"
+ inkscape:pageopacity="0.0"
+ />
+ <path
+ id="path1716"
+ style="stroke-linejoin:round;stroke:#ffffff;stroke-width:8.3605;fill:none"
+ transform="matrix(.97183 0 0 .97183 .87037 .23733)"
+ d="m7.513 4.5767c-1.3709 0-2.4745 1.1036-2.4745 2.4745v31.564c0 1.371 1.1036 2.474 2.4745 2.474h29.783c1.371 0 2.474-1.103 2.474-2.474v-31.564c0-1.3707-1.103-2.4743-2.474-2.4743h-29.783z"
+ />
+ <path
+ id="rect1101"
+ style="stroke-linejoin:round;fill-rule:evenodd;stroke:#000000;stroke-width:3.2156;fill:#ffffff"
+ transform="matrix(.97183 0 0 .97183 .87037 .23733)"
+ d="m7.513 4.5767c-1.3709 0-2.4745 1.1036-2.4745 2.4745v31.564c0 1.371 1.1036 2.474 2.4745 2.474h29.783c1.371 0 2.474-1.103 2.474-2.474v-31.564c0-1.3707-1.103-2.4743-2.474-2.4743h-29.783z"
+ />
+ <path
+ id="path1094"
+ style="stroke-linejoin:round;stroke:#ffffff;stroke-width:8.3605;fill:none"
+ transform="matrix(.97183 0 0 .97183 .87037 .23733)"
+ d="m22.652 20.161c-1.37 0-2.474 1.104-2.474 2.475v31.564c0 1.371 1.104 2.474 2.474 2.474h29.783c1.371 0 2.475-1.103 2.475-2.474v-31.564c0-1.371-1.104-2.475-2.475-2.475h-29.783z"
+ />
+ <path
+ id="rect1111"
+ style="stroke-linejoin:round;fill-rule:evenodd;stroke:#000000;stroke-width:3.2156;fill:#ffffff"
+ transform="matrix(.97183 0 0 .97183 .87037 .23733)"
+ d="m22.652 20.161c-1.37 0-2.474 1.104-2.474 2.475v31.564c0 1.371 1.104 2.474 2.474 2.474h29.783c1.371 0 2.475-1.103 2.475-2.474v-31.564c0-1.371-1.104-2.475-2.475-2.475h-29.783z"
+ />
+ <path
+ id="path1718"
+ style="stroke-linejoin:round;stroke:#ffffff;stroke-linecap:round;stroke-width:8.125;fill:none"
+ d="m12.457 21.599c2.325 20.529 20.15 19.15 21.296 19.043v6.139l8.981-8.889-8.981-8.87v6.066c-1.348 0.159-13.941 1.422-21.296-13.489z"
+ />
+ <path
+ id="path1574"
+ style="stroke-linejoin:round;fill-rule:evenodd;stroke:#000000;stroke-linecap:round;stroke-width:3.125;fill:#000000"
+ d="m12.457 21.599c2.325 20.529 20.15 19.15 21.296 19.043v6.139l8.981-8.889-8.981-8.87v6.066c-1.348 0.159-13.941 1.422-21.296-13.489z"
+ />
+ <metadata
+ >
+ <rdf:RDF
+ >
+ <cc:Work
+ >
+ <dc:format
+ >image/svg+xml</dc:format
+ >
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ />
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/publicdomain/"
+ />
+ <dc:publisher
+ >
+ <cc:Agent
+ rdf:about="http://openclipart.org/"
+ >
+ <dc:title
+ >Openclipart</dc:title
+ >
+ </cc:Agent
+ >
+ </dc:publisher
+ >
+ </cc:Work
+ >
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/publicdomain/"
+ >
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction"
+ />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution"
+ />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
+ />
+ </cc:License
+ >
+ </rdf:RDF
+ >
+ </metadata
+ >
+</svg
+>
diff --git a/apps/user_ldap/js/experiencedAdmin.js b/apps/user_ldap/js/experiencedAdmin.js
deleted file mode 100644
index 7dc5a4e503d..00000000000
--- a/apps/user_ldap/js/experiencedAdmin.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * Copyright (c) 2014, Arthur Schiwon <blizzz@owncloud.com>
- * This file is licensed under the Affero General Public License version 3 or later.
- * See the COPYING-README file.
- */
-
-/* global LdapWizard */
-
-/**
- * controls behaviour depend on whether the admin is experienced in LDAP or not.
- *
- * @class
- * @param {object} wizard the LDAP Wizard object
- * @param {boolean} initialState whether the admin is experienced or not
- */
-function ExperiencedAdmin(wizard, initialState) {
- this.wizard = wizard;
- this._isExperienced = initialState;
- if(this._isExperienced) {
- this.hideEntryCounters();
- }
-}
-
-
-/**
- * toggles whether the admin is an experienced one or not
- *
- * @param {boolean} isExperienced whether the admin is experienced or not
- */
-ExperiencedAdmin.prototype.setExperienced = function(isExperienced) {
- this._isExperienced = isExperienced;
- if(this._isExperienced) {
- this.enableRawMode();
- this.hideEntryCounters();
- } else {
- this.showEntryCounters();
- }
-};
-
-/**
-* answers whether the admin is an experienced one or not
-*
-* @return {boolean} whether the admin is experienced or not
-*/
-ExperiencedAdmin.prototype.isExperienced = function() {
- return this._isExperienced;
-};
-
-/**
- * switches all LDAP filters from Assisted to Raw mode.
- */
-ExperiencedAdmin.prototype.enableRawMode = function() {
- LdapWizard._save({id: 'ldapGroupFilterMode'}, LdapWizard.filterModeRaw);
- LdapWizard._save({id: 'ldapUserFilterMode' }, LdapWizard.filterModeRaw);
- LdapWizard._save({id: 'ldapLoginFilterMode'}, LdapWizard.filterModeRaw);
-};
-
-ExperiencedAdmin.prototype.updateUserTab = function(mode) {
- this._updateTab(mode, $('#ldap_user_count'));
-};
-
-ExperiencedAdmin.prototype.updateGroupTab = function(mode) {
- this._updateTab(mode, $('#ldap_group_count'));
-};
-
-ExperiencedAdmin.prototype._updateTab = function(mode, $countEl) {
- if(mode === LdapWizard.filterModeAssisted) {
- $countEl.removeClass('hidden');
- } else if(!this._isExperienced) {
- $countEl.removeClass('hidden');
- } else {
- $countEl.addClass('hidden');
- }
-};
-
-/**
- * hide user and group counters, they will be displayed on demand only
- */
-ExperiencedAdmin.prototype.hideEntryCounters = function() {
- $('#ldap_user_count').addClass('hidden');
- $('#ldap_group_count').addClass('hidden');
- $('.ldapGetEntryCount').removeClass('hidden');
-};
-
-/**
-* shows user and group counters, they will be displayed on demand only
-*/
-ExperiencedAdmin.prototype.showEntryCounters = function() {
- $('#ldap_user_count').removeClass('hidden');
- $('#ldap_group_count').removeClass('hidden');
- $('.ldapGetEntryCount').addClass('hidden');
-};
diff --git a/apps/user_ldap/js/ldapFilter.js b/apps/user_ldap/js/ldapFilter.js
deleted file mode 100644
index dc65858217d..00000000000
--- a/apps/user_ldap/js/ldapFilter.js
+++ /dev/null
@@ -1,193 +0,0 @@
-/* global LdapWizard */
-
-function LdapFilter(target, determineModeCallback) {
- this.locked = true;
- this.target = false;
- this.mode = LdapWizard.filterModeAssisted;
- this.lazyRunCompose = false;
- this.determineModeCallback = determineModeCallback;
- this.foundFeatures = false;
- this.activated = false;
- this.countPending = false;
-
- if( target === 'User' ||
- target === 'Login' ||
- target === 'Group') {
- this.target = target;
- }
-}
-
-LdapFilter.prototype.activate = function() {
- if(this.activated) {
- // might be necessary, if configuration changes happened.
- this.findFeatures();
- return;
- }
- this.activated = true;
-
- this.determineMode();
-};
-
-LdapFilter.prototype.compose = function(updateCount) {
- var action;
-
- if(updateCount === true) {
- this.countPending = updateCount;
- }
-
- if(this.locked) {
- this.lazyRunCompose = true;
- return false;
- }
-
- if(this.mode === LdapWizard.filterModeRaw) {
- //Raw filter editing, i.e. user defined filter, don't compose
- return;
- }
-
- if(this.target === 'User') {
- action = 'getUserListFilter';
- } else if(this.target === 'Login') {
- action = 'getUserLoginFilter';
- } else if(this.target === 'Group') {
- action = 'getGroupFilter';
- }
-
- var param = 'action='+action+
- '&ldap_serverconfig_chooser='+
- encodeURIComponent($('#ldap_serverconfig_chooser').val());
-
- var filter = this;
-
- LdapWizard.ajax(param,
- function(result) {
- filter.afterComposeSuccess(result);
- },
- function () {
- filter.countPending = false;
- console.log('LDAP Wizard: could not compose filter. '+
- 'Please check owncloud.log');
- }
- );
-};
-
-/**
- * this function is triggered after LDAP filters have been composed successfully
- * @param {object} result returned by the ajax call
- */
-LdapFilter.prototype.afterComposeSuccess = function(result) {
- LdapWizard.applyChanges(result);
- if(this.countPending) {
- this.countPending = false;
- this.updateCount();
- }
-};
-
-LdapFilter.prototype.determineMode = function() {
- var param = 'action=get'+encodeURIComponent(this.target)+'FilterMode'+
- '&ldap_serverconfig_chooser='+
- encodeURIComponent($('#ldap_serverconfig_chooser').val());
-
- var filter = this;
- LdapWizard.ajax(param,
- function(result) {
- var property = 'ldap' + filter.target + 'FilterMode';
- filter.mode = parseInt(result.changes[property], 10);
- var rawContainerIsInvisible =
- $('#raw'+filter.target+'FilterContainer').hasClass('invisible');
- if ( filter.mode === LdapWizard.filterModeRaw
- && rawContainerIsInvisible
- ) {
- LdapWizard['toggleRaw'+filter.target+'Filter']();
- } else if ( filter.mode === LdapWizard.filterModeAssisted
- && !rawContainerIsInvisible
- ) {
- LdapWizard['toggleRaw'+filter.target+'Filter']();
- } else {
- console.log('LDAP Wizard determineMode: returned mode was »' +
- filter.mode + '« of type ' + typeof filter.mode);
- }
- filter.unlock();
- filter.determineModeCallback(filter.mode);
- },
- function () {
- //on error case get back to default i.e. Assisted
- if(!$('#raw'+filter.target+'FilterContainer').hasClass('invisible')) {
- LdapWizard['toggleRaw'+filter.target+'Filter']();
- filter.mode = LdapWizard.filterModeAssisted;
- }
- filter.unlock();
- filter.determineModeCallback(filter.mode);
- }
- );
-};
-
-LdapFilter.prototype.setMode = function(mode) {
- if(mode === LdapWizard.filterModeAssisted || mode === LdapWizard.filterModeRaw) {
- this.mode = mode;
- }
-};
-
-LdapFilter.prototype.getMode = function() {
- return this.mode;
-};
-
-LdapFilter.prototype.unlock = function() {
- this.locked = false;
- if(this.lazyRunCompose) {
- this.lazyRunCompose = false;
- this.compose();
- }
-};
-
-/**
- * resets this.foundFeatures so that LDAP queries can be fired again to retrieve
- * objectClasses, groups, etc.
- */
-LdapFilter.prototype.reAllowFeatureLookup = function () {
- this.foundFeatures = false;
-};
-
-LdapFilter.prototype.findFeatures = function() {
- if(!this.foundFeatures && !this.locked && this.mode === LdapWizard.filterModeAssisted) {
- this.foundFeatures = true;
- var objcEl, avgrEl;
- if(this.target === 'User') {
- objcEl = 'ldap_userfilter_objectclass';
- avgrEl = 'ldap_userfilter_groups';
- } else if (this.target === 'Group') {
- objcEl = 'ldap_groupfilter_objectclass';
- avgrEl = 'ldap_groupfilter_groups';
- } else if (this.target === 'Login') {
- LdapWizard.findAttributes();
- return;
- } else {
- return false;
- }
- LdapWizard.findObjectClasses(objcEl, this.target);
- LdapWizard.findAvailableGroups(avgrEl, this.target + "s");
- }
-};
-
-/**
- * this function is triggered before user and group counts are executed
- * resolving the passed status variable will fire up counting
- */
-LdapFilter.prototype.beforeUpdateCount = function() {
- var status = $.Deferred();
- LdapWizard.runDetectors(this.target, function() {
- status.resolve();
- });
- return status;
-};
-
-LdapFilter.prototype.updateCount = function(doneCallback) {
- var filter = this;
- $.when(this.beforeUpdateCount()).done(function() {
- if(filter.target === 'User') {
- LdapWizard.countUsers(doneCallback);
- } else if (filter.target === 'Group') {
- LdapWizard.countGroups(doneCallback);
- }
- });
-};
diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js
deleted file mode 100644
index 768d62a18d1..00000000000
--- a/apps/user_ldap/js/settings.js
+++ /dev/null
@@ -1,1205 +0,0 @@
-var LdapConfiguration = {
- refreshConfig: function() {
- if($('#ldap_serverconfig_chooser option').length < 2) {
- LdapConfiguration.addConfiguration(true);
- return;
- }
- $.post(
- OC.filePath('user_ldap','ajax','getConfiguration.php'),
- $('#ldap_serverconfig_chooser').serialize(),
- function (result) {
- if(result.status === 'success') {
- $.each(result.configuration, function(configkey, configvalue) {
- elementID = '#'+configkey;
-
- //deal with Checkboxes
- if($(elementID).is('input[type=checkbox]')) {
- if(parseInt(configvalue, 10) === 1) {
- $(elementID).attr('checked', 'checked');
- } else {
- $(elementID).removeAttr('checked');
- }
- return;
- }
-
- //On Textareas, Multi-Line Settings come as array
- if($(elementID).is('textarea') && $.isArray(configvalue)) {
- configvalue = configvalue.join("\n");
- }
-
- // assign the value
- $('#'+configkey).val(configvalue);
- });
- LdapWizard.init();
- }
- }
- );
- },
-
- resetDefaults: function() {
- $('#ldap').find('input[type=text], input[type=number], input[type=password], textarea, select').each(function() {
- if($(this).attr('id') === 'ldap_serverconfig_chooser') {
- return;
- }
- $(this).val($(this).attr('data-default'));
- });
- $('#ldap').find('input[type=checkbox]').each(function() {
- if($(this).attr('data-default') === 1) {
- $(this).attr('checked', 'checked');
- } else {
- $(this).removeAttr('checked');
- }
- });
- },
-
- deleteConfiguration: function() {
- $.post(
- OC.filePath('user_ldap','ajax','deleteConfiguration.php'),
- $('#ldap_serverconfig_chooser').serialize(),
- function (result) {
- if(result.status === 'success') {
- $('#ldap_serverconfig_chooser option:selected').remove();
- $('#ldap_serverconfig_chooser option:first').select();
- LdapConfiguration.refreshConfig();
- } else {
- OC.dialogs.alert(
- result.message,
- t('user_ldap', 'Deletion failed')
- );
- }
- }
- );
- },
-
- addConfiguration: function(doNotAsk) {
- $.post(
- OC.filePath('user_ldap','ajax','getNewServerConfigPrefix.php'),
- function (result) {
- if(result.status === 'success') {
- if(doNotAsk) {
- LdapConfiguration.resetDefaults();
- } else {
- OC.dialogs.confirm(
- t('user_ldap', 'Take over settings from recent server configuration?'),
- t('user_ldap', 'Keep settings?'),
- function(keep) {
- if(!keep) {
- LdapConfiguration.resetDefaults();
- }
- }
- );
- }
- $('#ldap_serverconfig_chooser option:selected').removeAttr('selected');
- var html = '<option value="'+result.configPrefix+'" selected="selected">'+t('user_ldap','{nthServer}. Server', {nthServer: $('#ldap_serverconfig_chooser option').length})+'</option>';
- $('#ldap_serverconfig_chooser option:last').before(html);
- LdapWizard.init();
- } else {
- OC.dialogs.alert(
- result.message,
- t('user_ldap', 'Cannot add server configuration')
- );
- }
- }
- );
- },
-
- testConfiguration: function(onSuccess, onError) {
- $.post(
- OC.filePath('user_ldap','ajax','testConfiguration.php'),
- $('#ldap').serialize(),
- function (result) {
- if (result.status === 'success') {
- onSuccess(result);
- } else {
- onError(result);
- }
- }
- );
- },
-
- clearMappings: function(mappingSubject) {
- $.post(
- OC.filePath('user_ldap','ajax','clearMappings.php'),
- 'ldap_clear_mapping='+encodeURIComponent(mappingSubject),
- function(result) {
- if(result.status === 'success') {
- OC.dialogs.info(
- t('user_ldap', 'mappings cleared'),
- t('user_ldap', 'Success')
- );
- } else {
- OC.dialogs.alert(
- result.message,
- t('user_ldap', 'Error')
- );
- }
- }
- );
- }
-};
-
-var LdapWizard = {
- checkPortInfoShown: false,
- saveBlacklist: {},
- userFilterGroupSelectState: 'enable',
- spinner: '<img class="wizSpinner" src="'+ OC.imagePath('core', 'loading.gif') +'">',
- filterModeAssisted: 0,
- filterModeRaw: 1,
- userFilter: false,
- loginFilter: false,
- groupFilter: false,
- ajaxRequests: {},
- lastTestSuccessful: true,
-
- ajax: function(param, fnOnSuccess, fnOnError, reqID) {
- if(!_.isUndefined(reqID)) {
- if(LdapWizard.ajaxRequests.hasOwnProperty(reqID)) {
- console.log('aborting ' + reqID);
- console.log(param);
- LdapWizard.ajaxRequests[reqID].abort();
- }
- }
- var request = $.post(
- OC.filePath('user_ldap','ajax','wizard.php'),
- param,
- function(result) {
- if(result.status === 'success') {
- fnOnSuccess(result);
- } else {
- fnOnError(result);
- }
- }
- );
- if(!_.isUndefined(reqID)) {
- LdapWizard.ajaxRequests[reqID] = request;
- }
- return request;
- },
-
- applyChanges: function (result) {
- for (var id in result.changes) {
- LdapWizard.blacklistAdd(id);
- if(id.indexOf('count') > 0) {
- $('#'+id).text(result.changes[id]);
- } else {
- $('#'+id).val(result.changes[id]);
- }
- }
- LdapWizard.functionalityCheck();
-
- if($('#ldapSettings').tabs('option', 'active') == 0) {
- LdapWizard.basicStatusCheck();
- }
- },
-
- enableTabs: function() {
- //do not use this function directly, use basicStatusCheck instead.
- if(LdapWizard.saveProcesses === 0) {
- $('.ldap_action_continue').removeAttr('disabled');
- $('.ldap_action_back').removeAttr('disabled');
- $('#ldapSettings').tabs('option', 'disabled', []);
- }
- },
-
- disableTabs: function() {
- $('.ldap_action_continue').attr('disabled', 'disabled');
- $('.ldap_action_back').attr('disabled', 'disabled');
- $('#ldapSettings').tabs('option', 'disabled', [1, 2, 3, 4, 5]);
- },
-
- basicStatusCheck: function() {
- //criteria to continue from the first tab
- // - host, port, user filter, agent dn, password, base dn
- var host = $('#ldap_host').val();
- var port = $('#ldap_port').val();
- var agent = $('#ldap_dn').val();
- var pwd = $('#ldap_agent_password').val();
- var base = $('#ldap_base').val();
-
- if((host && port && base) && ((!agent && !pwd) || (agent && pwd))) {
- LdapWizard.enableTabs();
- } else {
- LdapWizard.disableTabs();
- }
- },
-
-
- blacklistAdd: function(id) {
- var obj = $('#' + id);
- if(!(obj[0].hasOwnProperty('multiple') && obj[0]['multiple'] === true)) {
- //no need to blacklist multiselect
- LdapWizard.saveBlacklist[id] = true;
- return true;
- }
- return false;
- },
-
- blacklistRemove: function(id) {
- if(LdapWizard.saveBlacklist.hasOwnProperty(id)) {
- delete LdapWizard.saveBlacklist[id];
- return true;
- }
- return false;
- },
-
- checkBaseDN: function() {
- var host = $('#ldap_host').val();
- var port = $('#ldap_port').val();
- var user = $('#ldap_dn').val();
- var pass = $('#ldap_agent_password').val();
-
- //FIXME: determine base dn with anonymous access
- if(host && port && user && pass) {
- var param = 'action=guessBaseDN'+
- '&ldap_serverconfig_chooser='+
- encodeURIComponent($('#ldap_serverconfig_chooser').val());
-
- LdapWizard.showSpinner('#ldap_base');
- $('#ldap_base').prop('disabled', 'disabled');
- LdapWizard.ajax(param,
- function(result) {
- LdapWizard.applyChanges(result);
- LdapWizard.hideSpinner('#ldap_base');
- if($('#ldap_base').val()) {
- LdapWizard.hideInfoBox();
- }
- $('#ldap_base').prop('disabled', false);
- },
- function (result) {
- LdapWizard.hideSpinner('#ldap_base');
- LdapWizard.showInfoBox(t('user_ldap', 'Please specify a Base DN'));
- LdapWizard.showInfoBox(t('user_ldap', 'Could not determine Base DN'));
- $('#ldap_base').prop('disabled', false);
- },
- 'guessBaseDN'
- );
- }
- },
-
- checkPort: function() {
- var host = $('#ldap_host').val();
- var port = $('#ldap_port').val();
-
- if(host && !port) {
- var param = 'action=guessPortAndTLS'+
- '&ldap_serverconfig_chooser='+
- encodeURIComponent($('#ldap_serverconfig_chooser').val());
-
- LdapWizard.showSpinner('#ldap_port');
- $('#ldap_port').prop('disabled', 'disabled');
- LdapWizard.ajax(param,
- function(result) {
- LdapWizard.applyChanges(result);
- LdapWizard.hideSpinner('#ldap_port');
- if($('#ldap_port').val()) {
- LdapWizard.checkBaseDN();
- $('#ldap_port').prop('disabled', false);
- LdapWizard.hideInfoBox();
- }
- },
- function (result) {
- LdapWizard.hideSpinner('#ldap_port');
- $('#ldap_port').prop('disabled', false);
- LdapWizard.showInfoBox(t('user_ldap', 'Please specify the port'));
- },
- 'guessPortAndTLS'
- );
- }
- },
-
- controlBack: function() {
- var curTabIndex = $('#ldapSettings').tabs('option', 'active');
- if(curTabIndex == 0) {
- return;
- }
- $('#ldapSettings').tabs('option', 'active', curTabIndex - 1);
- LdapWizard.controlUpdate(curTabIndex - 1);
- },
-
- controlContinue: function() {
- var curTabIndex = $('#ldapSettings').tabs('option', 'active');
- if(curTabIndex == 3) {
- return;
- }
- $('#ldapSettings').tabs('option', 'active', 1 + curTabIndex);
- LdapWizard.controlUpdate(curTabIndex + 1);
- },
-
- controlUpdate: function(nextTabIndex) {
- if(nextTabIndex == 0) {
- $('.ldap_action_back').addClass('invisible');
- $('.ldap_action_continue').removeClass('invisible');
- } else
- if(nextTabIndex == 1) {
- $('.ldap_action_back').removeClass('invisible');
- $('.ldap_action_continue').removeClass('invisible');
- } else
- if(nextTabIndex == 2) {
- $('.ldap_action_continue').removeClass('invisible');
- $('.ldap_action_back').removeClass('invisible');
- } else
- if(nextTabIndex == 3) {
- //now last tab
- $('.ldap_action_back').removeClass('invisible');
- $('.ldap_action_continue').addClass('invisible');
- }
- },
-
- _countThings: function(method, spinnerID, doneCallback) {
- var param = 'action='+method+
- '&ldap_serverconfig_chooser='+
- encodeURIComponent($('#ldap_serverconfig_chooser').val());
-
- LdapWizard.showSpinner(spinnerID);
- LdapWizard.ajax(param,
- function(result) {
- LdapWizard.applyChanges(result);
- LdapWizard.hideSpinner(spinnerID);
- if(!_.isUndefined(doneCallback)) {
- doneCallback(method);
- }
- },
- function (result) {
- OC.Notification.showTemporary('Counting the entries failed with: ' + result.message);
- LdapWizard.hideSpinner(spinnerID);
- if(!_.isUndefined(doneCallback)) {
- doneCallback(method);
- }
- },
- method
- );
- },
-
- countGroups: function(doneCallback) {
- var groupFilter = $('#ldap_group_filter').val();
- if(!_.isEmpty(groupFilter)) {
- LdapWizard._countThings('countGroups', '#ldap_group_count', doneCallback);
- }
- },
-
- countUsers: function(doneCallback) {
- var userFilter = $('#ldap_userlist_filter').val();
- if(!_.isEmpty(userFilter)) {
- LdapWizard._countThings('countUsers', '#ldap_user_count', doneCallback);
- }
- },
-
- /**
- * called after detectors have run
- * @callback runDetectorsCallback
- */
-
- /**
- * runs detectors to determine appropriate attributes, e.g. displayName
- * @param {string} type either "User" or "Group"
- * @param {runDetectorsCallback} triggered after all detectors have completed
- */
- runDetectors: function(type, callback) {
- if(type === 'Group') {
- $.when(LdapWizard.detectGroupMemberAssoc())
- .then(callback, callback);
- if( LdapWizard.admin.isExperienced
- && !(LdapWizard.detectorsRunInXPMode & LdapWizard.groupDetectors)) {
- LdapWizard.detectorsRunInXPMode += LdapWizard.groupDetectors;
- }
- } else if(type === 'User') {
- var req1 = LdapWizard.detectUserDisplayNameAttribute();
- var req2 = LdapWizard.detectEmailAttribute();
- $.when(req1, req2)
- .then(callback, callback);
- if( LdapWizard.admin.isExperienced
- && !(LdapWizard.detectorsRunInXPMode & LdapWizard.userDetectors)) {
- LdapWizard.detectorsRunInXPMode += LdapWizard.userDetectors;
- }
- }
- },
-
- /**
- * runs detector to find out a fitting user display name attribute
- */
- detectUserDisplayNameAttribute: function() {
- var param = 'action=detectUserDisplayNameAttribute' +
- '&ldap_serverconfig_chooser='+
- encodeURIComponent($('#ldap_serverconfig_chooser').val());
-
- //runs in the background, no callbacks necessary
- return LdapWizard.ajax(param, LdapWizard.applyChanges, function(){}, 'detectUserDisplayNameAttribute');
- },
-
- detectEmailAttribute: function() {
- var param = 'action=detectEmailAttribute'+
- '&ldap_serverconfig_chooser='+
- encodeURIComponent($('#ldap_serverconfig_chooser').val());
- //runs in the background, no callbacks necessary
- return LdapWizard.ajax(param, LdapWizard.applyChanges, function(){}, 'detectEmailAttribute');
- },
-
- detectGroupMemberAssoc: function() {
- param = 'action=determineGroupMemberAssoc'+
- '&ldap_serverconfig_chooser='+
- encodeURIComponent($('#ldap_serverconfig_chooser').val());
-
- return LdapWizard.ajax(param,
- function(result) {
- //pure background story
- },
- function (result) {
- // error handling
- },
- 'determineGroupMemberAssoc'
- );
- },
-
- findAttributes: function() {
- param = 'action=determineAttributes'+
- '&ldap_serverconfig_chooser='+
- encodeURIComponent($('#ldap_serverconfig_chooser').val());
-
- LdapWizard.showSpinner('#ldap_loginfilter_attributes');
- LdapWizard.ajax(param,
- function(result) {
- $('#ldap_loginfilter_attributes').find('option').remove();
- for (var i in result.options['ldap_loginfilter_attributes']) {
- //FIXME: move HTML into template
- var attr = result.options['ldap_loginfilter_attributes'][i];
- $('#ldap_loginfilter_attributes').append(
- "<option value='"+attr+"'>"+attr+"</option>");
- }
- LdapWizard.hideSpinner('#ldap_loginfilter_attributes');
- LdapWizard.applyChanges(result);
- $('#ldap_loginfilter_attributes').multiselect('refresh');
- if($('#rawLoginFilterContainer').hasClass('invisible')) {
- $('#ldap_loginfilter_attributes').multiselect('enable');
- }
- LdapWizard.postInitLoginFilter();
- },
- function (result) {
- //deactivate if no attributes found
- $('#ldap_loginfilter_attributes').multiselect(
- {noneSelectedText : 'No attributes found'});
- $('#ldap_loginfilter_attributes').multiselect('disable');
- LdapWizard.hideSpinner('#ldap_loginfilter_attributes');
- },
- 'determineAttributes'
- );
- },
-
- findAvailableGroups: function(multisel, type) {
- if(type !== 'Users' && type !== 'Groups') {
- return false;
- }
- param = 'action=determineGroupsFor'+encodeURIComponent(type)+
- '&ldap_serverconfig_chooser='+
- encodeURIComponent($('#ldap_serverconfig_chooser').val());
-
- LdapWizard.showSpinner('#'+multisel);
- LdapWizard.ajax(param,
- function(result) {
- $('#'+multisel).find('option').remove();
- for (var i in result.options[multisel]) {
- //FIXME: move HTML into template
- objc = result.options[multisel][i];
- $('#'+multisel).append("<option value='"+objc+"'>"+objc+"</option>");
- }
- LdapWizard.hideSpinner('#'+multisel);
- LdapWizard.applyChanges(result);
- $('#'+multisel).multiselect('refresh');
- part = type.slice(0, -1);
- if($('#raw' + part + 'FilterContainer').hasClass('invisible')) {
- //enable only when raw filter editing is not turned on
- $('#'+multisel).multiselect('enable');
- }
- if(type === 'Users') {
- //required for initial save
- filter = $('#ldap_userlist_filter').val();
- if(!filter) {
- LdapWizard.saveMultiSelect(multisel,
- $('#'+multisel).multiselect("getChecked"));
- }
- LdapWizard.userFilterAvailableGroupsHasRun = true;
- LdapWizard.postInitUserFilter();
- }
- },
- function (result) {
- LdapWizard.hideSpinner('#'+multisel);
- $('#'+multisel).multiselect('disable');
- if(type === 'Users') {
- LdapWizard.userFilterAvailableGroupsHasRun = true;
- LdapWizard.postInitUserFilter();
- }
- },
- 'findAvailableGroupsFor' + type
- );
- },
-
- findObjectClasses: function(multisel, type) {
- if(type !== 'User' && type !== 'Group') {
- return false;
- }
- var param = 'action=determine'+encodeURIComponent(type)+'ObjectClasses'+
- '&ldap_serverconfig_chooser='+
- encodeURIComponent($('#ldap_serverconfig_chooser').val());
-
- LdapWizard.showSpinner('#'+multisel);
- LdapWizard.ajax(param,
- function(result) {
- $('#'+multisel).find('option').remove();
- for (var i in result.options[multisel]) {
- //FIXME: move HTML into template
- objc = result.options[multisel][i];
- $('#'+multisel).append("<option value='"+objc+"'>"+objc+"</option>");
- }
- LdapWizard.hideSpinner('#'+multisel);
- LdapWizard.applyChanges(result);
- $('#'+multisel).multiselect('refresh');
- if(type === 'User') {
- //required for initial save
- filter = $('#ldap_userlist_filter').val();
- if(!filter) {
- LdapWizard.saveMultiSelect(multisel,
- $('#'+multisel).multiselect("getChecked"));
- }
- LdapWizard.userFilterObjectClassesHasRun = true;
- LdapWizard.postInitUserFilter();
- }
- },
- function (result) {
- LdapWizard.hideSpinner('#'+multisel);
- if(type === 'User') {
- LdapWizard.userFilterObjectClassesHasRun = true;
- LdapWizard.postInitUserFilter();
- }
- //TODO: error handling
- },
- 'determine' + type + 'ObjectClasses'
- );
- },
-
- functionalityCheck: function() {
- //criteria to enable the connection:
- // - host, port, basedn, user filter, login filter
- var host = $('#ldap_host').val();
- var port = $('#ldap_port').val();
- var base = $('#ldap_base').val();
- var userfilter = $('#ldap_userlist_filter').val();
- var loginfilter = $('#ldap_login_filter').val();
-
- //FIXME: activates a manually deactivated configuration.
- if(host && port && base && userfilter && loginfilter) {
- LdapWizard.updateStatusIndicator(true);
- if($('#ldap_configuration_active').is(':checked')) {
- return;
- }
- if(!LdapWizard.isConfigurationActiveControlLocked) {
- //avoids a manually deactivated connection will be activated
- //upon opening the admin page
- $('#ldap_configuration_active').prop('checked', true);
- LdapWizard.save($('#ldap_configuration_active')[0]);
- }
- } else {
- if($('#ldap_configuration_active').is(':checked')) {
- $('#ldap_configuration_active').prop('checked', false);
- LdapWizard.save($('#ldap_configuration_active')[0]);
- }
- LdapWizard.updateStatusIndicator(false);
- }
- },
-
- hideInfoBox: function() {
- if(LdapWizard.checkInfoShown) {
- $('#ldapWizard1 .ldapWizardInfo').addClass('invisible');
- LdapWizard.checkInfoShown = false;
- }
- },
-
- hideSpinner: function(id) {
- $(id+' + .wizSpinner').remove();
- $(id + " + button").css('display', 'inline');
- },
-
- isConfigurationActiveControlLocked: true,
- detectorsRunInXPMode: 0,
- userDetectors: 1,
- groupDetectors: 2,
-
- init: function() {
- LdapWizard.detectorsRunInXPMode = 0;
- LdapWizard.instantiateFilters();
- LdapWizard.admin.setExperienced($('#ldap_experienced_admin').is(':checked'));
- LdapWizard.lastTestSuccessful = true;
- LdapWizard.basicStatusCheck();
- LdapWizard.functionalityCheck();
- LdapWizard.isConfigurationActiveControlLocked = false;
- },
-
- initGroupFilter: function() {
- LdapWizard.groupFilter.activate();
- },
-
- /** init login filter tab section **/
-
- initLoginFilter: function() {
- LdapWizard.loginFilter.activate();
- },
-
- postInitLoginFilter: function() {
- if($('#rawLoginFilterContainer').hasClass('invisible')) {
- LdapWizard.loginFilter.compose();
- }
- },
-
- /** end of init user filter tab section **/
-
- initMultiSelect: function(object, id, caption) {
- object.multiselect({
- header: false,
- selectedList: 9,
- noneSelectedText: caption,
- click: function(event, ui) {
- LdapWizard.saveMultiSelect(id,
- $('#'+id).multiselect("getChecked"));
- }
- });
- },
-
- hideTestSpinner:function (countMethod) {
- var selector;
- if(countMethod === 'countUsers') {
- selector = '#rawUserFilterContainer .ldapGetEntryCount';
- } else {
- selector = '#rawGroupFilterContainer .ldapGetEntryCount';
- }
- LdapWizard.hideSpinner(selector);
- },
-
- /** init user filter tab section **/
-
- instantiateFilters: function() {
- delete LdapWizard.userFilter;
- LdapWizard.userFilter = new LdapFilter('User', function(mode) {
- if( !LdapWizard.admin.isExperienced()
- || mode === LdapWizard.filterModeAssisted) {
- LdapWizard.userFilter.updateCount();
- }
- LdapWizard.userFilter.findFeatures();
- });
- $('#rawUserFilterContainer .ldapGetEntryCount').click(function(event) {
- event.preventDefault();
- $('#ldap_user_count').text('');
- LdapWizard.showSpinner('#rawUserFilterContainer .ldapGetEntryCount');
- LdapWizard.userFilter.updateCount(LdapWizard.hideTestSpinner);
- $('#ldap_user_count').removeClass('hidden');
- });
-
- delete LdapWizard.loginFilter;
- LdapWizard.loginFilter = new LdapFilter('Login', function(mode) {
- LdapWizard.loginFilter.findFeatures();
- });
-
- delete LdapWizard.groupFilter;
- LdapWizard.groupFilter = new LdapFilter('Group', function(mode) {
- if( !LdapWizard.admin.isExperienced()
- || mode === LdapWizard.filterModeAssisted) {
- LdapWizard.groupFilter.updateCount();
- }
- LdapWizard.groupFilter.findFeatures();
- });
- $('#rawGroupFilterContainer .ldapGetEntryCount').click(function(event) {
- event.preventDefault();
- $('#ldap_group_count').text('');
- LdapWizard.showSpinner('#rawGroupFilterContainer .ldapGetEntryCount');
- LdapWizard.groupFilter.updateCount(LdapWizard.hideTestSpinner);
- $('#ldap_group_count').removeClass('hidden');
- });
- },
-
- userFilterObjectClassesHasRun: false,
- userFilterAvailableGroupsHasRun: false,
-
- initUserFilter: function() {
- LdapWizard.userFilterObjectClassesHasRun = false;
- LdapWizard.userFilterAvailableGroupsHasRun = false;
- LdapWizard.userFilter.activate();
- },
-
- postInitUserFilter: function() {
- if(LdapWizard.userFilterObjectClassesHasRun &&
- LdapWizard.userFilterAvailableGroupsHasRun) {
- LdapWizard.userFilter.compose();
- }
- },
-
- /** end of init user filter tab section **/
-
- onTabChange: function(event, ui) {
- if(LdapWizard.saveProcesses > 0) {
- //do not allow to switch tabs as long as a save process is active
- return false;
- }
- var newTabIndex = 0;
- if(ui.newTab[0].id === '#ldapWizard2') {
- LdapWizard.initUserFilter();
- newTabIndex = 1;
- } else if(ui.newTab[0].id === '#ldapWizard3') {
- LdapWizard.initLoginFilter();
- newTabIndex = 2;
- } else if(ui.newTab[0].id === '#ldapWizard4') {
- LdapWizard.initGroupFilter();
- newTabIndex = 3;
- }
-
- var curTabIndex = $('#ldapSettings').tabs('option', 'active');
- if(curTabIndex >= 0 && curTabIndex <= 3) {
- LdapWizard.controlUpdate(newTabIndex);
- //run detectors in XP mode, when "Test Filter" button has not been
- //clicked in order to make sure that email, displayname, member-
- //group association attributes are properly set.
- if( curTabIndex === 1
- && LdapWizard.admin.isExperienced
- && !(LdapWizard.detecorsRunInXPMode & LdapWizard.userDetectors)
- ) {
- LdapWizard.runDetectors('User', function(){});
- } else if( curTabIndex === 3
- && LdapWizard.admin.isExperienced
- && !(LdapWizard.detecorsRunInXPMode & LdapWizard.groupDetectors)
- ) {
- LdapWizard.runDetectors('Group', function(){});
- }
- }
- },
-
- /**
- * allows UserFilter, LoginFilter and GroupFilter to lookup objectClasses
- * and similar again. This should be called after essential changes, e.g.
- * Host or BaseDN changes, or positive functionality check
- *
- */
- allowFilterFeatureSearch: function () {
- LdapWizard.userFilter.reAllowFeatureLookup();
- LdapWizard.loginFilter.reAllowFeatureLookup();
- LdapWizard.groupFilter.reAllowFeatureLookup();
- },
-
- processChanges: function (triggerObj) {
- LdapWizard.hideInfoBox();
-
- if(triggerObj.id === 'ldap_host'
- || triggerObj.id === 'ldap_port'
- || triggerObj.id === 'ldap_dn'
- || triggerObj.id === 'ldap_agent_password') {
- LdapWizard.checkPort();
- if($('#ldap_port').val()) {
- //if Port is already set, check BaseDN
- LdapWizard.checkBaseDN();
- LdapWizard.allowFilterFeatureSearch();
- }
- }
-
- if(triggerObj.id === 'ldap_loginfilter_username'
- || triggerObj.id === 'ldap_loginfilter_email') {
- LdapWizard.loginFilter.compose();
- } else if (!LdapWizard.admin.isExperienced()) {
- if(triggerObj.id === 'ldap_userlist_filter') {
- LdapWizard.userFilter.updateCount();
- } else if (triggerObj.id === 'ldap_group_filter') {
- LdapWizard.groupFilter.updateCount();
- }
- }
-
- if($('#ldapSettings').tabs('option', 'active') == 0) {
- LdapWizard.basicStatusCheck();
- LdapWizard.functionalityCheck();
- }
- },
-
- save: function(inputObj) {
- if(LdapWizard.blacklistRemove(inputObj.id)) {
- return;
- }
- if($(inputObj).is('input[type=checkbox]')
- && !$(inputObj).is(':checked')) {
- val = 0;
- } else {
- val = $(inputObj).val();
- }
- LdapWizard._save(inputObj, val);
- },
-
- /**
- * updates user or group count on multiSelect close. Resets the event
- * function subsequently.
- *
- * @param {LdapFilter} filter
- * @param {Object} $multiSelectObj
- */
- onMultiSelectClose: function(filter, $multiSelectObj) {
- filter.updateCount();
- $multiSelectObj.multiselect({close: function(){}});
- },
-
- saveMultiSelect: function(originalObj, resultObj) {
- var values = '';
- for(var i = 0; i < resultObj.length; i++) {
- values = values + "\n" + resultObj[i].value;
- }
- LdapWizard._save($('#'+originalObj)[0], $.trim(values));
- var $multiSelectObj = $('#'+originalObj);
- var updateCount = !$multiSelectObj.multiselect("isOpen");
- var applyUpdateOnCloseToFilter;
- if(originalObj === 'ldap_userfilter_objectclass'
- || originalObj === 'ldap_userfilter_groups') {
- LdapWizard.userFilter.compose(updateCount);
- if(!updateCount) {
- applyUpdateOnCloseToFilter = LdapWizard.userFilter;
- }
- //when user filter is changed afterwards, login filter needs to
- //be adjusted, too
- if(!LdapWizard.loginFilter) {
- LdapWizard.initLoginFilter();
- }
- LdapWizard.loginFilter.compose();
- } else if(originalObj === 'ldap_loginfilter_attributes') {
- LdapWizard.loginFilter.compose();
- } else if(originalObj === 'ldap_groupfilter_objectclass'
- || originalObj === 'ldap_groupfilter_groups') {
- LdapWizard.groupFilter.compose(updateCount);
- if(!updateCount) {
- applyUpdateOnCloseToFilter = LdapWizard.groupFilter;
- }
- }
-
- if(applyUpdateOnCloseToFilter instanceof LdapFilter) {
- $multiSelectObj.multiselect({
- close: function () {
- LdapWizard.onMultiSelectClose(
- applyUpdateOnCloseToFilter, $multiSelectObj);
- }
- });
- }
- },
-
- saveProcesses: 0,
- _save: function(object, value) {
- $('#ldap .ldap_saving').removeClass('hidden');
- LdapWizard.saveProcesses += 1;
- $('#ldap *').addClass('save-cursor');
- param = 'cfgkey='+encodeURIComponent(object.id)+
- '&cfgval='+encodeURIComponent(value)+
- '&action=save'+
- '&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
-
- $.post(
- OC.filePath('user_ldap','ajax','wizard.php'),
- param,
- function(result) {
- LdapWizard.saveProcesses -= 1;
- if(LdapWizard.saveProcesses === 0) {
- $('#ldap .ldap_saving').addClass('hidden');
- $('#ldap *').removeClass('save-cursor');
- }
- if(result.status === 'success') {
- LdapWizard.processChanges(object);
- } else {
- console.log('Could not save value for ' + object.id);
- }
- }
- );
- },
-
- showInfoBox: function(text) {
- $('#ldapWizard1 .ldapWizardInfo').text(text);
- $('#ldapWizard1 .ldapWizardInfo').removeClass('invisible');
- LdapWizard.checkInfoShown = true;
- },
-
- showSpinner: function(id) {
- if($(id + ' + .wizSpinner').length == 0) {
- $(LdapWizard.spinner).insertAfter($(id));
- $(id + " + img + button").css('display', 'none');
- }
- },
-
- toggleRawFilter: function(container, moc, mg, stateVar, modeKey) {
- var isUser = moc.indexOf('user') >= 0;
- var filter = isUser ? LdapWizard.userFilter : LdapWizard.groupFilter;
- //moc = multiselect objectclass
- //mg = mutliselect groups
- if($(container).hasClass('invisible')) {
- filter.setMode(LdapWizard.filterModeRaw);
- $(container).removeClass('invisible');
- $(moc).multiselect('disable');
- if($(mg).multiselect().attr('disabled') === 'disabled') {
- LdapWizard[stateVar] = 'disable';
- } else {
- LdapWizard[stateVar] = 'enable';
- }
- $(mg).multiselect('disable');
- LdapWizard._save({ id: modeKey }, LdapWizard.filterModeRaw);
- } else {
- filter.setMode(LdapWizard.filterModeAssisted);
- filter.findFeatures();
- $(container).addClass('invisible');
- $(mg).multiselect(LdapWizard[stateVar]);
- $(moc).multiselect('enable');
- LdapWizard._save({ id: modeKey }, LdapWizard.filterModeAssisted);
- if(isUser) {
- LdapWizard.blacklistRemove('ldap_userlist_filter');
- LdapWizard.userFilter.compose(true);
- } else {
- LdapWizard.blacklistRemove('ldap_group_filter');
- LdapWizard.groupFilter.compose(true);
- }
- }
- },
-
- onToggleRawFilterConfirmation: function(currentMode, isRawVisible, callback) {
- if( !LdapWizard.admin.isExperienced()
- || currentMode === LdapWizard.filterModeAssisted
- || (LdapWizard.admin.isExperienced() && !isRawVisible)
- ) {
- return callback(true);
- }
-
- var confirmed = OCdialogs.confirm(
- 'Switching the mode will enable automatic LDAP queries. Depending on your LDAP size they may take a while. Do you still want to switch the mode?',
- 'Mode switch',
- callback
- );
- },
-
- toggleRawGroupFilter: function() {
- LdapWizard.onToggleRawFilterConfirmation(
- LdapWizard.groupFilter.getMode(),
- !$('#rawGroupFilterContainer').hasClass('invisible'),
- function(confirmed) {
- if(confirmed !== true) {
- return;
- }
-
- LdapWizard.blacklistRemove('ldap_group_filter');
- LdapWizard.toggleRawFilter('#rawGroupFilterContainer',
- '#ldap_groupfilter_objectclass',
- '#ldap_groupfilter_groups',
- 'groupFilterGroupSelectState',
- 'ldapGroupFilterMode'
- );
- LdapWizard.admin.updateGroupTab(LdapWizard.groupFilter.getMode());
- }
- );
- },
-
- toggleRawLoginFilter: function() {
- LdapWizard.onToggleRawFilterConfirmation(
- LdapWizard.loginFilter.getMode(),
- !$('#rawLoginFilterContainer').hasClass('invisible'),
- function(confirmed) {
- if(confirmed !== true) {
- return;
- }
-
- LdapWizard.blacklistRemove('ldap_login_filter');
- container = '#rawLoginFilterContainer';
- if($(container).hasClass('invisible')) {
- $(container).removeClass('invisible');
- action = 'disable';
- property = 'disabled';
- mode = LdapWizard.filterModeRaw;
- } else {
- $(container).addClass('invisible');
- action = 'enable';
- property = false;
- mode = LdapWizard.filterModeAssisted;
- }
- LdapWizard.loginFilter.setMode(mode);
- LdapWizard.loginFilter.findFeatures();
- $('#ldap_loginfilter_attributes').multiselect(action);
- $('#ldap_loginfilter_email').prop('disabled', property);
- $('#ldap_loginfilter_username').prop('disabled', property);
- LdapWizard._save({ id: 'ldapLoginFilterMode' }, mode);
- if(action === 'enable') {
- LdapWizard.loginFilter.compose();
- }
- }
- );
- },
-
- toggleRawUserFilter: function() {
- LdapWizard.onToggleRawFilterConfirmation(
- LdapWizard.userFilter.getMode(),
- !$('#rawUserFilterContainer').hasClass('invisible'),
- function(confirmed) {
- if(confirmed === true) {
- LdapWizard.blacklistRemove('ldap_userlist_filter');
- LdapWizard.toggleRawFilter('#rawUserFilterContainer',
- '#ldap_userfilter_objectclass',
- '#ldap_userfilter_groups',
- 'userFilterGroupSelectState',
- 'ldapUserFilterMode'
- );
- LdapWizard.admin.updateUserTab(LdapWizard.userFilter.getMode());
- }
- }
- );
- },
-
- updateStatusIndicator: function(isComplete) {
- if(isComplete) {
- LdapConfiguration.testConfiguration(
- //onSuccess
- function(result) {
- $('.ldap_config_state_indicator').text(t('user_ldap',
- 'Configuration OK'
- ));
- $('.ldap_config_state_indicator').addClass('ldap_grey');
- $('.ldap_config_state_indicator_sign').removeClass('error');
- $('.ldap_config_state_indicator_sign').addClass('success');
- if(!LdapWizard.lastTestSuccessful) {
- LdapWizard.lastTestSuccessful = true;
- LdapWizard.allowFilterFeatureSearch();
- }
- },
- //onError
- function(result) {
- $('.ldap_config_state_indicator').text(t('user_ldap',
- 'Configuration incorrect'
- ));
- $('.ldap_config_state_indicator').removeClass('ldap_grey');
- $('.ldap_config_state_indicator_sign').addClass('error');
- $('.ldap_config_state_indicator_sign').removeClass('success');
- LdapWizard.lastTestSuccessful = false;
- }
- );
- } else {
- $('.ldap_config_state_indicator').text(t('user_ldap',
- 'Configuration incomplete'
- ));
- $('.ldap_config_state_indicator').removeClass('ldap_grey');
- $('.ldap_config_state_indicator_sign').removeClass('error');
- $('.ldap_config_state_indicator_sign').removeClass('success');
- }
- }
-};
-
-$(document).ready(function() {
- $('#ldapAdvancedAccordion').accordion({ heightStyle: 'content', animate: 'easeInOutCirc'});
- $('#ldapSettings').tabs({ beforeActivate: LdapWizard.onTabChange });
- $('.ldap_submit').button();
- $('.ldap_action_test_connection').button();
- $('#ldap_action_delete_configuration').button();
- LdapWizard.initMultiSelect($('#ldap_userfilter_groups'),
- 'ldap_userfilter_groups',
- t('user_ldap', 'Select groups'));
- 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'));
- 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);
- $('#toggleRawLoginFilter').click(LdapWizard.toggleRawLoginFilter);
- LdapConfiguration.refreshConfig();
- $('.ldap_action_continue').click(function(event) {
- event.preventDefault();
- LdapWizard.controlContinue();
- });
- $('.ldap_action_back').click(function(event) {
- event.preventDefault();
- LdapWizard.controlBack();
- });
- $('.ldap_action_test_connection').click(function(event){
- event.preventDefault();
- LdapConfiguration.testConfiguration(
- //onSuccess
- function(result) {
- OC.dialogs.alert(
- result.message,
- t('user_ldap', 'Connection test succeeded')
- );
- },
- //onError
- function(result) {
- OC.dialogs.alert(
- result.message,
- t('user_ldap', 'Connection test failed')
- );
- }
- );
- });
-
- $('#ldap_action_delete_configuration').click(function(event) {
- event.preventDefault();
- OC.dialogs.confirm(
- t('user_ldap', 'Do you really want to delete the current Server Configuration?'),
- t('user_ldap', 'Confirm Deletion'),
- function(deleteConfiguration) {
- if(deleteConfiguration) {
- LdapConfiguration.deleteConfiguration();
- }
- }
- );
- });
-
- $('.ldap_submit').click(function(event) {
- event.preventDefault();
- $.post(
- OC.filePath('user_ldap','ajax','setConfiguration.php'),
- $('#ldap').serialize(),
- function (result) {
- bgcolor = $('.ldap_submit').css('background');
- if (result.status === 'success') {
- //the dealing with colors is a but ugly, but the jQuery version in use has issues with rgba colors
- $('.ldap_submit').css('background', '#fff');
- $('.ldap_submit').effect('highlight', {'color':'#A8FA87'}, 5000, function() {
- $('.ldap_submit').css('background', bgcolor);
- });
- //update the Label in the config chooser
- caption = $('#ldap_serverconfig_chooser option:selected:first').text();
- pretext = '. Server: ';
- caption = caption.slice(0, caption.indexOf(pretext) + pretext.length);
- caption = caption + $('#ldap_host').val();
- $('#ldap_serverconfig_chooser option:selected:first').text(caption);
-
- } else {
- $('.ldap_submit').css('background', '#fff');
- $('.ldap_submit').effect('highlight', {'color':'#E97'}, 5000, function() {
- $('.ldap_submit').css('background', bgcolor);
- });
- }
- }
- );
- });
-
- $('#ldap_action_clear_user_mappings').click(function(event) {
- event.preventDefault();
- LdapConfiguration.clearMappings('user');
- });
-
- $('#ldap_action_clear_group_mappings').click(function(event) {
- event.preventDefault();
- LdapConfiguration.clearMappings('group');
- });
-
- $('#ldap_serverconfig_chooser').change(function(event) {
- value = $('#ldap_serverconfig_chooser option:selected:first').attr('value');
- if(value === 'NEW') {
- LdapConfiguration.addConfiguration(false);
- } else {
- LdapConfiguration.refreshConfig();
- }
- });
-
- expAdminCB = $('#ldap_experienced_admin');
- LdapWizard.admin = new ExperiencedAdmin(LdapWizard, expAdminCB.is(':checked'));
- expAdminCB.change(function() {
- LdapWizard.admin.setExperienced($(this).is(':checked'));
- });
-});
diff --git a/apps/user_ldap/js/wizard/configModel.js b/apps/user_ldap/js/wizard/configModel.js
new file mode 100644
index 00000000000..c3f1e85b592
--- /dev/null
+++ b/apps/user_ldap/js/wizard/configModel.js
@@ -0,0 +1,606 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc this class represents a server configuration. It communicates
+ * with the ownCloud server to ensure to always have the up to date LDAP
+ * configuration. It sends various events that views can listen to and
+ * provides methods so they can modify the configuration based upon user
+ * input. This model is also extended by so-called "detectors" who let the
+ * ownCloud server try to auto-detect settings and manipulate the
+ * configuration as well.
+ *
+ * @constructor
+ */
+ var ConfigModel = function() {};
+
+ ConfigModel.prototype = {
+ /** @constant {number} */
+ FILTER_MODE_ASSISTED: 0,
+ /** @constant {number} */
+ FILTER_MODE_RAW: 1,
+
+ /**
+ * initializes the instance. Always call it after creating the instance.
+ *
+ * @param {OCA.LDAP.Wizard.WizardDetectorQueue} detectorQueue
+ */
+ init: function (detectorQueue) {
+ /** @type {object} holds the configuration in key-value-pairs */
+ this.configuration = {};
+ /** @type {object} holds the subscribers that listen to the events */
+ this.subscribers = {};
+ /** @type {Array} holds registered detectors */
+ this.detectors = [];
+ /** @type {boolean} whether a configuration is currently loading */
+ this.loadingConfig = false;
+
+ if(detectorQueue instanceof OCA.LDAP.Wizard.WizardDetectorQueue) {
+ /** @type {OCA.LDAP.Wizard.WizardDetectorQueue} */
+ this.detectorQueue = detectorQueue;
+ }
+ },
+
+ /**
+ * loads a specified configuration
+ *
+ * @param {string} [configID] - the configuration id (or prefix)
+ */
+ load: function (configID) {
+ if(this.loadingConfig) {
+ return;
+ }
+ this._resetDetectorQueue();
+
+ this.configID = configID;
+ var url = OC.generateUrl('apps/user_ldap/ajax/getConfiguration.php');
+ var params = OC.buildQueryString({ldap_serverconfig_chooser: configID});
+ this.loadingConfig = true;
+ var model = this;
+ $.post(url, params, function (result) { model._processLoadConfig(model, result) });
+ },
+
+ /**
+ * creates a new LDAP configuration
+ *
+ * @param {boolean} [copyCurrent] - if true, the current configuration
+ * is copied, otherwise a blank one is created.
+ */
+ newConfig: function(copyCurrent) {
+ this._resetDetectorQueue();
+
+ var url = OC.generateUrl('apps/user_ldap/ajax/getNewServerConfigPrefix.php');
+ var params = {};
+ if(copyCurrent === true) {
+ params['copyConfig'] = this.configID;
+ }
+ params = OC.buildQueryString(params);
+ var model = this;
+ copyCurrent = _.isUndefined(copyCurrent) ? false : copyCurrent;
+ $.post(url, params, function (result) { model._processNewConfigPrefix(model, result, copyCurrent) });
+ },
+
+ /**
+ * deletes the current configuration. This method will not ask for
+ * confirmation, if desired it needs to be ensured by the caller.
+ *
+ * @param {string} [configID] - the configuration id (or prefix)
+ */
+ deleteConfig: function(configID) {
+ var url = OC.generateUrl('apps/user_ldap/ajax/deleteConfiguration.php');
+ var params = OC.buildQueryString({ldap_serverconfig_chooser: configID});
+ var model = this;
+ $.post(url, params, function (result) { model._processDeleteConfig(model, result, configID) });
+ },
+
+ /**
+ * @callback wizardCallBack
+ * @param {ConfigModel} [model]
+ * @param {OCA.LDAP.Wizard.WizardDetectorGeneric} [detector]
+ * @param {object} [result] - response from the ajax request
+ */
+
+ /**
+ * calls an AJAX endpoint at ownCloud. This method should be called by
+ * detectors only!
+ *
+ * @param {string} [params] - as return by OC.buildQueryString
+ * @param {wizardCallBack} [callback]
+ * @param {OCA.LDAP.Wizard.WizardDetectorGeneric} [detector]
+ * @returns {jqXHR}
+ */
+ callWizard: function(params, callback, detector) {
+ return this.callAjax('wizard.php', params, callback, detector);
+ },
+
+ /**
+ * calls an AJAX endpoint at ownCloud. This method should be called by
+ * detectors only!
+ *
+ * @param {string} destination - the desired end point
+ * @param {string} [params] - as return by OC.buildQueryString
+ * @param {wizardCallBack} [callback]
+ * @param {OCA.LDAP.Wizard.WizardDetectorGeneric} [detector]
+ * @returns {jqXHR}
+ */
+ callAjax: function(destination, params, callback, detector) {
+ var url = OC.generateUrl('apps/user_ldap/ajax/' + destination);
+ var model = this;
+ return $.post(url, params, function (result) {
+ callback(model, detector,result);
+ });
+ },
+
+ /**
+ * setRequested Event
+ *
+ * @event ConfigModel#setRequested
+ * @type{object} - empty
+ */
+
+ /**
+ * modifies a configuration key. If a provided configuration key does
+ * not exist or the provided value equals the current setting, false is
+ * returned. Otherwise ownCloud server will be called to save the new
+ * value, an event will notify when this is done. True is returned when
+ * the request is sent, however it does not mean whether saving was
+ * successful or not.
+ *
+ * This method is supposed to be called by views, after the user did a
+ * change which needs to be saved.
+ *
+ * @param {string} [key]
+ * @param {string|number} [value]
+ * @returns {boolean}
+ * @fires {ConfigModel#setRequested}
+ */
+ set: function(key, value) {
+ if(_.isUndefined(this.configuration[key])) {
+ console.warn('will not save undefined key: ' + key);
+ return false;
+ }
+ if(this.configuration[key] === value) {
+ return false;
+ }
+ this._broadcast('setRequested', {});
+ var url = OC.generateUrl('apps/user_ldap/ajax/wizard.php');
+ var objParams = {
+ ldap_serverconfig_chooser: this.configID,
+ action: 'save',
+ cfgkey: key,
+ cfgval: value
+ };
+ var strParams = OC.buildQueryString(objParams);
+ var model = this;
+ $.post(url, strParams, function(result) { model._processSetResult(model, result, objParams) });
+ return true;
+ },
+
+ /**
+ * configUpdated Event
+ *
+ * object property is a key-value-pair of the configuration key as index
+ * and its value.
+ *
+ * @event ConfigModel#configUpdated
+ * @type{object}
+ */
+
+ /**
+ * updates the model's configuration data. This should be called only,
+ * when a new configuration value was received from the ownCloud server.
+ * This is typically done by detectors, but never by views.
+ *
+ * Cancels with false if old and new values already match.
+ *
+ * @param {string} [key]
+ * @param {string} [value]
+ * @returns {boolean}
+ * @fires ConfigModel#configUpdated
+ */
+ update: function(key, value) {
+ if(this.configuration[key] === value) {
+ return false;
+ }
+ if(!_.isUndefined(this.configuration[key])) {
+ // don't write e.g. count values to the configuration
+ // they don't go as feature, yet
+ this.configuration[key] = value;
+ }
+ var configPart = {};
+ configPart[key] = value;
+ this._broadcast('configUpdated', configPart);
+ },
+
+ /**
+ * @typedef {object} FeaturePayload
+ * @property {string} feature
+ * @property {Array} data
+ */
+
+ /**
+ * informs about a detected LDAP "feature" (wider sense). For examples,
+ * the detected object classes for users or groups
+ *
+ * @param {FeaturePayload} payload
+ */
+ inform: function(payload) {
+ this._broadcast('receivedLdapFeature', payload);
+ },
+
+ /**
+ * @typedef {object} ErrorPayload
+ * @property {string} message
+ * @property {string} relatedKey
+ */
+
+ /**
+ * broadcasts an error message, if a wizard reply ended up in an error.
+ * To be called by detectors.
+ *
+ * @param {ErrorPayload} payload
+ */
+ gotServerError: function(payload) {
+ this._broadcast('serverError', payload);
+ },
+
+ /**
+ * detectionStarted Event
+ *
+ * @event ConfigModel#detectionStarted
+ * @type{string} - the target configuration key that is being
+ * auto-detected
+ */
+
+ /**
+ * lets the model broadcast the info that a detector starts to run
+ *
+ * supposed to be called by detectors only
+ *
+ * @param {string} [key]
+ * @fires ConfigModel#detectionStarted
+ */
+ notifyAboutDetectionStart: function(key) {
+ this._broadcast('detectionStarted', key);
+ },
+
+ /**
+ * detectionCompleted Event
+ *
+ * @event ConfigModel#detectionCompleted
+ * @type{string} - the target configuration key that was
+ * auto-detected
+ */
+
+ /**
+ * lets the model broadcast the info that a detector run was completed
+ *
+ * supposed to be called by detectors only
+ *
+ * @param {string} [key]
+ * @fires ConfigModel#detectionCompleted
+ */
+ notifyAboutDetectionCompletion: function(key) {
+ this._broadcast('detectionCompleted', key);
+ },
+
+ /**
+ * @callback listenerCallback
+ * @param {OCA.LDAP.Wizard.WizardTabGeneric|OCA.LDAP.Wizard.WizardView} [view]
+ * @param {object} [params]
+ */
+
+ /**
+ * registers a listener to an event
+ *
+ * the idea is that only views listen.
+ *
+ * @param {string} [name] - the event name
+ * @param {listenerCallback} [fn]
+ * @param {OCA.LDAP.Wizard.WizardTabGeneric|OCA.LDAP.Wizard.WizardView} [context]
+ */
+ on: function(name, fn, context) {
+ if(_.isUndefined(this.subscribers[name])) {
+ this.subscribers[name] = [];
+ }
+ this.subscribers[name].push({fn: fn, context: context});
+ },
+
+ /**
+ * starts a configuration test on the ownCloud server
+ */
+ requestConfigurationTest: function() {
+ var url = OC.generateUrl('apps/user_ldap/ajax/testConfiguration.php');
+ var params = OC.buildQueryString(this.configuration);
+ var model = this;
+ $.post(url, params, function(result) { model._processTestResult(model, result) });
+ //TODO: make sure only one test is running at a time
+ },
+
+ /**
+ * the view may request a call to the wizard, for instance to fetch
+ * object classes or groups
+ *
+ * @param {string} featureKey
+ * @param {Object} [additionalParams]
+ */
+ requestWizard: function(featureKey, additionalParams) {
+ var model = this;
+ var detectorCount = this.detectors.length;
+ var found = false;
+ for(var i = 0; i < detectorCount; i++) {
+ if(this.detectors[i].runsOnFeatureRequest(featureKey)) {
+ found = true;
+ (function (detector) {
+ model.detectorQueue.add(function() {
+ return detector.run(model, model.configID, additionalParams);
+ });
+ })(model.detectors[i]);
+ }
+ }
+ if(!found) {
+ console.warn('No detector found for feature ' + featureKey);
+ }
+ },
+
+ /**
+ * resets the detector queue
+ *
+ * @private
+ */
+ _resetDetectorQueue: function() {
+ if(!_.isUndefined(this.detectorQueue)) {
+ this.detectorQueue.reset();
+ }
+ },
+
+ /**
+ * detectors can be registered herewith
+ *
+ * @param {OCA.LDAP.Wizard.WizardDetectorGeneric} [detector]
+ */
+ registerDetector: function(detector) {
+ if(detector instanceof OCA.LDAP.Wizard.WizardDetectorGeneric) {
+ this.detectors.push(detector);
+ }
+ },
+
+ /**
+ * emits an event
+ *
+ * @param {string} [name] - the event name
+ * @param {*} [params]
+ * @private
+ */
+ _broadcast: function(name, params) {
+ if(_.isUndefined(this.subscribers[name])) {
+ return;
+ }
+ var subscribers = this.subscribers[name];
+ var subscriberCount = subscribers.length;
+ for(var i = 0; i < subscriberCount; i++) {
+ if(_.isUndefined(subscribers[i]['fn'])) {
+ console.warn('callback method is not defined. Event ' + name);
+ continue;
+ }
+ subscribers[i]['fn'](subscribers[i]['context'], params);
+ }
+ },
+
+ /**
+ * ConfigModel#configLoaded Event
+ *
+ * @event ConfigModel#configLoaded
+ * @type {object} - LDAP configuration as key-value-pairs
+ */
+
+ /**
+ * @typedef {object} ConfigLoadResponse
+ * @property {string} [status]
+ * @property {object} [configuration] - only present if status equals 'success'
+ */
+
+ /**
+ * processes the ajax response of a configuration load request
+ *
+ * @param {ConfigModel} [model]
+ * @param {ConfigLoadResponse} [result]
+ * @fires ConfigModel#configLoaded
+ * @private
+ */
+ _processLoadConfig: function(model, result) {
+ model.configuration = {};
+ if(result['status'] === 'success') {
+ $.each(result['configuration'], function(key, value) {
+ model.configuration[key] = value;
+ });
+ }
+ model.loadingConfig = false;
+ model._broadcast('configLoaded', model.configuration);
+ },
+
+ /**
+ * @typedef {object} ConfigSetPayload
+ * @property {boolean} [isSuccess]
+ * @property {string} [key]
+ * @property {string} [value]
+ * @property {string} [errorMessage]
+ */
+
+ /**
+ * ConfigModel#setCompleted Event
+ *
+ * @event ConfigModel#setCompleted
+ * @type {ConfigSetPayload}
+ */
+
+ /**
+ * @typedef {object} ConfigSetResponse
+ * @property {string} [status]
+ * @property {object} [message] - might be present only in error cases
+ */
+
+ /**
+ * processes the ajax response of a configuration key set request
+ *
+ * @param {ConfigModel} [model]
+ * @param {ConfigSetResponse} [result]
+ * @param {object} [params] - the original changeSet
+ * @fires ConfigModel#configLoaded
+ * @private
+ */
+ _processSetResult: function(model, result, params) {
+ var isSuccess = (result['status'] === 'success');
+ if(isSuccess) {
+ model.configuration[params.cfgkey] = params.cfgval;
+ }
+ var payload = {
+ isSuccess: isSuccess,
+ key: params.cfgkey,
+ value: model.configuration[params.cfgkey],
+ errorMessage: _.isUndefined(result['message']) ? '' : result['message']
+ };
+ model._broadcast('setCompleted', payload);
+
+ // let detectors run
+ // NOTE: detector's changes will not result in new _processSetResult
+ // calls, … in case they interfere it is because of this ;)
+ if(_.isUndefined(model.detectorQueue)) {
+ console.warn("DetectorQueue was not set, detectors will not be fired");
+ return;
+ }
+ var detectorCount = model.detectors.length;
+ for(var i = 0; i < detectorCount; i++) {
+ if(model.detectors[i].triggersOn(params.cfgkey)) {
+ (function (detector) {
+ model.detectorQueue.add(function() {
+ return detector.run(model, model.configID);
+ });
+ })(model.detectors[i]);
+ }
+ }
+ },
+
+ /**
+ * @typedef {object} ConfigTestPayload
+ * @property {boolean} [isSuccess]
+ */
+
+ /**
+ * ConfigModel#configurationTested Event
+ *
+ * @event ConfigModel#configurationTested
+ * @type {ConfigTestPayload}
+ */
+
+ /**
+ * @typedef {object} StatusResponse
+ * @property {string} [status]
+ */
+
+ /**
+ * processes the ajax response of a configuration test request
+ *
+ * @param {ConfigModel} [model]
+ * @param {StatusResponse} [result]
+ * @fires ConfigModel#configurationTested
+ * @private
+ */
+ _processTestResult: function(model, result) {
+ var payload = {
+ isSuccess: (result['status'] === 'success')
+ };
+ model._broadcast('configurationTested', payload);
+ },
+
+ /**
+ * @typedef {object} BasicConfigPayload
+ * @property {boolean} [isSuccess]
+ * @property {string} [configPrefix] - the new config ID
+ * @property {string} [errorMessage]
+ */
+
+ /**
+ * ConfigModel#newConfiguration Event
+ *
+ * @event ConfigModel#newConfiguration
+ * @type {BasicConfigPayload}
+ */
+
+ /**
+ * @typedef {object} NewConfigResponse
+ * @property {string} [status]
+ * @property {string} [configPrefix]
+ * @property {object} [defaults] - default configuration values
+ * @property {string} [message] - might only appear with status being
+ * not 'success'
+ */
+
+ /**
+ * processes the ajax response of a new configuration request
+ *
+ * @param {ConfigModel} [model]
+ * @param {NewConfigResponse} [result]
+ * @param {boolean} [copyCurrent]
+ * @fires ConfigModel#newConfiguration
+ * @fires ConfigModel#configLoaded
+ * @private
+ */
+ _processNewConfigPrefix: function(model, result, copyCurrent) {
+ var isSuccess = (result['status'] === 'success');
+ var payload = {
+ isSuccess: isSuccess,
+ configPrefix: result['configPrefix'],
+ errorMessage: _.isUndefined(result['message']) ? '' : result['message']
+ };
+ model._broadcast('newConfiguration', payload);
+
+ if(isSuccess) {
+ this.configID = result['configPrefix'];
+ if(!copyCurrent) {
+ model.configuration = {};
+ $.each(result['defaults'], function(key, value) {
+ model.configuration[key] = value;
+ });
+ // view / tabs need to update with new blank config
+ model._broadcast('configLoaded', model.configuration);
+ }
+ }
+ },
+
+ /**
+ * ConfigModel#deleteConfiguration Event
+ *
+ * @event ConfigModel#deleteConfiguration
+ * @type {BasicConfigPayload}
+ */
+
+ /**
+ * processes the ajax response of a delete configuration request
+ *
+ * @param {ConfigModel} [model]
+ * @param {StatusResponse} [result]
+ * @param {string} [configID]
+ * @fires ConfigModel#deleteConfiguration
+ * @private
+ */
+ _processDeleteConfig: function(model, result, configID) {
+ var isSuccess = (result['status'] === 'success');
+ var payload = {
+ isSuccess: isSuccess,
+ configPrefix: configID,
+ errorMessage: _.isUndefined(result['message']) ? '' : result['message']
+ };
+ model._broadcast('deleteConfiguration', payload);
+ }
+ };
+
+ OCA.LDAP.Wizard.ConfigModel = ConfigModel;
+})();
diff --git a/apps/user_ldap/js/wizard/controller.js b/apps/user_ldap/js/wizard/controller.js
new file mode 100644
index 00000000000..7c1f0d5d818
--- /dev/null
+++ b/apps/user_ldap/js/wizard/controller.js
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+OCA.LDAP = {};
+OCA.LDAP.Wizard = {};
+
+(function(){
+
+ /**
+ * @classdesc minimalistic controller that basically makes the view render
+ *
+ * @constructor
+ */
+ var WizardController = function() {};
+
+ WizardController.prototype = {
+ /**
+ * initializes the instance. Always call it after creating the instance.
+ */
+ init: function() {
+ this.view = false;
+ this.configModel = false;
+ },
+
+ /**
+ * sets the model instance
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} [model]
+ */
+ setModel: function(model) {
+ this.configModel = model;
+ },
+
+ /**
+ * sets the view instance
+ *
+ * @param {OCA.LDAP.Wizard.WizardView} [view]
+ */
+ setView: function(view) {
+ this.view = view;
+ },
+
+ /**
+ * makes the view render i.e. ready to be used
+ */
+ run: function() {
+ this.view.render();
+ }
+ };
+
+ OCA.LDAP.Wizard.Controller = WizardController;
+})();
diff --git a/apps/user_ldap/js/wizard/view.js b/apps/user_ldap/js/wizard/view.js
new file mode 100644
index 00000000000..8eb10c58017
--- /dev/null
+++ b/apps/user_ldap/js/wizard/view.js
@@ -0,0 +1,433 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc main view class. It takes care of tab-unrelated control
+ * elements (status bar, control buttons) and does or requests configuration
+ * checks. It also manages the separate tab views.
+ *
+ * @constructor
+ */
+ var WizardView = function() {};
+
+ WizardView.prototype = {
+ /** @constant {number} */
+ STATUS_ERROR: 0,
+ /** @constant {number} */
+ STATUS_INCOMPLETE: 1,
+ /** @constant {number} */
+ STATUS_SUCCESS: 2,
+
+ /**
+ * initializes the instance. Always call it after creating the instance.
+ */
+ init: function () {
+ this.tabs = {};
+ this.tabs.server = new OCA.LDAP.Wizard.WizardTabElementary();
+ this.$settings = $('#ldapSettings');
+ this.$saveSpinners = $('.ldap_saving');
+ this.saveProcesses = 0;
+ _.bindAll(this, 'onTabChange', 'onTestButtonClick');
+ },
+
+ /**
+ * applies click events to the forward and backword buttons
+ */
+ initControls: function() {
+ var view = this;
+ $('.ldap_action_continue').click(function(event) {
+ event.preventDefault();
+ view._controlContinue(view);
+ });
+
+ $('.ldap_action_back').click(function(event) {
+ event.preventDefault();
+ view._controlBack(view);
+ });
+
+ $('.ldap_action_test_connection').click(this.onTestButtonClick);
+ },
+
+ /**
+ * registers a tab
+ *
+ * @param {OCA.LDAP.Wizard.WizardTabGeneric} tabView
+ * @param {string} index
+ * @returns {boolean}
+ */
+ registerTab: function(tabView, index) {
+ if( _.isUndefined(this.tabs[index])
+ && tabView instanceof OCA.LDAP.Wizard.WizardTabGeneric
+ ) {
+ this.tabs[index] = tabView;
+ this.tabs[index].setModel(this.configModel);
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * checks certain config values for completeness and depending on them
+ * enables or disables non-elementary tabs.
+ */
+ basicStatusCheck: function(view) {
+ var host = view.configModel.configuration.ldap_host;
+ var port = view.configModel.configuration.ldap_port;
+ var base = view.configModel.configuration.ldap_base;
+ var agent = view.configModel.configuration.ldap_dn;
+ var pwd = view.configModel.configuration.ldap_agent_password;
+
+ if((host && port && base) && ((!agent && !pwd) || (agent && pwd))) {
+ view.enableTabs();
+ } else {
+ view.disableTabs();
+ }
+ },
+
+ /**
+ * if the configuration is sufficient the model is being request to
+ * perform a configuration test. Otherwise, the status indicator is
+ * being updated with the status "incomplete"
+ */
+ functionalityCheck: function() {
+ // this method should be called only if necessary, because it may
+ // cause an LDAP request!
+ var host = this.configModel.configuration.ldap_host;
+ var port = this.configModel.configuration.ldap_port;
+ var base = this.configModel.configuration.ldap_base;
+ var userFilter = this.configModel.configuration.ldap_userlist_filter;
+ var loginFilter = this.configModel.configuration.ldap_login_filter;
+
+ if(host && port && base && userFilter && loginFilter) {
+ this.configModel.requestConfigurationTest();
+ } else {
+ this._updateStatusIndicator(this.STATUS_INCOMPLETE);
+ }
+ },
+
+ /**
+ * will request a functionality check if one of the related configuration
+ * settings was changed.
+ *
+ * @param {ConfigSetPayload|Object} [changeSet]
+ */
+ considerFunctionalityCheck: function(changeSet) {
+ var testTriggers = [
+ 'ldap_host', 'ldap_port', 'ldap_dn', 'ldap_agent_password',
+ 'ldap_base', 'ldap_userlist_filter', 'ldap_login_filter'
+ ];
+ for(var key in changeSet) {
+ if($.inArray(key, testTriggers)) {
+ this.functionalityCheck();
+ return;
+ }
+ }
+ },
+
+ /**
+ * keeps number of running save processes and shows a spinner if
+ * necessary
+ *
+ * @param {WizardView} [view]
+ * @listens ConfigModel#setRequested
+ */
+ onSetRequested: function(view) {
+ view.saveProcesses += 1;
+ if(view.saveProcesses === 1) {
+ view.showSaveSpinner();
+ }
+ },
+
+ /**
+ * keeps number of running save processes and hides the spinner if
+ * necessary. Also triggers checks, to adjust tabs state and status bar.
+ *
+ * @param {WizardView} [view]
+ * @param {ConfigSetPayload} [result]
+ * @listens ConfigModel#setCompleted
+ */
+ onSetRequestDone: function(view, result) {
+ if(view.saveProcesses > 0) {
+ view.saveProcesses -= 1;
+ if(view.saveProcesses === 0) {
+ view.hideSaveSpinner();
+ }
+ }
+
+ view.basicStatusCheck(view);
+ var param = {};
+ param[result.key] = 1;
+ view.considerFunctionalityCheck(param);
+ },
+
+ /**
+ * updates the status indicator based on the configuration test result
+ *
+ * @param {WizardView} [view]
+ * @param {ConfigTestPayload} [result]
+ * @listens ConfigModel#configurationTested
+ */
+ onTestCompleted: function(view, result) {
+ if(result.isSuccess) {
+ view._updateStatusIndicator(view.STATUS_SUCCESS);
+ } else {
+ view._updateStatusIndicator(view.STATUS_ERROR);
+ }
+ },
+
+ /**
+ * triggers initial checks upon configuration loading to update status
+ * controls
+ *
+ * @param {WizardView} [view]
+ * @listens ConfigModel#configLoaded
+ */
+ onConfigLoaded: function(view) {
+ view.basicStatusCheck(view);
+ view.functionalityCheck();
+ },
+
+ /**
+ * reacts on attempts to switch to a different tab
+ *
+ * @param {object} event
+ * @param {object} ui
+ * @returns {boolean}
+ */
+ onTabChange: function(event, ui) {
+ if(this.saveProcesses > 0) {
+ return false;
+ }
+
+ var newTabID = ui.newTab[0].id;
+ if(newTabID === '#ldapWizard1') {
+ newTabID = 'server';
+ }
+ var oldTabID = ui.oldTab[0].id;
+ if(oldTabID === '#ldapWizard1') {
+ oldTabID = 'server';
+ }
+ if(!_.isUndefined(this.tabs[newTabID])) {
+ this.tabs[newTabID].isActive = true;
+ this.tabs[newTabID].onActivate();
+ } else {
+ console.warn('Unreferenced activated tab ' + newTabID);
+ }
+ if(!_.isUndefined(this.tabs[oldTabID])) {
+ this.tabs[oldTabID].isActive = false;
+ } else {
+ console.warn('Unreferenced left tab ' + oldTabID);
+ }
+ },
+
+ /**
+ * triggers checks upon configuration updates to keep status controls
+ * up to date
+ *
+ * @param {WizardView} [view]
+ * @param {object} [changeSet]
+ * @listens ConfigModel#configUpdated
+ */
+ onConfigUpdated: function(view, changeSet) {
+ view.basicStatusCheck(view);
+ view.considerFunctionalityCheck(changeSet);
+ },
+
+ /**
+ * requests a configuration test
+ */
+ onTestButtonClick: function() {
+ this.configModel.requestWizard('ldap_action_test_connection', this.configModel.configuration);
+ },
+
+ /**
+ * sets the model instance and registers event listeners
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} [configModel]
+ */
+ setModel: function(configModel) {
+ /** @type {OCA.LDAP.Wizard.ConfigModel} */
+ this.configModel = configModel;
+ for(var i in this.tabs) {
+ this.tabs[i].setModel(configModel);
+ }
+
+ // make sure this is definitely run after tabs did their work, order is important here
+ // for now this works, because tabs are supposed to register their listeners in their
+ // setModel() method.
+ // alternative: make Elementary Tab a Publisher as well.
+ this.configModel.on('configLoaded', this.onConfigLoaded, this);
+ this.configModel.on('configUpdated', this.onConfigUpdated, this);
+ this.configModel.on('setRequested', this.onSetRequested, this);
+ this.configModel.on('setCompleted', this.onSetRequestDone, this);
+ this.configModel.on('configurationTested', this.onTestCompleted, this);
+ },
+
+ /**
+ * enables tab and navigation buttons
+ */
+ enableTabs: function() {
+ //do not use this function directly, use basicStatusCheck instead.
+ if(this.saveProcesses === 0) {
+ $('.ldap_action_continue').removeAttr('disabled');
+ $('.ldap_action_back').removeAttr('disabled');
+ this.$settings.tabs('option', 'disabled', []);
+ }
+ },
+
+ /**
+ * disables tab and navigation buttons
+ */
+ disableTabs: function() {
+ $('.ldap_action_continue').attr('disabled', 'disabled');
+ $('.ldap_action_back').attr('disabled', 'disabled');
+ this.$settings.tabs('option', 'disabled', [1, 2, 3, 4, 5]);
+ },
+
+ /**
+ * shows a save spinner
+ */
+ showSaveSpinner: function() {
+ this.$saveSpinners.removeClass('hidden');
+ $('#ldap *').addClass('save-cursor');
+ },
+
+ /**
+ * hides the save spinner
+ */
+ hideSaveSpinner: function() {
+ this.$saveSpinners.addClass('hidden');
+ $('#ldap *').removeClass('save-cursor');
+ },
+
+ /**
+ * performs a config load request to the model
+ *
+ * @param {string} [configID]
+ * @private
+ */
+ _requestConfig: function(configID) {
+ this.configModel.load(configID);
+ },
+
+ /**
+ * bootstraps the visual appearance and event listeners, as well as the
+ * first config
+ */
+ render: function () {
+ $('#ldapAdvancedAccordion').accordion({ heightStyle: 'content', animate: 'easeInOutCirc'});
+ this.$settings.tabs({});
+ $('.ldap_submit').button();
+ $('.ldap_action_test_connection').button();
+ $('#ldapSettings').tabs({ beforeActivate: this.onTabChange });
+
+ this.initControls();
+ this.disableTabs();
+
+ this._requestConfig(this.tabs.server.getConfigID());
+ },
+
+ /**
+ * updates the status indicator / bar
+ *
+ * @param {number} [state]
+ * @private
+ */
+ _updateStatusIndicator: function(state) {
+ var $indicator = $('.ldap_config_state_indicator');
+ var $indicatorLight = $('.ldap_config_state_indicator_sign');
+
+ switch(state) {
+ case this.STATUS_ERROR:
+ $indicator.text(t('user_ldap',
+ 'Configuration incorrect'
+ ));
+ $indicator.removeClass('ldap_grey');
+ $indicatorLight.addClass('error');
+ $indicatorLight.removeClass('success');
+ break;
+ case this.STATUS_INCOMPLETE:
+ $indicator.text(t('user_ldap',
+ 'Configuration incomplete'
+ ));
+ $indicator.removeClass('ldap_grey');
+ $indicatorLight.removeClass('error');
+ $indicatorLight.removeClass('success');
+ break;
+ case this.STATUS_SUCCESS:
+ $indicator.text(t('user_ldap', 'Configuration OK'));
+ $indicator.addClass('ldap_grey');
+ $indicatorLight.removeClass('error');
+ $indicatorLight.addClass('success');
+ if(!this.tabs.server.isActive) {
+ this.configModel.set('ldap_configuration_active', 1);
+ }
+ break;
+ }
+ },
+
+ /**
+ * handles a click on the Back button
+ *
+ * @param {WizardView} [view]
+ * @private
+ */
+ _controlBack: function(view) {
+ var curTabIndex = view.$settings.tabs('option', 'active');
+ if(curTabIndex == 0) {
+ return;
+ }
+ view.$settings.tabs('option', 'active', curTabIndex - 1);
+ view._controlUpdate(curTabIndex - 1);
+ },
+
+ /**
+ * handles a click on the Continue button
+ *
+ * @param {WizardView} [view]
+ * @private
+ */
+ _controlContinue: function(view) {
+ var curTabIndex = view.$settings.tabs('option', 'active');
+ if(curTabIndex == 3) {
+ return;
+ }
+ view.$settings.tabs('option', 'active', 1 + curTabIndex);
+ view._controlUpdate(curTabIndex + 1);
+ },
+
+ /**
+ * updates the controls (navigation buttons)
+ *
+ * @param {number} [nextTabIndex] - index of the tab being switched to
+ * @private
+ */
+ _controlUpdate: function(nextTabIndex) {
+ if(nextTabIndex == 0) {
+ $('.ldap_action_back').addClass('invisible');
+ $('.ldap_action_continue').removeClass('invisible');
+ } else
+ if(nextTabIndex == 1) {
+ $('.ldap_action_back').removeClass('invisible');
+ $('.ldap_action_continue').removeClass('invisible');
+ } else
+ if(nextTabIndex == 2) {
+ $('.ldap_action_continue').removeClass('invisible');
+ $('.ldap_action_back').removeClass('invisible');
+ } else
+ if(nextTabIndex == 3) {
+ $('.ldap_action_back').removeClass('invisible');
+ $('.ldap_action_continue').addClass('invisible');
+ }
+ }
+ };
+
+ OCA.LDAP.Wizard.WizardView = WizardView;
+})();
diff --git a/apps/user_ldap/js/wizard/wizard.js b/apps/user_ldap/js/wizard/wizard.js
new file mode 100644
index 00000000000..faa9de918a4
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizard.js
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+
+
+/**
+ * initializes the wizard and related components and kicks it off.
+ */
+
+(function() {
+ var Wizard = function() {
+ var detectorQueue = new OCA.LDAP.Wizard.WizardDetectorQueue();
+ detectorQueue.init();
+
+ var detectors = [];
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorPort());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorBaseDN());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorEmailAttribute());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorUserDisplayNameAttribute());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorUserGroupAssociation());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorUserObjectClasses());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorGroupObjectClasses());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorGroupsForUsers());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorGroupsForGroups());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorFilterUser());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorFilterLogin());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorFilterGroup());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorUserCount());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorGroupCount());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorAvailableAttributes());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorTestLoginName());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorTestBaseDN());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorTestConfiguration());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorClearUserMappings());
+ detectors.push(new OCA.LDAP.Wizard.WizardDetectorClearGroupMappings());
+
+ var model = new OCA.LDAP.Wizard.ConfigModel();
+ model.init(detectorQueue);
+ // NOTE: order of detectors may play a role
+ // for example, BaseDN detector needs the port. The port is typically found
+ // by the Port Detector. If BaseDN detector was run first, it will not have
+ // all necessary information. Only after Port Detector was executed…
+ for (var i = 0; i <= detectors.length; i++) {
+ model.registerDetector(detectors[i]);
+ }
+
+ var filterOnTypeFactory = new OCA.LDAP.Wizard.FilterOnTypeFactory();
+
+ var tabs = [];
+ tabs.push(new OCA.LDAP.Wizard.WizardTabUserFilter(filterOnTypeFactory));
+ tabs.push(new OCA.LDAP.Wizard.WizardTabLoginFilter());
+ tabs.push(new OCA.LDAP.Wizard.WizardTabGroupFilter(filterOnTypeFactory));
+ tabs.push(new OCA.LDAP.Wizard.WizardTabAdvanced());
+ tabs.push(new OCA.LDAP.Wizard.WizardTabExpert());
+
+ var view = new OCA.LDAP.Wizard.WizardView(model);
+ view.init();
+ view.setModel(model);
+ for (var j = 0; j <= tabs.length; j++) {
+ view.registerTab(tabs[j], '#ldapWizard' + (j + 2));
+ }
+
+ var controller = new OCA.LDAP.Wizard.Controller();
+ controller.init();
+ controller.setView(view);
+ controller.setModel(model);
+ controller.run();
+ }
+
+ OCA.LDAP.Wizard.Wizard = Wizard;
+})();
+
+$(document).ready(function() {
+ new OCA.LDAP.Wizard.Wizard();
+});
diff --git a/apps/user_ldap/js/wizard/wizardDetectorAvailableAttributes.js b/apps/user_ldap/js/wizard/wizardDetectorAvailableAttributes.js
new file mode 100644
index 00000000000..f0272351749
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorAvailableAttributes.js
@@ -0,0 +1,59 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc an Attributes Detector. It executes the auto-detection of
+ * available attributes by the ownCloud server, if requirements are met.
+ *
+ * @constructor
+ */
+ var WizardDetectorAvailableAttributes = OCA.LDAP.Wizard.WizardDetectorGeneric.subClass({
+ /** @inheritdoc */
+ init: function() {
+ // given, it is not a configuration key
+ this.setTargetKey('ldap_loginfilter_attributes');
+ this.runsOnRequest = true;
+ },
+
+ /**
+ * runs the detector, if port is not set.
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} model
+ * @param {string} configID - the configuration prefix
+ * @returns {boolean|jqXHR}
+ * @abstract
+ */
+ run: function(model, configID) {
+ model.notifyAboutDetectionStart(this.getTargetKey());
+ var params = OC.buildQueryString({
+ action: 'determineAttributes',
+ ldap_serverconfig_chooser: configID
+ });
+ return model.callWizard(params, this.processResult, this);
+ },
+
+ /**
+ * @inheritdoc
+ */
+ processResult: function(model, detector, result) {
+ if(result.status === 'success') {
+ var payload = {
+ feature: 'AvailableAttributes',
+ data: result.options[detector.getTargetKey()]
+ };
+ model.inform(payload);
+ }
+ this._super(model, detector, result);
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorAvailableAttributes = WizardDetectorAvailableAttributes;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorBaseDN.js b/apps/user_ldap/js/wizard/wizardDetectorBaseDN.js
new file mode 100644
index 00000000000..70b9923e58d
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorBaseDN.js
@@ -0,0 +1,52 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc a Base DN Detector. It executes the auto-detection of the base
+ * DN by the ownCloud server, if requirements are met.
+ *
+ * @constructor
+ */
+ var WizardDetectorBaseDN = OCA.LDAP.Wizard.WizardDetectorGeneric.subClass({
+ /** @inheritdoc */
+ init: function() {
+ this.setTargetKey('ldap_base');
+ this.runsOnRequest = true;
+ },
+
+ /**
+ * runs the detector, if specified configuration settings are set and
+ * base DN is not set.
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} model
+ * @param {string} configID - the configuration prefix
+ * @returns {boolean|jqXHR}
+ * @abstract
+ */
+ run: function(model, configID) {
+ if( !model.configuration['ldap_host']
+ || !model.configuration['ldap_port']
+
+ )
+ {
+ return false;
+ }
+ model.notifyAboutDetectionStart(this.getTargetKey());
+ var params = OC.buildQueryString({
+ action: 'guessBaseDN',
+ ldap_serverconfig_chooser: configID
+ });
+ return model.callWizard(params, this.processResult, this);
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorBaseDN = WizardDetectorBaseDN;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorClearGroupMappings.js b/apps/user_ldap/js/wizard/wizardDetectorClearGroupMappings.js
new file mode 100644
index 00000000000..c6ef0a9cab1
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorClearGroupMappings.js
@@ -0,0 +1,30 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc requests clearing of user mappings
+ *
+ * @constructor
+ */
+ var WizardDetectorClearGroupMappings = OCA.LDAP.Wizard.WizardDetectorTestAbstract.subClass({
+ /** @inheritdoc */
+ init: function() {
+ // given, it is not a configuration key
+ this.setTargetKey('ldap_action_clear_group_mappings');
+ this.testName = 'ClearMappings';
+ this.isLegacy = true;
+ this.legacyDestination = 'clearMappings.php';
+ this.runsOnRequest = true;
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorClearGroupMappings = WizardDetectorClearGroupMappings;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorClearUserMappings.js b/apps/user_ldap/js/wizard/wizardDetectorClearUserMappings.js
new file mode 100644
index 00000000000..0e4811b39ea
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorClearUserMappings.js
@@ -0,0 +1,30 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc requests clearing of user mappings
+ *
+ * @constructor
+ */
+ var WizardDetectorClearUserMappings = OCA.LDAP.Wizard.WizardDetectorTestAbstract.subClass({
+ /** @inheritdoc */
+ init: function() {
+ // given, it is not a configuration key
+ this.setTargetKey('ldap_action_clear_user_mappings');
+ this.testName = 'ClearMappings';
+ this.isLegacy = true;
+ this.legacyDestination = 'clearMappings.php';
+ this.runsOnRequest = true;
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorClearUserMappings = WizardDetectorClearUserMappings;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorEmailAttribute.js b/apps/user_ldap/js/wizard/wizardDetectorEmailAttribute.js
new file mode 100644
index 00000000000..5f177734681
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorEmailAttribute.js
@@ -0,0 +1,38 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc let's the wizard backend count the available users
+ *
+ * @constructor
+ */
+ var WizardDetectorEmailAttribute = OCA.LDAP.Wizard.WizardDetectorFilterSimpleRequestAbstract.subClass({
+ init: function() {
+ this.setTargetKey('ldap_user_count');
+ this.wizardMethod = 'detectEmailAttribute';
+ this.runsOnRequest = true;
+ },
+
+ /**
+ * @inheritdoc
+ */
+ run: function(model, configID) {
+ if(model.configuration.ldap_email_attr) {
+ // a value is already set. Don't overwrite and don't ask LDAP
+ // without reason.
+ return false;
+ }
+ this._super(model, configID);
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorEmailAttribute = WizardDetectorEmailAttribute;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorFeatureAbstract.js b/apps/user_ldap/js/wizard/wizardDetectorFeatureAbstract.js
new file mode 100644
index 00000000000..e025d8d6242
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorFeatureAbstract.js
@@ -0,0 +1,52 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc abstract detector for detecting groups and object classes
+ *
+ * @constructor
+ */
+ var WizardDetectorFeatureAbstract = OCA.LDAP.Wizard.WizardDetectorGeneric.subClass({
+ /**
+ * runs the detector, if port is not set.
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} model
+ * @param {string} configID - the configuration prefix
+ * @returns {boolean|jqXHR}
+ * @abstract
+ */
+ run: function(model, configID) {
+ model.notifyAboutDetectionStart(this.getTargetKey());
+ var params = OC.buildQueryString({
+ action: this.wizardMethod,
+ ldap_serverconfig_chooser: configID
+ });
+ return model.callWizard(params, this.processResult, this);
+ },
+
+ /**
+ * @inheritdoc
+ */
+ processResult: function(model, detector, result) {
+ if(result.status === 'success') {
+ var payload = {
+ feature: detector.featureName,
+ data: result.options[detector.getTargetKey()]
+ };
+ model.inform(payload);
+ }
+
+ this._super(model, detector, result);
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorFeatureAbstract = WizardDetectorFeatureAbstract;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorFilterGroup.js b/apps/user_ldap/js/wizard/wizardDetectorFilterGroup.js
new file mode 100644
index 00000000000..cca889839e4
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorFilterGroup.js
@@ -0,0 +1,31 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc a Port Detector. It executes the auto-detection of the port
+ * by the ownCloud server, if requirements are met.
+ *
+ * @constructor
+ */
+ var WizardDetectorFilterGroup = OCA.LDAP.Wizard.WizardDetectorFilterSimpleRequestAbstract.subClass({
+ init: function() {
+ this.setTrigger([
+ 'ldap_groupfilter_groups',
+ 'ldap_groupfilter_objectclass'
+ ]);
+ this.setTargetKey('ldap_group_filter');
+
+ this.wizardMethod = 'getGroupFilter';
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorFilterGroup = WizardDetectorFilterGroup;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorFilterLogin.js b/apps/user_ldap/js/wizard/wizardDetectorFilterLogin.js
new file mode 100644
index 00000000000..310f261e05e
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorFilterLogin.js
@@ -0,0 +1,32 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc a Port Detector. It executes the auto-detection of the port
+ * by the ownCloud server, if requirements are met.
+ *
+ * @constructor
+ */
+ var WizardDetectorFilterLogin = OCA.LDAP.Wizard.WizardDetectorFilterSimpleRequestAbstract.subClass({
+ init: function() {
+ this.setTrigger([
+ 'ldap_loginfilter_username',
+ 'ldap_loginfilter_email',
+ 'ldap_loginfilter_attributes'
+ ]);
+ this.setTargetKey('ldap_login_filter');
+
+ this.wizardMethod = 'getUserLoginFilter';
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorFilterLogin = WizardDetectorFilterLogin;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorFilterUser.js b/apps/user_ldap/js/wizard/wizardDetectorFilterUser.js
new file mode 100644
index 00000000000..63dff4e2985
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorFilterUser.js
@@ -0,0 +1,31 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc a Port Detector. It executes the auto-detection of the port
+ * by the ownCloud server, if requirements are met.
+ *
+ * @constructor
+ */
+ var WizardDetectorFilterUser = OCA.LDAP.Wizard.WizardDetectorFilterSimpleRequestAbstract.subClass({
+ init: function() {
+ this.setTrigger([
+ 'ldap_userfilter_groups',
+ 'ldap_userfilter_objectclass'
+ ]);
+ this.setTargetKey('ldap_userlist_filter');
+
+ this.wizardMethod = 'getUserListFilter';
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorFilterUser = WizardDetectorFilterUser;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorGeneric.js b/apps/user_ldap/js/wizard/wizardDetectorGeneric.js
new file mode 100644
index 00000000000..fd80018943e
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorGeneric.js
@@ -0,0 +1,117 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+ /**
+ * @classdesc a generic (abstract) Detector template. A Detector's task is
+ * to kick off server side detection of certain LDAP features. It is invoked
+ * when changes to specified configuration keys happen.
+ *
+ * @constructor
+ */
+ var WizardDetectorGeneric = OCA.LDAP.Wizard.WizardObject.subClass({
+ /**
+ * initializes the instance. Always call it after creating the instance.
+ */
+ init: function() {
+ this.setTrigger([]);
+ this.targetKey = '';
+ this.runsOnRequest = false;
+ },
+
+ /**
+ * sets the configuration keys the detector is listening on
+ *
+ * @param {string[]} triggers
+ */
+ setTrigger: function(triggers) {
+ this.triggers = triggers;
+ },
+
+ /**
+ * tests whether the detector is triggered by the provided key
+ *
+ * @param {string} key
+ * @returns {boolean}
+ */
+ triggersOn: function(key) {
+ return ($.inArray(key, this.triggers) >= 0);
+ },
+
+ /**
+ * whether the detector runs on explicit request
+ *
+ * @param {string} key
+ * @returns {boolean}
+ */
+ runsOnFeatureRequest: function(key) {
+ return !!(this.runsOnRequest && this.targetKey === key);
+ },
+
+ /**
+ * sets the configuration key the detector is attempting to auto-detect
+ *
+ * @param {string} key
+ */
+ setTargetKey: function(key) {
+ this.targetKey = key;
+ },
+
+ /**
+ * returns the configuration key the detector is attempting to
+ * auto-detect
+ */
+ getTargetKey: function() {
+ return this.targetKey;
+ },
+
+ /**
+ * runs the detector. This method is supposed to be implemented by the
+ * concrete detector.
+ *
+ * Must return false if the detector decides not to run.
+ * Must return a jqXHR object otherwise, which is provided by the
+ * model's callWizard()
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} model
+ * @param {string} configID - the configuration prefix
+ * @returns {boolean|jqXHR}
+ * @abstract
+ */
+ run: function(model, configID) {
+ // to be implemented by subClass
+ return false;
+ },
+
+ /**
+ * processes the result of the ownCloud server
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} model
+ * @param {WizardDetectorGeneric} detector
+ * @param {object} result
+ */
+ processResult: function(model, detector, result) {
+ model['notifyAboutDetectionCompletion'](detector.getTargetKey());
+ if(result.status === 'success') {
+ for (var id in result.changes) {
+ // update and not set method, as values are already stored
+ model['update'](id, result.changes[id]);
+ }
+ } else {
+ var payload = { relatedKey: detector.targetKey };
+ if(!_.isUndefined(result.message)) {
+ payload.message = result.message;
+ }
+ model.gotServerError(payload);
+ }
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorGeneric = WizardDetectorGeneric;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorGroupCount.js b/apps/user_ldap/js/wizard/wizardDetectorGroupCount.js
new file mode 100644
index 00000000000..12d7df7514b
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorGroupCount.js
@@ -0,0 +1,27 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc a Port Detector. It executes the auto-detection of the port
+ * by the ownCloud server, if requirements are met.
+ *
+ * @constructor
+ */
+ var WizardDetectorGroupCount = OCA.LDAP.Wizard.WizardDetectorFilterSimpleRequestAbstract.subClass({
+ init: function() {
+ this.setTargetKey('ldap_group_count');
+ this.wizardMethod = 'countGroups';
+ this.runsOnRequest = true;
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorGroupCount = WizardDetectorGroupCount;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorGroupObjectClasses.js b/apps/user_ldap/js/wizard/wizardDetectorGroupObjectClasses.js
new file mode 100644
index 00000000000..6d6048b7986
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorGroupObjectClasses.js
@@ -0,0 +1,29 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc discovers object classes for the groups tab
+ *
+ * @constructor
+ */
+ var WizardDetectorGroupObjectClasses = OCA.LDAP.Wizard.WizardDetectorFeatureAbstract.subClass({
+ /** @inheritdoc */
+ init: function() {
+ // given, it is not a configuration key
+ this.setTargetKey('ldap_groupfilter_objectclass');
+ this.wizardMethod = 'determineGroupObjectClasses';
+ this.featureName = 'GroupObjectClasses';
+ this.runsOnRequest = true;
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorGroupObjectClasses = WizardDetectorGroupObjectClasses;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorGroupsForGroups.js b/apps/user_ldap/js/wizard/wizardDetectorGroupsForGroups.js
new file mode 100644
index 00000000000..fbb3f02e10a
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorGroupsForGroups.js
@@ -0,0 +1,29 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc detects groups for the groups tab
+ *
+ * @constructor
+ */
+ var WizardDetectorGroupsForGroups = OCA.LDAP.Wizard.WizardDetectorFeatureAbstract.subClass({
+ /** @inheritdoc */
+ init: function() {
+ // given, it is not a configuration key
+ this.setTargetKey('ldap_groupfilter_groups');
+ this.wizardMethod = 'determineGroupsForGroups';
+ this.featureName = 'GroupsForGroups';
+ this.runsOnRequest = true;
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorGroupsForGroups = WizardDetectorGroupsForGroups;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorGroupsForUsers.js b/apps/user_ldap/js/wizard/wizardDetectorGroupsForUsers.js
new file mode 100644
index 00000000000..fe67854c794
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorGroupsForUsers.js
@@ -0,0 +1,29 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc detects groups for the users tab
+ *
+ * @constructor
+ */
+ var WizardDetectorGroupsForUsers = OCA.LDAP.Wizard.WizardDetectorFeatureAbstract.subClass({
+ /** @inheritdoc */
+ init: function() {
+ // given, it is not a configuration key
+ this.setTargetKey('ldap_userfilter_groups');
+ this.wizardMethod = 'determineGroupsForUsers';
+ this.featureName = 'GroupsForUsers';
+ this.runsOnRequest = true;
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorGroupsForUsers = WizardDetectorGroupsForUsers;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorPort.js b/apps/user_ldap/js/wizard/wizardDetectorPort.js
new file mode 100644
index 00000000000..ba075189667
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorPort.js
@@ -0,0 +1,44 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc a Port Detector. It executes the auto-detection of the port
+ * by the ownCloud server, if requirements are met.
+ *
+ * @constructor
+ */
+ var WizardDetectorPort = OCA.LDAP.Wizard.WizardDetectorGeneric.subClass({
+ /** @inheritdoc */
+ init: function() {
+ this.setTargetKey('ldap_port');
+ this.runsOnRequest = true;
+ },
+
+ /**
+ * runs the detector, if port is not set.
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} model
+ * @param {string} configID - the configuration prefix
+ * @returns {boolean|jqXHR}
+ * @abstract
+ */
+ run: function(model, configID) {
+ model.notifyAboutDetectionStart('ldap_port');
+ var params = OC.buildQueryString({
+ action: 'guessPortAndTLS',
+ ldap_serverconfig_chooser: configID
+ });
+ return model.callWizard(params, this.processResult, this);
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorPort = WizardDetectorPort;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorQueue.js b/apps/user_ldap/js/wizard/wizardDetectorQueue.js
new file mode 100644
index 00000000000..448dfc18036
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorQueue.js
@@ -0,0 +1,89 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+ /**
+ * @classdesc only run detector is allowed to run at a time. Basically
+ * because we cannot have parallel LDAP connections per session. This
+ * queue is takes care of running all the detectors one after the other.
+ *
+ * @constructor
+ */
+ var WizardDetectorQueue = OCA.LDAP.Wizard.WizardObject.subClass({
+ /**
+ * initializes the instance. Always call it after creating the instance.
+ */
+ init: function() {
+ this.queue = [];
+ this.isRunning = false;
+ },
+
+ /**
+ * empties the queue and cancels a possibly running request
+ */
+ reset: function() {
+ this.queue = [];
+ if(!_.isUndefined(this.runningRequest)) {
+ this.runningRequest.abort();
+ delete this.runningRequest;
+ }
+ this.isRunning = false;
+ },
+
+ /**
+ * a parameter-free callback that eventually executes the run method of
+ * the detector.
+ *
+ * @callback detectorCallBack
+ * @see OCA.LDAP.Wizard.ConfigModel._processSetResult
+ */
+
+ /**
+ * adds a detector to the queue and attempts to trigger to run the
+ * next job, because it might be the first.
+ *
+ * @param {detectorCallBack} callback
+ */
+ add: function(callback) {
+ this.queue.push(callback);
+ this.next();
+ },
+
+ /**
+ * Executes the next detector if none is running. This method is also
+ * automatically invoked after a detector finished.
+ */
+ next: function() {
+ if(this.isRunning === true || this.queue.length === 0) {
+ return;
+ }
+
+ this.isRunning = true;
+ var callback = this.queue.shift();
+ var request = callback();
+
+ // we receive either false or a jqXHR object
+ // false in case the detector decided against executing
+ if(request === false) {
+ this.isRunning = false;
+ this.next();
+ return;
+ }
+ this.runningRequest = request;
+
+ var detectorQueue = this;
+ $.when(request).then(function() {
+ detectorQueue.isRunning = false;
+ detectorQueue.next();
+ });
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorQueue = WizardDetectorQueue;
+})(); \ No newline at end of file
diff --git a/apps/user_ldap/js/wizard/wizardDetectorSimpleRequestAbstract.js b/apps/user_ldap/js/wizard/wizardDetectorSimpleRequestAbstract.js
new file mode 100644
index 00000000000..37e41f42a64
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorSimpleRequestAbstract.js
@@ -0,0 +1,44 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc a Port Detector. It executes the auto-detection of the port
+ * by the ownCloud server, if requirements are met.
+ *
+ * @constructor
+ */
+ var WizardDetectorFilterSimpleRequestAbstract = OCA.LDAP.Wizard.WizardDetectorGeneric.subClass({
+ runsOnRequest: true,
+
+ /**
+ * runs the detector, if port is not set.
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} model
+ * @param {string} configID - the configuration prefix
+ * @returns {boolean|jqXHR}
+ * @abstract
+ */
+ run: function(model, configID) {
+ if(_.isUndefined(this.wizardMethod)) {
+ console.warn('wizardMethod not set! ' + this.constructor);
+ return false;
+ }
+ model.notifyAboutDetectionStart(this.targetKey);
+ var params = OC.buildQueryString({
+ action: this.wizardMethod,
+ ldap_serverconfig_chooser: configID
+ });
+ return model.callWizard(params, this.processResult, this);
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorFilterSimpleRequestAbstract = WizardDetectorFilterSimpleRequestAbstract;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorTestAbstract.js b/apps/user_ldap/js/wizard/wizardDetectorTestAbstract.js
new file mode 100644
index 00000000000..df0b0a2200a
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorTestAbstract.js
@@ -0,0 +1,63 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc a Port Detector. It executes the auto-detection of the port
+ * by the ownCloud server, if requirements are met.
+ *
+ * @constructor
+ */
+ var WizardDetectorTestAbstract = OCA.LDAP.Wizard.WizardDetectorGeneric.subClass({
+ isLegacy: false,
+
+ /**
+ * runs the test
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} model
+ * @param {string} configID - the configuration prefix
+ * @param {Object} params - additional parameters needed to send to the
+ * wizard
+ * @returns {boolean|jqXHR}
+ * @abstract
+ */
+ run: function(model, configID, params) {
+ if(_.isUndefined(this.wizardMethod) && !this.isLegacy) {
+ console.warn('wizardMethod not set! ' + this.constructor);
+ return false;
+ }
+ model.notifyAboutDetectionStart(this.getTargetKey());
+ params = params || {};
+ params = OC.buildQueryString($.extend({
+ action: this.wizardMethod,
+ ldap_serverconfig_chooser: configID
+ }, params));
+ if(!this.isLegacy) {
+ return model.callWizard(params, this.processResult, this);
+ } else {
+ return model.callAjax(this.legacyDestination, params, this.processResult, this);
+ }
+ },
+
+ /**
+ * @inheritdoc
+ */
+ processResult: function(model, detector, result) {
+ model['notifyAboutDetectionCompletion'](detector.getTargetKey());
+ var payload = {
+ feature: detector.testName,
+ data: result
+ };
+ model.inform(payload);
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorTestAbstract = WizardDetectorTestAbstract;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorTestBaseDN.js b/apps/user_ldap/js/wizard/wizardDetectorTestBaseDN.js
new file mode 100644
index 00000000000..52848819bd8
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorTestBaseDN.js
@@ -0,0 +1,29 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc Tests, how many objects reside in the given base DN(s)
+ *
+ * @constructor
+ */
+ var WizardDetectorTestBaseDN = OCA.LDAP.Wizard.WizardDetectorTestAbstract.subClass({
+ /** @inheritdoc */
+ init: function() {
+ // given, it is not a configuration key
+ this.setTargetKey('ldap_test_base');
+ this.testName = 'TestBaseDN';
+ this.wizardMethod = 'countInBaseDN';
+ this.runsOnRequest = true;
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorTestBaseDN = WizardDetectorTestBaseDN;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorTestConfiguration.js b/apps/user_ldap/js/wizard/wizardDetectorTestConfiguration.js
new file mode 100644
index 00000000000..1308c182909
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorTestConfiguration.js
@@ -0,0 +1,31 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc a Port Detector. It executes the auto-detection of the port
+ * by the ownCloud server, if requirements are met.
+ *
+ * @constructor
+ */
+ var WizardDetectorTestConfiguration = OCA.LDAP.Wizard.WizardDetectorTestAbstract.subClass({
+ /** @inheritdoc */
+ init: function() {
+ // given, it is not a configuration key
+ this.setTargetKey('ldap_action_test_connection');
+ this.testName = 'TestConfiguration';
+ this.isLegacy = true;
+ this.legacyDestination = 'testConfiguration.php';
+ this.runsOnRequest = true;
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorTestConfiguration = WizardDetectorTestConfiguration;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorTestLoginName.js b/apps/user_ldap/js/wizard/wizardDetectorTestLoginName.js
new file mode 100644
index 00000000000..cf992df43b3
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorTestLoginName.js
@@ -0,0 +1,30 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc a Port Detector. It executes the auto-detection of the port
+ * by the ownCloud server, if requirements are met.
+ *
+ * @constructor
+ */
+ var WizardDetectorTestLoginName = OCA.LDAP.Wizard.WizardDetectorTestAbstract.subClass({
+ /** @inheritdoc */
+ init: function() {
+ // given, it is not a configuration key
+ this.setTargetKey('ldap_test_loginname');
+ this.testName = 'TestLoginName';
+ this.wizardMethod = 'testLoginName';
+ this.runsOnRequest = true;
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorTestLoginName = WizardDetectorTestLoginName;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorUserCount.js b/apps/user_ldap/js/wizard/wizardDetectorUserCount.js
new file mode 100644
index 00000000000..bcff2cf3b10
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorUserCount.js
@@ -0,0 +1,26 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc let's the wizard backend count the available users
+ *
+ * @constructor
+ */
+ var WizardDetectorUserCount = OCA.LDAP.Wizard.WizardDetectorFilterSimpleRequestAbstract.subClass({
+ init: function() {
+ this.setTargetKey('ldap_user_count');
+ this.wizardMethod = 'countUsers';
+ this.runsOnRequest = true;
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorUserCount = WizardDetectorUserCount;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorUserDisplayNameAttribute.js b/apps/user_ldap/js/wizard/wizardDetectorUserDisplayNameAttribute.js
new file mode 100644
index 00000000000..ae734480c1c
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorUserDisplayNameAttribute.js
@@ -0,0 +1,39 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc let's the wizard backend count the available users
+ *
+ * @constructor
+ */
+ var WizardDetectorUserDisplayNameAttribute = OCA.LDAP.Wizard.WizardDetectorFilterSimpleRequestAbstract.subClass({
+ init: function() {
+ this.setTargetKey('ldap_user_count');
+ this.wizardMethod = 'detectUserDisplayNameAttribute';
+ this.runsOnRequest = true;
+ },
+
+ /**
+ * @inheritdoc
+ */
+ run: function(model, configID) {
+ // default value has capital N. Detected values are always lowercase
+ if(model.configuration.ldap_display_name && model.configuration.ldap_display_name !== 'displayName') {
+ // a value is already set. Don't overwrite and don't ask LDAP
+ // without reason.
+ return false;
+ }
+ this._super(model, configID);
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorUserDisplayNameAttribute = WizardDetectorUserDisplayNameAttribute;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorUserGroupAssociation.js b/apps/user_ldap/js/wizard/wizardDetectorUserGroupAssociation.js
new file mode 100644
index 00000000000..953a0b909a6
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorUserGroupAssociation.js
@@ -0,0 +1,40 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc let's the wizard backend count the available users
+ *
+ * @constructor
+ */
+ var WizardDetectorUserGroupAssociation = OCA.LDAP.Wizard.WizardDetectorFilterSimpleRequestAbstract.subClass({
+ init: function() {
+ this.setTargetKey('ldap_group_count');
+ this.wizardMethod = 'determineGroupMemberAssoc';
+ this.runsOnRequest = true;
+ },
+
+ /**
+ * @inheritdoc
+ */
+ run: function(model, configID) {
+ // TODO: might be better with configuration marker as uniqueMember
+ // is a valid value (although probably less common then member and memberUid).
+ if(model.configuration.ldap_group_member_assoc_attribute && model.configuration.ldap_group_member_assoc_attribute !== 'uniqueMember') {
+ // a value is already set. Don't overwrite and don't ask LDAP
+ // without reason.
+ return false;
+ }
+ this._super(model, configID);
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorUserGroupAssociation = WizardDetectorUserGroupAssociation;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardDetectorUserObjectClasses.js b/apps/user_ldap/js/wizard/wizardDetectorUserObjectClasses.js
new file mode 100644
index 00000000000..0fa324a0809
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorUserObjectClasses.js
@@ -0,0 +1,29 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc discovers object classes for the users tab
+ *
+ * @constructor
+ */
+ var WizardDetectorUserObjectClasses = OCA.LDAP.Wizard.WizardDetectorFeatureAbstract.subClass({
+ /** @inheritdoc */
+ init: function() {
+ // given, it is not a configuration key
+ this.setTargetKey('ldap_userfilter_objectclass');
+ this.wizardMethod = 'determineUserObjectClasses';
+ this.featureName = 'UserObjectClasses';
+ this.runsOnRequest = true;
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardDetectorUserObjectClasses = WizardDetectorUserObjectClasses;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardFilterOnType.js b/apps/user_ldap/js/wizard/wizardFilterOnType.js
new file mode 100644
index 00000000000..f3f1368982b
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardFilterOnType.js
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc filters a select box when a text element is typed in
+ */
+ var FilterOnType = OCA.LDAP.Wizard.WizardObject.subClass({
+ /**
+ * initializes a type filter on a text input for a select element
+ *
+ * @param {jQuery} $select
+ * @param {jQuery} $textInput
+ */
+ init: function($select, $textInput) {
+ this.$select = $select;
+ this.$textInput = $textInput;
+ this.updateOptions();
+ this.lastSearch = '';
+
+ var fity = this;
+ $textInput.bind('change keyup', function () {
+ if(fity.runID) {
+ window.clearTimeout(fity.runID);
+ }
+ fity.runID = window.setTimeout(function() {
+ fity.filter(fity);
+ }, 250);
+ });
+ },
+
+ /**
+ * the options will be read in again. Should be called after a
+ * configuration switch.
+ */
+ updateOptions: function() {
+ var options = [];
+ this.$select.find('option').each(function() {
+ options.push({
+ value: $(this).val(),
+ normalized: $(this).val().toLowerCase()
+ }
+ );
+ });
+ this._options = options;
+ },
+
+ /**
+ * the actual search or filter method
+ *
+ * @param {FilterOnType} fity
+ */
+ filter: function(fity) {
+ var filterVal = fity.$textInput.val().toLowerCase();
+ if(filterVal === fity.lastSearch) {
+ return;
+ }
+ fity.lastSearch = filterVal;
+ fity.$select.empty();
+ $.each(fity._options, function() {
+ if(!filterVal || this.normalized.indexOf(filterVal) > -1) {
+ fity.$select.append($('<option>').val(this.value).text(this.value));
+ }
+ });
+ delete(fity.runID);
+ }
+ });
+
+ OCA.LDAP.Wizard.FilterOnType = FilterOnType;
+})(); \ No newline at end of file
diff --git a/apps/user_ldap/js/wizard/wizardFilterOnTypeFactory.js b/apps/user_ldap/js/wizard/wizardFilterOnTypeFactory.js
new file mode 100644
index 00000000000..eb529212734
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardFilterOnTypeFactory.js
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc creates instances of OCA.LDAP.Wizard.FilterOnType upon request
+ */
+ var FilterOnTypeFactory = OCA.LDAP.Wizard.WizardObject.subClass({
+ /**
+ * initializes a type filter on a text input for a select element
+ *
+ * @param {jQuery} $select
+ * @param {jQuery} $textInput
+ */
+ get: function($select, $textInput) {
+ return new OCA.LDAP.Wizard.FilterOnType($select, $textInput);
+ }
+ });
+
+ OCA.LDAP.Wizard.FilterOnTypeFactory = FilterOnTypeFactory;
+})(); \ No newline at end of file
diff --git a/apps/user_ldap/js/wizard/wizardObject.js b/apps/user_ldap/js/wizard/wizardObject.js
new file mode 100644
index 00000000000..a90f1533a26
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardObject.js
@@ -0,0 +1,60 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+ var initializing = false;
+ var superPattern = /xyz/.test(function() { xyz; }) ? /\b_super\b/ : /.*/;
+
+ /**
+ * @classdesc a base class that allows inheritance
+ *
+ * @abstrcact
+ * @constructor
+ */
+ var WizardObject = function(){};
+ WizardObject.subClass = function(properties) {
+ var _super = this.prototype;
+
+ initializing = true;
+ var proto = new this();
+ initializing = false;
+
+ for (var name in properties) {
+ proto[name] =
+ typeof properties[name] === "function" &&
+ typeof _super[name] === 'function' &&
+ superPattern.test(properties[name]) ?
+ (function (name, fn) {
+ return function () {
+ var tmp = this._super;
+ this._super = _super[name];
+ var ret = fn.apply(this, arguments);
+ this._super = tmp;
+ return ret;
+ };
+ })(name, properties[name]) :
+ properties[name];
+ };
+
+ function Class() {
+ if(!initializing && this.init) {
+ this.init.apply(this, arguments);
+ }
+ }
+
+ Class.prototype = proto;
+ Class.constructor = Class;
+ Class.subClass = arguments.callee;
+ return Class;
+ };
+
+ WizardObject.constructor = WizardObject;
+
+ OCA.LDAP.Wizard.WizardObject = WizardObject;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardTabAbstractFilter.js b/apps/user_ldap/js/wizard/wizardTabAbstractFilter.js
new file mode 100644
index 00000000000..ace8501117f
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardTabAbstractFilter.js
@@ -0,0 +1,373 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc This class represents the view belonging to the server tab
+ * in the LDAP wizard.
+ */
+ var WizardTabAbstractFilter = OCA.LDAP.Wizard.WizardTabGeneric.subClass({
+ /**
+ * @property {number} number that needs to exceeded to use complex group
+ * selection element
+ */
+ _groupElementSwitchThreshold: 40,
+
+ /**
+ * @property {boolean} - tells whether multiselect or complex element is
+ * used for selecting groups
+ */
+ isComplexGroupChooser: false,
+
+ /** @property {string} */
+ tabID: '',
+
+ /**
+ * initializes the instance. Always call it after initialization.
+ * concrete view must set managed items first, and then call the parent
+ * init.
+ *
+ * @param {OCA.LDAP.Wizard.FilterOnTypeFactory} fotf
+ * @param {number} [tabIndex]
+ * @param {string} [tabID]
+ */
+ init: function (fotf, tabIndex, tabID) {
+ this._super(tabIndex, tabID);
+
+ /** @type {OCA.LDAP.Wizard.FilterOnTypeFactory} */
+ this.foTFactory = fotf;
+ this._initMultiSelect(
+ this.getGroupsItem().$element,
+ t('user_ldap', 'Select groups')
+ );
+ this._initMultiSelect(
+ this.getObjectClassItem().$element,
+ t('user_ldap', 'Select object classes')
+ );
+ this.filterName = this.getFilterItem().keyName;
+ this._initFilterModeSwitcher(
+ this.getToggleItem().$element,
+ this.getRawFilterContainerItem().$element,
+ [ this.getObjectClassItem().$element ],
+ this.getFilterModeKey(),
+ {
+ status: 'disabled',
+ $element: this.getGroupsItem().$element
+ }
+ );
+ _.bindAll(this, 'onCountButtonClick', 'onSelectGroup', 'onDeselectGroup');
+ this.getCountItem().$relatedElements.click(this.onCountButtonClick);
+ if(this.manyGroupsSupport) {
+ var $selectBtn = $(this.tabID).find('.ldapGroupListSelect');
+ $selectBtn.click(this.onSelectGroup);
+ var $deselectBtn = $(this.tabID).find('.ldapGroupListDeselect');
+ $deselectBtn.click(this.onDeselectGroup);
+ }
+ },
+
+ /**
+ * returns managed item for the object class chooser. must be
+ * implemented by concrete view
+ */
+ getObjectClassItem: function () {},
+
+ /**
+ * returns managed item for the group chooser. must be
+ * implemented by concrete view
+ */
+ getGroupsItem: function () {},
+
+ /**
+ * returns managed item for the effective filter. must be
+ * implemented by concrete view
+ */
+ getFilterItem: function () {},
+
+ /**
+ * returns managed item for the toggle element. must be
+ * implemented by concrete view
+ */
+ getToggleItem: function () {},
+
+ /**
+ * returns managed item for the raw filter container. must be
+ * implemented by concrete view
+ */
+ getRawFilterContainerItem: function () {},
+
+ /**
+ * returns managed item for the count control. must be
+ * implemented by concrete view
+ */
+ getCountItem: function () {},
+
+ /**
+ * returns name of the filter mode key. must be implemented by concrete
+ * view
+ */
+ getFilterModeKey: function () {},
+
+ /**
+ * Sets the config model for this view and subscribes to some events.
+ * Also binds the config chooser to the model
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} configModel
+ */
+ setModel: function(configModel) {
+ this._super(configModel);
+ this.configModel.on('configLoaded', this.onConfigSwitch, this);
+ this.configModel.on('receivedLdapFeature', this.onFeatureReceived, this);
+ },
+
+ /**
+ * @inheritdoc
+ */
+ _setFilterModeAssisted: function () {
+ this._super();
+ if(this.isComplexGroupChooser) {
+ this.enableElement(this.getGroupsItem().$relatedElements);
+ }
+ },
+
+ /**
+ * @inheritdoc
+ */
+ _setFilterModeRaw: function () {
+ this._super();
+ if(this.manyGroupsSupport) {
+ this.disableElement(this.getGroupsItem().$relatedElements);
+ }
+ },
+
+ /**
+ * sets the selected user object classes
+ *
+ * @param {Array} classes
+ */
+ setObjectClass: function(classes) {
+ this.setElementValue(this.getObjectClassItem().$element, classes);
+ this.getObjectClassItem().$element.multiselect('refresh');
+ },
+
+ /**
+ * sets the selected groups
+ *
+ * @param {Array} groups
+ */
+ setGroups: function(groups) {
+ if(!this.isComplexGroupChooser) {
+ this.setElementValue(this.getGroupsItem().$element, groups);
+ this.getGroupsItem().$element.multiselect('refresh');
+ } else {
+ var $element = $(this.tabID).find('.ldapGroupListSelected');
+ this.equipMultiSelect($element, groups);
+ }
+ },
+
+ /**
+ * sets the filter
+ *
+ * @param {string} filter
+ */
+ setFilter: function(filter) {
+ this.setElementValue(this.getFilterItem().$element, filter);
+ this.$filterModeRawContainer.siblings('.ldapReadOnlyFilterContainer').find('.ldapFilterReadOnlyElement').text(filter);
+ },
+
+ /**
+ * sets the user count string
+ *
+ * @param {string} countInfo
+ */
+ setCount: function(countInfo) {
+ this.setElementValue(this.getCountItem().$element, countInfo);
+ },
+
+ /**
+ * @inheritdoc
+ */
+ considerFeatureRequests: function() {
+ if(!this.isActive) {
+ return;
+ }
+ if(this.getObjectClassItem().$element.find('option').length === 0) {
+ this.disableElement(this.getObjectClassItem().$element);
+ this.disableElement(this.getGroupsItem().$element);
+ if(this.parsedFilterMode === this.configModel.FILTER_MODE_ASSISTED) {
+ this.configModel.requestWizard(this.getObjectClassItem().keyName);
+ this.configModel.requestWizard(this.getGroupsItem().keyName);
+ }
+ }
+ },
+
+ /**
+ * updates (creates, if necessary) filterOnType instances
+ *
+ * @param {string} [only] - if only one search index should be updated
+ */
+ updateFilterOnType: function(only) {
+ if(_.isUndefined(this.filterOnType)) {
+ this.filterOnType = [];
+
+ var $availableGroups = $(this.tabID).find('.ldapGroupListAvailable');
+ this.filterOnType.push(this.foTFactory.get(
+ $availableGroups, $(this.tabID).find('.ldapManyGroupsSearch')
+ ));
+ var $selectedGroups = $(this.tabID).find('.ldapGroupListSelected');
+ this.filterOnType.push(this.foTFactory.get(
+ $selectedGroups, $(this.tabID).find('.ldapManyGroupsSearch')
+ ));
+ } else {
+ if(_.isUndefined || only.toLowerCase() === 'available') {
+ this.filterOnType[0].updateOptions();
+ }
+ if(_.isUndefined || only.toLowerCase() === 'selected') {
+ this.filterOnType[1].updateOptions();
+ }
+ }
+ },
+
+ /**
+ * @inheritdoc
+ */
+ onActivate: function() {
+ this.considerFeatureRequests();
+ },
+
+ /**
+ * resets the view when a configuration switch happened.
+ *
+ * @param {WizardTabAbstractFilter} view
+ * @param {Object} configuration
+ */
+ onConfigSwitch: function(view, configuration) {
+ view.getObjectClassItem().$element.find('option').remove();
+ view.getGroupsItem().$element.find('option').remove();
+ view.getCountItem().$element.text('');
+ $(view.tabID).find('.ldapGroupListAvailable').empty();
+ $(view.tabID).find('.ldapGroupListSelected').empty();
+ view.updateFilterOnType();
+ $(view.tabID).find('.ldapManyGroupsSearch').val('');
+
+ if(view.isComplexGroupChooser) {
+ view.isComplexGroupChooser = false;
+ view.getGroupsItem().$element.multiselect({classes: view.multiSelectPluginClass});
+ $(view.tabID).find(".ldapManyGroupsSupport").addClass('hidden');
+ }
+
+ view.onConfigLoaded(view, configuration);
+ },
+
+ /**
+ * @inheritdoc
+ */
+ onConfigLoaded: function(view, configuration) {
+ for(var key in view.managedItems){
+ if(!_.isUndefined(configuration[key])) {
+ var value = configuration[key];
+ var methodName = view.managedItems[key].setMethod;
+ if(!_.isUndefined(view[methodName])) {
+ view[methodName](value);
+ // we reimplement it here to update the filter index
+ // for groups. Maybe we can isolate it?
+ if(methodName === 'setGroups') {
+ view.updateFilterOnType('selected');
+ }
+ }
+ }
+ }
+ },
+
+ /**
+ * if UserObjectClasses are found, the corresponding element will be
+ * updated
+ *
+ * @param {WizardTabAbstractFilter} view
+ * @param {FeaturePayload} payload
+ */
+ onFeatureReceived: function(view, payload) {
+ if(payload.feature === view.getObjectClassItem().featureName) {
+ view.equipMultiSelect(view.getObjectClassItem().$element, payload.data);
+ } else if (payload.feature === view.getGroupsItem().featureName) {
+ if(view.manyGroupsSupport && payload.data.length > view._groupElementSwitchThreshold) {
+ // we need to fill the left list box, excluding the values
+ // that are already selected
+ var $element = $(view.tabID).find('.ldapGroupListAvailable');
+ var selected = view.configModel.configuration[view.getGroupsItem().keyName];
+ var available = $(payload.data).not(selected).get();
+ view.equipMultiSelect($element, available);
+ view.updateFilterOnType('available');
+ $(view.tabID).find(".ldapManyGroupsSupport").removeClass('hidden');
+ view.getGroupsItem().$element.multiselect({classes: view.multiSelectPluginClass + ' forceHidden'});
+ view.isComplexGroupChooser = true;
+ } else {
+ view.isComplexGroupChooser = false;
+ view.equipMultiSelect(view.getGroupsItem().$element, payload.data);
+ view.getGroupsItem().$element.multiselect({classes: view.multiSelectPluginClass});
+ $(view.tabID).find(".ldapManyGroupsSupport").addClass('hidden');
+
+ }
+ }
+ },
+
+ /**
+ * request to count the users with the current filter
+ *
+ * @param {Event} event
+ */
+ onCountButtonClick: function(event) {
+ event.preventDefault();
+ // let's clear the field
+ this.getCountItem().$element.text('');
+ this.configModel.requestWizard(this.getCountItem().keyName);
+ },
+
+ /**
+ * saves groups when using the complex UI
+ *
+ * @param {Array} groups
+ * @returns {boolean}
+ * @private
+ */
+ _saveGroups: function(groups) {
+ var toSave = '';
+ $(groups).each(function() { toSave = toSave + "\n" + this; } );
+ this.configModel.set(this.getGroupsItem().keyName, $.trim(toSave));
+ },
+
+ /**
+ * acts on adding groups to the filter
+ */
+ onSelectGroup: function() {
+ var $available = $(this.tabID).find('.ldapGroupListAvailable');
+ var $selected = $(this.tabID).find('.ldapGroupListSelected');
+ var selected = $.map($selected.find('option'), function(e) { return e.value; });
+
+ this._saveGroups(selected.concat($available.val()));
+ $available.find('option:selected').prependTo($selected);
+ this.updateFilterOnType();
+ },
+
+ /**
+ * acts on removing groups to the filter
+ */
+ onDeselectGroup: function() {
+ var $available = $(this.tabID).find('.ldapGroupListAvailable');
+ var $selected = $(this.tabID).find('.ldapGroupListSelected');
+ var selected = $.map($selected.find('option:not(:selected)'), function(e) { return e.value; });
+
+ this._saveGroups(selected);
+ $selected.find('option:selected').appendTo($available);
+ this.updateFilterOnType();
+ }
+
+ });
+
+ OCA.LDAP.Wizard.WizardTabAbstractFilter = WizardTabAbstractFilter;
+})(); \ No newline at end of file
diff --git a/apps/user_ldap/js/wizard/wizardTabAdvanced.js b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
new file mode 100644
index 00000000000..931a547218b
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
@@ -0,0 +1,330 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc This class represents the view belonging to the advanced tab
+ * in the LDAP wizard.
+ */
+ var WizardTabAdvanced = OCA.LDAP.Wizard.WizardTabGeneric.subClass({
+ /**
+ * initializes the instance. Always call it after initialization.
+ *
+ * @param tabIndex
+ * @param tabID
+ */
+ init: function (tabIndex, tabID) {
+ this._super(tabIndex, tabID);
+
+ var items = {
+ // Connection settings
+ ldap_configuration_active: {
+ $element: $('#ldap_configuration_active'),
+ setMethod: 'setConfigurationState'
+ },
+ ldap_backup_host: {
+ $element: $('#ldap_backup_host'),
+ setMethod: 'setBackupHost'
+ },
+ ldap_backup_port: {
+ $element: $('#ldap_backup_port'),
+ setMethod: 'setBackupPort'
+ },
+ ldap_override_main_server: {
+ $element: $('#ldap_override_main_server'),
+ setMethod: 'setOverrideMainServerState'
+ },
+ ldap_nocase: {
+ $element: $('#ldap_nocase'),
+ setMethod: 'setNoCase'
+ },
+ ldap_turn_off_cert_check: {
+ $element: $('#ldap_turn_off_cert_check'),
+ setMethod: 'setCertCheckDisabled'
+ },
+ ldap_cache_ttl: {
+ $element: $('#ldap_cache_ttl'),
+ setMethod: 'setCacheTTL'
+ },
+
+ //Directory Settings
+ ldap_display_name: {
+ $element: $('#ldap_display_name'),
+ setMethod: 'setUserDisplayName'
+ },
+ ldap_base_users: {
+ $element: $('#ldap_base_users'),
+ setMethod: 'setBaseDNUsers'
+ },
+ ldap_attributes_for_user_search: {
+ $element: $('#ldap_attributes_for_user_search'),
+ setMethod: 'setSearchAttributesUsers'
+ },
+ ldap_group_display_name: {
+ $element: $('#ldap_group_display_name'),
+ setMethod: 'setGroupDisplayName'
+ },
+ ldap_base_groups: {
+ $element: $('#ldap_base_groups'),
+ setMethod: 'setBaseDNGroups'
+ },
+ ldap_attributes_for_group_search: {
+ $element: $('#ldap_attributes_for_group_search'),
+ setMethod: 'setSearchAttributesGroups'
+ },
+ ldap_group_member_assoc_attribute: {
+ $element: $('#ldap_group_member_assoc_attribute'),
+ setMethod: 'setGroupMemberAssociationAttribute'
+ },
+ ldap_nested_groups: {
+ $element: $('#ldap_nested_groups'),
+ setMethod: 'setUseNestedGroups'
+ },
+ ldap_paging_size: {
+ $element: $('#ldap_paging_size'),
+ setMethod: 'setPagingSize'
+ },
+
+ //Special Attributes
+ ldap_quota_attr: {
+ $element: $('#ldap_quota_attr'),
+ setMethod: 'setQuotaAttribute'
+ },
+ ldap_quota_def: {
+ $element: $('#ldap_quota_def'),
+ setMethod: 'setQuotaDefault'
+ },
+ ldap_email_attr: {
+ $element: $('#ldap_email_attr'),
+ setMethod: 'setEmailAttribute'
+ },
+ home_folder_naming_rule: {
+ $element: $('#home_folder_naming_rule'),
+ setMethod: 'setHomeFolderAttribute'
+ }
+ };
+ this.setManagedItems(items);
+ },
+
+ /**
+ * Sets the config model for this view and subscribes to some events.
+ * Also binds the config chooser to the model
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} configModel
+ */
+ setModel: function(configModel) {
+ this._super(configModel);
+ this.configModel.on('configLoaded', this.onConfigLoaded, this);
+ this.configModel.on('receivedLdapFeature', this.onResultReceived, this);
+ },
+
+ /**
+ * updates the experienced admin check box
+ *
+ * @param {string} isConfigActive contains an int
+ */
+ setConfigurationState: function(isConfigActive) {
+ this.setElementValue(
+ this.managedItems.ldap_configuration_active.$element, isConfigActive
+ );
+ },
+
+ /**
+ * updates the backup host configuration text field
+ *
+ * @param {string} host
+ */
+ setBackupHost: function(host) {
+ this.setElementValue(this.managedItems.ldap_backup_host.$element, host);
+ },
+
+ /**
+ * updates the backup port configuration text field
+ *
+ * @param {string} port
+ */
+ setBackupPort: function(port) {
+ this.setElementValue(this.managedItems.ldap_backup_port.$element, port);
+ },
+
+ /**
+ * sets whether the main server should be overridden or not
+ *
+ * @param {string} doOverride contains an int
+ */
+ setOverrideMainServerState: function(doOverride) {
+ this.setElementValue(
+ this.managedItems.ldap_override_main_server.$element, doOverride
+ );
+ },
+
+ /**
+ * whether the server is case insensitive. This setting does not play
+ * a role anymore (probably never had).
+ *
+ * @param {string} noCase contains an int
+ */
+ setNoCase: function(noCase) {
+ this.setElementValue(this.managedItems.ldap_nocase.$element, noCase);
+ },
+
+ /**
+ * sets whether the SSL/TLS certification check shout be disabled
+ *
+ * @param {string} doCertCheck contains an int
+ */
+ setCertCheckDisabled: function(doCertCheck) {
+ this.setElementValue(
+ this.managedItems.ldap_turn_off_cert_check.$element, doCertCheck
+ );
+ },
+
+ /**
+ * sets the time-to-live of the LDAP cache (in seconds)
+ *
+ * @param {string} cacheTTL contains an int
+ */
+ setCacheTTL: function(cacheTTL) {
+ this.setElementValue(this.managedItems.ldap_cache_ttl.$element, cacheTTL);
+ },
+
+ /**
+ * sets the user display name attribute
+ *
+ * @param {string} attribute
+ */
+ setUserDisplayName: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_display_name.$element, attribute);
+ },
+
+ /**
+ * sets the Base DN for users
+ *
+ * @param {string} base
+ */
+ setBaseDNUsers: function(base) {
+ this.setElementValue(this.managedItems.ldap_base_users.$element, base);
+ },
+
+ /**
+ * sets the attributes for user searches
+ *
+ * @param {string} attributes
+ */
+ setSearchAttributesUsers: function(attributes) {
+ this.setElementValue(this.managedItems.ldap_attributes_for_user_search.$element, attributes);
+ },
+
+ /**
+ * sets the display name attribute for groups
+ *
+ * @param {string} attribute
+ */
+ setGroupDisplayName: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_group_display_name.$element, attribute);
+ },
+
+ /**
+ * sets the Base DN for groups
+ *
+ * @param {string} base
+ */
+ setBaseDNGroups: function(base) {
+ this.setElementValue(this.managedItems.ldap_base_groups.$element, base);
+ },
+
+ /**
+ * sets the attributes for group search
+ *
+ * @param {string} attributes
+ */
+ setSearchAttributesGroups: function(attributes) {
+ this.setElementValue(this.managedItems.ldap_attributes_for_group_search.$element, attributes);
+ },
+
+ /**
+ * sets the attribute for the association of users and groups
+ *
+ * @param {string} attribute
+ */
+ setGroupMemberAssociationAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_group_member_assoc_attribute.$element, attribute);
+ },
+
+ /**
+ * enabled or disables the use of nested groups (groups in groups in
+ * groups…)
+ *
+ * @param {string} useNestedGroups contains an int
+ */
+ setUseNestedGroups: function(useNestedGroups) {
+ this.setElementValue(this.managedItems.ldap_nested_groups.$element, useNestedGroups);
+ },
+
+ /**
+ * sets the size of pages for paged search
+ *
+ * @param {string} size contains an int
+ */
+ setPagingSize: function(size) {
+ this.setElementValue(this.managedItems.ldap_paging_size.$element, size);
+ },
+
+ /**
+ * sets the email attribute
+ *
+ * @param {string} attribute
+ */
+ setEmailAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_email_attr.$element, attribute);
+ },
+
+ /**
+ * sets the quota attribute
+ *
+ * @param {string} attribute
+ */
+ setQuotaAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_quota_attr.$element, attribute);
+ },
+
+ /**
+ * sets the default quota for LDAP users
+ *
+ * @param {string} quota contains an int
+ */
+ setQuotaDefault: function(quota) {
+ this.setElementValue(this.managedItems.ldap_quota_def.$element, quota);
+ },
+
+ /**
+ * sets the attribute for the ownCloud user specific home folder location
+ *
+ * @param {string} attribute
+ */
+ setHomeFolderAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.home_folder_naming_rule.$element, attribute);
+ },
+
+ /**
+ * deals with the result of the Test Connection test
+ *
+ * @param {WizardTabAdvanced} view
+ * @param {FeaturePayload} payload
+ */
+ onResultReceived: function(view, payload) {
+ if(payload.feature === 'TestConfiguration') {
+ OC.Notification.showTemporary(payload.data.message);
+ }
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardTabAdvanced = WizardTabAdvanced;
+})(); \ No newline at end of file
diff --git a/apps/user_ldap/js/wizard/wizardTabElementary.js b/apps/user_ldap/js/wizard/wizardTabElementary.js
new file mode 100644
index 00000000000..9113ecffcf4
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardTabElementary.js
@@ -0,0 +1,346 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc This class represents the view belonging to the server tab
+ * in the LDAP wizard.
+ */
+ var WizardTabElementary = OCA.LDAP.Wizard.WizardTabGeneric.subClass({
+ /**
+ * initializes the instance. Always call it after initialization.
+ *
+ * @param tabIndex
+ * @param tabID
+ */
+ init: function (tabIndex, tabID) {
+ this._super(tabIndex, tabID);
+ this.isActive = true;
+ this.configChooserID = '#ldap_serverconfig_chooser';
+
+ var items = {
+ ldap_host: {
+ $element: $('#ldap_host'),
+ setMethod: 'setHost'
+ },
+ ldap_port: {
+ $element: $('#ldap_port'),
+ setMethod: 'setPort',
+ $relatedElements: $('.ldapDetectPort')
+ },
+ ldap_dn: {
+ $element: $('#ldap_dn'),
+ setMethod: 'setAgentDN'
+ },
+ ldap_agent_password: {
+ $element: $('#ldap_agent_password'),
+ setMethod: 'setAgentPwd'
+ },
+ ldap_base: {
+ $element: $('#ldap_base'),
+ setMethod: 'setBase',
+ $relatedElements: $('.ldapDetectBase, .ldapTestBase'),
+ $detectButton: $('.ldapDetectBase'),
+ $testButton: $('.ldapTestBase')
+ },
+ ldap_base_test: {
+ $element: $('#ldap_base')
+ },
+ ldap_experienced_admin: {
+ $element: $('#ldap_experienced_admin'),
+ setMethod: 'setExperiencedAdmin'
+ }
+ };
+ this.setManagedItems(items);
+ _.bindAll(this, 'onPortButtonClick', 'onBaseDNButtonClick', 'onBaseDNTestButtonClick');
+ this.managedItems.ldap_port.$relatedElements.click(this.onPortButtonClick);
+ this.managedItems.ldap_base.$detectButton.click(this.onBaseDNButtonClick);
+ this.managedItems.ldap_base.$testButton.click(this.onBaseDNTestButtonClick);
+ },
+
+ /**
+ * Sets the config model for this view and subscribes to some events.
+ * Also binds the config chooser to the model
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} configModel
+ */
+ setModel: function(configModel) {
+ this._super(configModel);
+ this.configModel.on('configLoaded', this.onConfigSwitch, this);
+ this.configModel.on('newConfiguration', this.onNewConfiguration, this);
+ this.configModel.on('deleteConfiguration', this.onDeleteConfiguration, this);
+ this.configModel.on('receivedLdapFeature', this.onTestResultReceived, this);
+ this._enableConfigChooser();
+ this._enableConfigButtons();
+ },
+
+ /**
+ * returns the currently selected configuration ID
+ *
+ * @returns {string}
+ */
+ getConfigID: function() {
+ return $(this.configChooserID).val();
+ },
+
+ /**
+ * updates the host configuration text field
+ *
+ * @param {string} host
+ */
+ setHost: function(host) {
+ this.setElementValue(this.managedItems.ldap_host.$element, host);
+ if(host) {
+ this.enableElement(this.managedItems.ldap_port.$relatedElements);
+ } else {
+ this.disableElement(this.managedItems.ldap_port.$relatedElements);
+ }
+ },
+
+ /**
+ * updates the port configuration text field
+ *
+ * @param {string} port
+ */
+ setPort: function(port) {
+ this.setElementValue(this.managedItems.ldap_port.$element, port);
+ },
+
+ /**
+ * updates the user (agent) DN text field
+ *
+ * @param {string} agentDN
+ */
+ setAgentDN: function(agentDN) {
+ this.setElementValue(this.managedItems.ldap_dn.$element, agentDN);
+ },
+
+ /**
+ * updates the user (agent) password field
+ *
+ * @param {string} agentPwd
+ */
+ setAgentPwd: function(agentPwd) {
+ this.setElementValue(
+ this.managedItems.ldap_agent_password.$element, agentPwd
+ );
+ },
+ /**
+ * updates the base DN text area
+ *
+ * @param {string} bases
+ */
+ setBase: function(bases) {
+ this.setElementValue(this.managedItems.ldap_base.$element, bases);
+ if(!bases) {
+ this.disableElement(this.managedItems.ldap_base.$testButton);
+ } else {
+ this.enableElement(this.managedItems.ldap_base.$testButton);
+ }
+ },
+
+ /**
+ * updates the experienced admin check box
+ *
+ * @param {string} xpAdminMode contains an int
+ */
+ setExperiencedAdmin: function(xpAdminMode) {
+ this.setElementValue(
+ this.managedItems.ldap_experienced_admin.$element, xpAdminMode
+ );
+ },
+
+ /**
+ * @inheritdoc
+ */
+ overrideErrorMessage: function(message, key) {
+ switch(key) {
+ case 'ldap_port':
+ if (message === 'Invalid credentials') {
+ return t('user_ldap', 'Please check the credentials, they seem to be wrong.');
+ } else {
+ return t('user_ldap', 'Please specify the port, it could not be auto-detected.');
+ }
+ break;
+ case 'ldap_base':
+ if( message === 'Server is unwilling to perform'
+ || message === 'Could not connect to LDAP'
+ ) {
+ return t('user_ldap', 'Base DN could not be auto-detected, please revise credentials, host and port.');
+ }
+ return t('user_ldap', 'Could not detect Base DN, please enter it manually.');
+ break;
+ }
+ return message;
+ },
+
+ /**
+ * resets the view when a configuration switch happened.
+ *
+ * @param {WizardTabElementary} view
+ * @param {Object} configuration
+ */
+ onConfigSwitch: function(view, configuration) {
+ view.disableElement(view.managedItems.ldap_port.$relatedElements);
+
+ view.onConfigLoaded(view, configuration);
+ },
+
+ /**
+ * updates the configuration chooser when a new configuration was added
+ * which also means it is being switched to. The configuration fields
+ * are updated on a different step.
+ *
+ * @param {WizardTabElementary} view
+ * @param {Object} result
+ */
+ onNewConfiguration: function(view, result) {
+ if(result.isSuccess === true) {
+ $(view.configChooserID + ' option:selected').removeAttr('selected');
+ var html = '<option value="'+result.configPrefix+'" selected="selected">'+t('user_ldap','{nthServer}. Server', {nthServer: $(view.configChooserID + ' option').length})+'</option>';
+ $(view.configChooserID + ' option:last').before(html);
+ }
+ },
+
+ /**
+ * updates the configuration chooser upon the deletion of a
+ * configuration and, if necessary, loads an existing one.
+ *
+ * @param view
+ * @param result
+ */
+ onDeleteConfiguration: function(view, result) {
+ if(result.isSuccess === true) {
+ if(view.getConfigID() === result.configPrefix) {
+ // if the deleted value is still the selected one (99% of
+ // the cases), remove it from the list and load the topmost
+ $(view.configChooserID + ' option:selected').remove();
+ $(view.configChooserID + ' option:first').select();
+ if($(view.configChooserID + ' option').length < 2) {
+ view.configModel.newConfig(false);
+ } else {
+ view.configModel.load(view.getConfigID());
+ }
+ } else {
+ // otherwise just remove the entry
+ $(view.configChooserID + ' option[value=' + result.configPrefix + ']').remove();
+ }
+ } else {
+ OC.Notification.showTemporary(result.errorMessage);
+ }
+ },
+
+ /**
+ * Base DN test results will arrive here
+ *
+ * @param {WizardTabElementary} view
+ * @param {FeaturePayload} payload
+ */
+ onTestResultReceived: function(view, payload) {
+ if(payload.feature === 'TestBaseDN') {
+ var message;
+ if(payload.data.status === 'success') {
+ var objectsFound = parseInt(payload.data.changes.ldap_test_base, 10);
+ if(objectsFound < 1) {
+ message = t('user_ldap', 'No object found in the given Base DN. Please revise.');
+ } else if(objectsFound > 1000) {
+ message = t('user_ldap', 'More then 1.000 directory entries available.');
+ } else {
+ message = t('user_ldap', objectsFound + ' entries available within the provided Base DN');
+ }
+ } else {
+ message = t('user_ldap', 'An error occurred. Please check the Base DN, as well as connection settings and credentials.');
+ if(payload.data.message) {
+ console.warn(payload.data.message);
+ }
+ }
+ OC.Notification.showTemporary(message);
+ }
+ },
+
+ /**
+ * request to count the users with the current filter
+ *
+ * @param {Event} event
+ */
+ onPortButtonClick: function(event) {
+ event.preventDefault();
+ this.configModel.requestWizard('ldap_port');
+ },
+
+ /**
+ * request to count the users with the current filter
+ *
+ * @param {Event} event
+ */
+ onBaseDNButtonClick: function(event) {
+ event.preventDefault();
+ this.configModel.requestWizard('ldap_base');
+ },
+
+ /**
+ * request to count the users with the current filter
+ *
+ * @param {Event} event
+ */
+ onBaseDNTestButtonClick: function(event) {
+ event.preventDefault();
+ this.configModel.requestWizard('ldap_test_base');
+ },
+
+ /**
+ * registers the change event on the configuration chooser and makes
+ * the model load a newly selected configuration
+ *
+ * @private
+ */
+ _enableConfigChooser: function() {
+ var view = this;
+ $(this.configChooserID).change(function(){
+ var value = $(view.configChooserID + ' option:selected:first').attr('value');
+ view.configModel.load(value);
+ });
+ },
+
+ /**
+ * adds actions to the action buttons for configuration management
+ *
+ * @private
+ */
+ _enableConfigButtons: function() {
+ var view = this;
+ $('#ldap_action_delete_configuration').click(function(event) {
+ event.preventDefault();
+ OC.dialogs.confirm(
+ t('user_ldap', 'Do you really want to delete the current Server Configuration?'),
+ t('user_ldap', 'Confirm Deletion'),
+ function(doDelete) {
+ if(doDelete) {
+ view.configModel.deleteConfig(view.getConfigID());
+ }
+ },
+ false
+ );
+ });
+
+ $('#ldap_action_add_configuration').click(function(event) {
+ event.preventDefault();
+ view.configModel.newConfig(false);
+ });
+
+ $('#ldap_action_copy_configuration').click(function(event) {
+ event.preventDefault();
+ view.configModel.newConfig(true);
+ });
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardTabElementary = WizardTabElementary;
+})(); \ No newline at end of file
diff --git a/apps/user_ldap/js/wizard/wizardTabExpert.js b/apps/user_ldap/js/wizard/wizardTabExpert.js
new file mode 100644
index 00000000000..6ff93bfd62f
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardTabExpert.js
@@ -0,0 +1,130 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc This class represents the view belonging to the expert tab
+ * in the LDAP wizard.
+ */
+ var WizardTabExpert = OCA.LDAP.Wizard.WizardTabGeneric.subClass({
+ /**
+ * initializes the instance. Always call it after initialization.
+ *
+ * @param tabIndex
+ * @param tabID
+ */
+ init: function (tabIndex, tabID) {
+ this._super(tabIndex, tabID);
+
+ var items = {
+ ldap_expert_username_attr: {
+ $element: $('#ldap_expert_username_attr'),
+ setMethod: 'setUsernameAttribute'
+ },
+ ldap_expert_uuid_user_attr: {
+ $element: $('#ldap_expert_uuid_user_attr'),
+ setMethod: 'setUserUUIDAttribute'
+ },
+ ldap_expert_uuid_group_attr: {
+ $element: $('#ldap_expert_uuid_group_attr'),
+ setMethod: 'setGroupUUIDAttribute'
+ },
+
+ //Buttons
+ ldap_action_clear_user_mappings: {
+ $element: $('#ldap_action_clear_user_mappings')
+ },
+ ldap_action_clear_group_mappings: {
+ $element: $('#ldap_action_clear_group_mappings')
+ }
+
+ };
+ this.setManagedItems(items);
+ _.bindAll(this, 'onClearUserMappingsClick', 'onClearGroupMappingsClick');
+ this.managedItems.ldap_action_clear_user_mappings.$element.click(this.onClearUserMappingsClick);
+ this.managedItems.ldap_action_clear_group_mappings.$element.click(this.onClearGroupMappingsClick);
+ },
+
+ /**
+ * Sets the config model for this view and subscribes to some events.
+ * Also binds the config chooser to the model
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} configModel
+ */
+ setModel: function(configModel) {
+ this._super(configModel);
+ this.configModel.on('configLoaded', this.onConfigLoaded, this);
+ this.configModel.on('receivedLdapFeature', this.onResultReceived, this);
+ },
+
+ /**
+ * sets the attribute to be used to create an ownCloud ID (username)
+ *
+ * @param {string} attribute
+ */
+ setUsernameAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_expert_username_attr.$element, attribute);
+ },
+
+ /**
+ * sets the attribute that provides an unique identifier per LDAP user
+ * entry
+ *
+ * @param {string} attribute
+ */
+ setUserUUIDAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_expert_uuid_user_attr.$element, attribute);
+ },
+
+ /**
+ * sets the attribute that provides an unique identifier per LDAP group
+ * entry
+ *
+ * @param {string} attribute
+ */
+ setGroupUUIDAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_expert_uuid_group_attr.$element, attribute);
+ },
+
+ /**
+ * requests clearing of all user mappings
+ */
+ onClearUserMappingsClick: function() {
+ this.configModel.requestWizard('ldap_action_clear_user_mappings', {ldap_clear_mapping: 'user'});
+ },
+
+ /**
+ * requests clearing of all group mappings
+ */
+ onClearGroupMappingsClick: function() {
+ this.configModel.requestWizard('ldap_action_clear_group_mappings', {ldap_clear_mapping: 'group'});
+ },
+
+ /**
+ * deals with the result of the Test Connection test
+ *
+ * @param {WizardTabAdvanced} view
+ * @param {FeaturePayload} payload
+ */
+ onResultReceived: function(view, payload) {
+ if(payload.feature === 'ClearMappings') {
+ var message;
+ if(payload.data.status === 'success') {
+ message = t('user_ldap', 'Mappings cleared successfully!');
+ } else {
+ message = t('user_ldap', 'Error while clearing the mappings.');
+ }
+ OC.Notification.showTemporary(message);
+ }
+ }
+ });
+
+ OCA.LDAP.Wizard.WizardTabExpert = WizardTabExpert;
+})(); \ No newline at end of file
diff --git a/apps/user_ldap/js/wizard/wizardTabGeneric.js b/apps/user_ldap/js/wizard/wizardTabGeneric.js
new file mode 100644
index 00000000000..524d2a048a1
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardTabGeneric.js
@@ -0,0 +1,547 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc An abstract tab view
+ * @abstract
+ */
+ var WizardTabGeneric = OCA.LDAP.Wizard.WizardObject.subClass({
+ isActive: false,
+
+ /**
+ * @property {string} - class that identifies a multiselect-plugin
+ * control.
+ */
+ multiSelectPluginClass: 'multiSelectPlugin',
+
+ /** @inheritdoc */
+ init: function(tabIndex, tabID) {
+ this.tabIndex = tabIndex;
+ this.tabID = tabID;
+ this.spinner = $('.ldapSpinner').first().clone().removeClass('hidden');
+ _.bindAll(this, '_toggleRawFilterMode', '_toggleRawFilterModeConfirmation');
+ },
+
+ /**
+ * sets the configuration items that are managed by that view.
+ *
+ * The parameter contains key-value pairs the key being the
+ * configuration keys and the value being its setter method.
+ *
+ * @param {object} managedItems
+ */
+ setManagedItems: function(managedItems) {
+ this.managedItems = managedItems;
+ this._enableAutoSave();
+ },
+
+ /**
+ * Sets the config model. The concrete view likely wants to subscribe
+ * to events as well.
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} configModel
+ */
+ setModel: function(configModel) {
+ this.configModel = configModel;
+ this.parsedFilterMode = this.configModel.FILTER_MODE_ASSISTED;
+ this.configModel.on('detectionStarted', this.onDetectionStarted, this);
+ this.configModel.on('detectionCompleted', this.onDetectionCompleted, this);
+ this.configModel.on('serverError', this.onServerError, this);
+ this.configModel.on('setCompleted', this.onItemSaved, this);
+ this.configModel.on('configUpdated', this.onConfigLoaded, this);
+ },
+
+ /**
+ * the method can be used to display a different error/information
+ * message than provided by the ownCloud server response. The concrete
+ * Tab View may optionally implement it. Returning an empty string will
+ * avoid any notification.
+ *
+ * @param {string} message
+ * @param {string} key
+ * @returns {string}
+ */
+ overrideErrorMessage: function(message, key) {
+ return message;
+ },
+
+ /**
+ * this is called by the main view, if the tab is being switched to.
+ * The concrete tab view can implement this if necessary.
+ */
+ onActivate: function() { },
+
+ /**
+ * updates the tab when the model loaded a configuration and notified
+ * this view.
+ *
+ * @param {WizardTabGeneric} view - this instance
+ * @param {Object} configuration
+ */
+ onConfigLoaded: function(view, configuration) {
+ for(var key in view.managedItems){
+ if(!_.isUndefined(configuration[key])) {
+ var value = configuration[key];
+ var methodName = view.managedItems[key].setMethod;
+ if(!_.isUndefined(view[methodName])) {
+ view[methodName](value);
+ }
+ }
+ }
+ },
+
+ /**
+ * reacts on a set action on the model and updates the tab with the
+ * valid value.
+ *
+ * @param {WizardTabGeneric} view
+ * @param {Object} result
+ */
+ onItemSaved: function(view, result) {
+ if(!_.isUndefined(view.managedItems[result.key])) {
+ var methodName = view.managedItems[result.key].setMethod;
+ view[methodName](result.value);
+ if(!result.isSuccess) {
+ OC.Notification.showTemporary(t('user_ldap', 'Saving failed. Please make sure the database is in Operation. Reload before continuing.'));
+ console.warn(result.errorMessage);
+ }
+ }
+ },
+
+ /**
+ * displays server error messages.
+ *
+ * @param view
+ * @param payload
+ */
+ onServerError: function(view, payload) {
+ if ( !_.isUndefined(view.managedItems[payload.relatedKey])) {
+ var message = view.overrideErrorMessage(payload.message, payload.relatedKey);
+ if(message) {
+ OC.Notification.showTemporary(message);
+ }
+ }
+ },
+
+ /**
+ * disables affected, managed fields if a detector is running against them
+ *
+ * @param {WizardTabGeneric} view
+ * @param {string} key
+ */
+ onDetectionStarted: function(view, key) {
+ if(!_.isUndefined(view.managedItems[key])) {
+ view.disableElement(view.managedItems[key].$element);
+ if(!_.isUndefined(view.managedItems[key].$relatedElements)){
+ view.disableElement(view.managedItems[key].$relatedElements);
+ }
+ view.attachSpinner(view.managedItems[key].$element.attr('id'));
+ }
+ },
+
+ /**
+ * enables affected, managed fields after a detector was run against them
+ *
+ * @param {WizardTabGeneric} view
+ * @param {string} key
+ */
+ onDetectionCompleted: function(view, key) {
+ if(!_.isUndefined(view.managedItems[key])) {
+ view.enableElement(view.managedItems[key].$element);
+ if(!_.isUndefined(view.managedItems[key].$relatedElements)){
+ view.enableElement(view.managedItems[key].$relatedElements);
+ }
+ view.removeSpinner(view.managedItems[key].$element.attr('id'));
+ }
+ },
+
+ /**
+ * sets the value to an HTML element. Checkboxes, text areas and (text)
+ * input fields are supported.
+ *
+ * @param {jQuery} $element - the target element
+ * @param {string|number|Array} value
+ */
+ setElementValue: function($element, value) {
+ // deal with check box
+ if ($element.is('input[type=checkbox]')) {
+ this._setCheckBox($element, value);
+ return;
+ }
+
+ // deal with text area
+ if ($element.is('textarea') && $.isArray(value)) {
+ value = value.join("\n");
+ }
+
+ if ($element.is('span')) {
+ $element.text(value);
+ } else {
+ $element.val(value);
+ }
+ },
+
+ /**
+ * replaces options on a multiselect element
+ *
+ * @param {jQuery} $element - the multiselect element
+ * @param {Array} options
+ */
+ equipMultiSelect: function($element, options) {
+ $element.empty();
+ for (var i in options) {
+ var name = options[i];
+ $element.append($('<option>').val(name).text(name).attr('title', name));
+ }
+ if(!$element.hasClass('ldapGroupList')) {
+ $element.multiselect('refresh');
+ this.enableElement($element);
+ }
+ },
+
+ /**
+ * enables the specified HTML element
+ *
+ * @param {jQuery} $element
+ */
+ enableElement: function($element) {
+ var isMS = $element.is('select[multiple]');
+ var hasOptions = isMS ? ($element.find('option').length > 0) : false;
+
+ if($element.hasClass(this.multiSelectPluginClass) && hasOptions) {
+ $element.multiselect("enable");
+ } else if(!isMS || (isMS && hasOptions)) {
+ $element.prop('disabled', false);
+ }
+ },
+
+ /**
+ * disables the specified HTML element
+ *
+ * @param {jQuery} $element
+ */
+ disableElement: function($element) {
+ if($element.hasClass(this.multiSelectPluginClass)) {
+ $element.multiselect("disable");
+ } else {
+ $element.prop('disabled', 'disabled');
+ }
+ },
+
+ /**
+ * attaches a spinner icon to the HTML element specified by ID
+ *
+ * @param {string} elementID
+ */
+ attachSpinner: function(elementID) {
+ if($('#' + elementID + ' + .ldapSpinner').length == 0) {
+ var spinner = this.spinner.clone();
+ var $element = $('#' + elementID);
+ $(spinner).insertAfter($element);
+ // and special treatment for multiselects:
+ if ($element.is('select[multiple]')) {
+ $('#' + elementID + " + img + button").css('display', 'none');
+ }
+ }
+ },
+
+ /**
+ * removes the spinner icon from the HTML element specified by ID
+ *
+ * @param {string} elementID
+ */
+ removeSpinner: function(elementID) {
+ $('#' + elementID+' + .ldapSpinner').remove();
+ // and special treatment for multiselects:
+ $('#' + elementID + " + button").css('display', 'inline');
+ },
+
+ /**
+ * whether the wizard works in experienced admin mode
+ *
+ * @returns {boolean}
+ */
+ isExperiencedMode: function() {
+ return parseInt(this.configModel.configuration.ldap_experienced_admin, 10) === 1;
+ },
+
+ /**
+ * sets up auto-save functionality to the managed items
+ *
+ * @private
+ */
+ _enableAutoSave: function() {
+ var view = this;
+
+ for(var id in this.managedItems) {
+ if(_.isUndefined(this.managedItems[id].$element)
+ || _.isUndefined(this.managedItems[id].setMethod)) {
+ continue;
+ }
+ var $element = this.managedItems[id].$element;
+ if (!$element.is('select[multiple]')) {
+ $element.change(function() {
+ view._requestSave($(this));
+ });
+ }
+ }
+ },
+
+ /**
+ * initializes a multiSelect element
+ *
+ * @param {jQuery} $element
+ * @param {string} caption
+ * @private
+ */
+ _initMultiSelect: function($element, caption) {
+ var view = this;
+ $element.multiselect({
+ header: false,
+ selectedList: 9,
+ noneSelectedText: caption,
+ classes: this.multiSelectPluginClass,
+ close: function() {
+ view._requestSave($element);
+ }
+ });
+ },
+
+ /**
+ * @typedef {object} viewSaveInfo
+ * @property {function} val
+ * @property {function} attr
+ * @property {function} is
+ */
+
+ /**
+ * requests a save operation from the model for a given value
+ * represented by a HTML element and its ID.
+ *
+ * @param {jQuery|viewSaveInfo} $element
+ * @private
+ */
+ _requestSave: function($element) {
+ var value = '';
+ if($element.is('input[type=checkbox]')
+ && !$element.is(':checked')) {
+ value = 0;
+ } else if ($element.is('select[multiple]')) {
+ var entries = $element.multiselect("getChecked");
+ for(var i = 0; i < entries.length; i++) {
+ value = value + "\n" + entries[i].value;
+ }
+ value = $.trim(value);
+ } else {
+ value = $element.val();
+ }
+ this.configModel.set($element.attr('id'), value);
+ },
+
+ /**
+ * updates a checkbox element according to the provided value
+ *
+ * @param {jQuery} $element
+ * @param {string|number} value
+ * @private
+ */
+ _setCheckBox: function($element, value) {
+ if(parseInt(value, 10) === 1) {
+ $element.attr('checked', 'checked');
+ } else {
+ $element.removeAttr('checked');
+ }
+ },
+
+ /**
+ * this is called when the filter mode is switched to assisted. The
+ * concrete tab view should implement this, to load LDAP features
+ * (e.g. object classes, groups, attributes…), if necessary.
+ */
+ considerFeatureRequests: function() {},
+
+ /**
+ * this is called when the filter mode is switched to Assisted. The
+ * concrete tab view should request the compilation of the respective
+ * filter.
+ */
+ requestCompileFilter: function() {
+ this.configModel.requestWizard(this.filterName);
+ },
+
+ /**
+ * sets the filter mode according to the provided configuration value
+ *
+ * @param {string} mode
+ */
+ setFilterMode: function(mode) {
+ if(parseInt(mode, 10) === this.configModel.FILTER_MODE_ASSISTED) {
+ this.parsedFilterMode = this.configModel.FILTER_MODE_ASSISTED;
+ this.considerFeatureRequests();
+ this._setFilterModeAssisted();
+ if(this.isActive) {
+ // filter compilation should happen only, if the mode was
+ // switched manually, but not when initiating the view
+ this.requestCompileFilter();
+ }
+ } else {
+ this._setFilterModeRaw();
+ this.parsedFilterMode = this.configModel.FILTER_MODE_RAW;
+ }
+ },
+
+ /**
+ * updates the UI so that it represents the assisted mode setting
+ *
+ * @private
+ */
+ _setFilterModeAssisted: function() {
+ var view = this;
+ this.$filterModeRawContainer.addClass('invisible');
+ var filter = this.$filterModeRawContainer.find('.ldapFilterInputElement').val();
+ this.$filterModeRawContainer.siblings('.ldapReadOnlyFilterContainer').find('.ldapFilterReadOnlyElement').text(filter);
+ this.$filterModeRawContainer.siblings('.ldapReadOnlyFilterContainer').removeClass('hidden');
+ $.each(this.filterModeDisableableElements, function(i, $element) {
+ view.enableElement($element);
+ });
+ if(!_.isUndefined(this.filterModeStateElement)) {
+ if (this.filterModeStateElement.status === 'enabled') {
+ this.enableElement(this.filterModeStateElement.$element);
+ } else {
+ this.filterModeStateElement.status = 'disabled';
+ }
+ }
+ },
+
+ /**
+ * updates the UI so that it represents the raw mode setting
+ *
+ * @private
+ */
+ _setFilterModeRaw: function() {
+ var view = this;
+ this.$filterModeRawContainer.removeClass('invisible');
+ this.$filterModeRawContainer.siblings('.ldapReadOnlyFilterContainer').addClass('hidden');
+ $.each(this.filterModeDisableableElements, function (i, $element) {
+ view.disableElement($element);
+ });
+
+ if(!_.isUndefined(this.filterModeStateElement)) {
+ if(this.filterModeStateElement.$element.multiselect().attr('disabled') === 'disabled') {
+ this.filterModeStateElement.status = 'disabled';
+ } else {
+ this.filterModeStateElement.status = 'enabled';
+ }
+ }
+ if(!_.isUndefined(this.filterModeStateElement)) {
+ this.disableElement(this.filterModeStateElement.$element);
+ }
+ },
+
+ /**
+ * @callback toggleConfirmCallback
+ * @param {boolean} isConfirmed
+ */
+
+ /**
+ * shows a confirmation dialogue before switching from raw to assisted
+ * mode if experienced mode is enabled.
+ *
+ * @param {toggleConfirmCallback} toggleFnc
+ * @private
+ */
+ _toggleRawFilterModeConfirmation: function(toggleFnc) {
+ if( !this.isExperiencedMode()
+ || this.parsedFilterMode === this.configModel.FILTER_MODE_ASSISTED
+ ) {
+ toggleFnc(true);
+ } else {
+ OCdialogs.confirm(
+ t('user_ldap', 'Switching the mode will enable automatic LDAP queries. Depending on your LDAP size they may take a while. Do you still want to switch the mode?'),
+ t('user_ldap', 'Mode switch'),
+ toggleFnc
+ );
+ }
+ },
+
+ /**
+ * toggles the visibility of a raw filter container and so also the
+ * state of the multi-select controls. The model is requested to save
+ * the state.
+ */
+ _toggleRawFilterMode: function() {
+ var view = this;
+ this._toggleRawFilterModeConfirmation(function(isConfirmed) {
+ if(!isConfirmed) {
+ return;
+ }
+ /** var {number} */
+ var mode;
+ if (view.parsedFilterMode === view.configModel.FILTER_MODE_ASSISTED) {
+ mode = view.configModel.FILTER_MODE_RAW;
+ } else {
+ mode = view.configModel.FILTER_MODE_ASSISTED;
+ }
+ view.setFilterMode(mode);
+ /** @var {viewSaveInfo} */
+ var saveInfo = {
+ val: function () {
+ return mode;
+ },
+ attr: function () {
+ return view.filterModeKey;
+ },
+ is: function () {
+ return false;
+ }
+ };
+ view._requestSave(saveInfo);
+ });
+ },
+
+ /**
+ * @typedef {object} filterModeStateElementObj
+ * @property {string} status - either "enabled" or "disabled"
+ * @property {jQuery} $element
+ */
+
+ /**
+ * initializes a raw filter mode switcher
+ *
+ * @param {jQuery} $switcher - the element receiving the click
+ * @param {jQuery} $filterModeRawContainer - contains the raw filter
+ * input elements
+ * @param {jQuery[]} filterModeDisableableElements - an array of elements
+ * not belonging to the raw filter part that shall be en/disabled.
+ * @param {string} filterModeKey - the setting key that save the state
+ * of the mode
+ * @param {filterModeStateElementObj} [filterModeStateElement] - one element
+ * which status (enabled or not) is tracked by a setting
+ * @private
+ */
+ _initFilterModeSwitcher: function(
+ $switcher,
+ $filterModeRawContainer,
+ filterModeDisableableElements,
+ filterModeKey,
+ filterModeStateElement
+ ) {
+ this.$filterModeRawContainer = $filterModeRawContainer;
+ this.filterModeDisableableElements = filterModeDisableableElements;
+ this.filterModeStateElement = filterModeStateElement;
+ this.filterModeKey = filterModeKey;
+ $switcher.click(this._toggleRawFilterMode);
+ }
+
+ });
+
+ OCA.LDAP.Wizard.WizardTabGeneric = WizardTabGeneric;
+})();
diff --git a/apps/user_ldap/js/wizard/wizardTabGroupFilter.js b/apps/user_ldap/js/wizard/wizardTabGroupFilter.js
new file mode 100644
index 00000000000..effb2b3debd
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardTabGroupFilter.js
@@ -0,0 +1,124 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc This class represents the view belonging to the server tab
+ * in the LDAP wizard.
+ */
+ var WizardTabGroupFilter = OCA.LDAP.Wizard.WizardTabAbstractFilter.subClass({
+ /**
+ * @inheritdoc
+ */
+ init: function (fotf, tabIndex, tabID) {
+ tabID = '#ldapWizard4';
+ var items = {
+ ldap_groupfilter_objectclass: {
+ $element: $('#ldap_groupfilter_objectclass'),
+ setMethod: 'setObjectClass',
+ keyName: 'ldap_groupfilter_objectclass',
+ featureName: 'GroupObjectClasses'
+ },
+ ldap_group_filter_mode: {
+ setMethod: 'setFilterMode'
+ },
+ ldap_groupfilter_groups: {
+ $element: $('#ldap_groupfilter_groups'),
+ setMethod: 'setGroups',
+ keyName: 'ldap_groupfilter_groups',
+ featureName: 'GroupsForGroups',
+ $relatedElements: $(
+ tabID + ' .ldapGroupListAvailable,' +
+ tabID + ' .ldapGroupListSelected,' +
+ tabID + ' .ldapManyGroupsSearch'
+ )
+ },
+ ldap_group_filter: {
+ $element: $('#ldap_group_filter'),
+ setMethod: 'setFilter',
+ keyName: 'ldap_group_filter'
+ },
+ groupFilterRawToggle: {
+ $element: $('#toggleRawGroupFilter')
+ },
+ groupFilterRawContainer: {
+ $element: $('#rawGroupFilterContainer')
+ },
+ ldap_group_count: {
+ $element: $('#ldap_group_count'),
+ $relatedElements: $('.ldapGetGroupCount'),
+ setMethod: 'setCount',
+ keyName: 'ldap_group_count'
+ }
+ };
+ this.setManagedItems(items);
+ this.manyGroupsSupport = true;
+ this._super(fotf, tabIndex, tabID);
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getObjectClassItem: function () {
+ return this.managedItems.ldap_groupfilter_objectclass;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getGroupsItem: function () {
+ return this.managedItems.ldap_groupfilter_groups;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getFilterItem: function () {
+ return this.managedItems.ldap_group_filter;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getToggleItem: function () {
+ return this.managedItems.groupFilterRawToggle;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getRawFilterContainerItem: function () {
+ return this.managedItems.groupFilterRawContainer;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getCountItem: function () {
+ return this.managedItems.ldap_group_count;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {string}
+ */
+ getFilterModeKey: function () {
+ return 'ldap_group_filter_mode';
+ }
+
+ });
+
+ OCA.LDAP.Wizard.WizardTabGroupFilter = WizardTabGroupFilter;
+})(); \ No newline at end of file
diff --git a/apps/user_ldap/js/wizard/wizardTabLoginFilter.js b/apps/user_ldap/js/wizard/wizardTabLoginFilter.js
new file mode 100644
index 00000000000..121b43793f2
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardTabLoginFilter.js
@@ -0,0 +1,235 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc This class represents the view belonging to the login filter
+ * tab in the LDAP wizard.
+ */
+ var WizardTabLoginFilter = OCA.LDAP.Wizard.WizardTabGeneric.subClass({
+ /**
+ * initializes the instance. Always call it after initialization.
+ *
+ * @param tabIndex
+ * @param tabID
+ */
+ init: function (tabIndex, tabID) {
+ this._super(tabIndex, tabID);
+
+ var items = {
+ ldap_loginfilter_username: {
+ $element: $('#ldap_loginfilter_username'),
+ setMethod: 'setLoginAttributeUsername'
+ },
+ ldap_loginfilter_email: {
+ $element: $('#ldap_loginfilter_email'),
+ setMethod: 'setLoginAttributeEmail'
+ },
+ ldap_login_filter_mode: {
+ setMethod: 'setFilterMode'
+ },
+ ldap_loginfilter_attributes: {
+ $element: $('#ldap_loginfilter_attributes'),
+ setMethod: 'setLoginAttributesOther'
+ },
+ ldap_login_filter: {
+ $element: $('#ldap_login_filter'),
+ setMethod: 'setLoginFilter'
+ },
+ loginFilterRawToggle: {
+ $element: $('#toggleRawLoginFilter')
+ },
+ loginFilterRawContainer: {
+ $element: $('#rawLoginFilterContainer')
+ },
+ ldap_test_loginname: {
+ $element: $('#ldap_test_loginname'),
+ $relatedElements: $('.ldapVerifyLoginName')
+ }
+ };
+ this.setManagedItems(items);
+
+ this.filterModeKey = 'ldapLoginFilterMode';
+ this._initMultiSelect(
+ this.managedItems.ldap_loginfilter_attributes.$element,
+ t('user_ldap', 'Select attributes')
+ );
+ this.filterName = 'ldap_login_filter';
+ this._initFilterModeSwitcher(
+ this.managedItems.loginFilterRawToggle.$element,
+ this.managedItems.loginFilterRawContainer.$element,
+ [
+ this.managedItems.ldap_loginfilter_username.$element,
+ this.managedItems.ldap_loginfilter_email.$element,
+ this.managedItems.ldap_loginfilter_attributes.$element
+ ],
+ 'ldap_login_filter_mode'
+ );
+ _.bindAll(this, 'onVerifyClick');
+ this.managedItems.ldap_test_loginname.$relatedElements.click(this.onVerifyClick);
+ },
+
+ /**
+ * Sets the config model for this view and subscribes to some events.
+ * Also binds the config chooser to the model
+ *
+ * @param {OCA.LDAP.Wizard.ConfigModel} configModel
+ */
+ setModel: function(configModel) {
+ this._super(configModel);
+ this.configModel.on('configLoaded', this.onConfigSwitch, this);
+ this.configModel.on('receivedLdapFeature', this.onFeatureReceived, this);
+ },
+
+ /**
+ * sets the selected attributes
+ *
+ * @param {Array} attributes
+ */
+ setLoginAttributesOther: function(attributes) {
+ this.setElementValue(this.managedItems.ldap_loginfilter_attributes.$element, attributes);
+ this.managedItems.ldap_loginfilter_attributes.$element.multiselect('refresh');
+ },
+
+ /**
+ * sets the login list filter
+ *
+ * @param {string} filter
+ */
+ setLoginFilter: function(filter) {
+ this.setElementValue(this.managedItems.ldap_login_filter.$element, filter);
+ this.$filterModeRawContainer.siblings('.ldapReadOnlyFilterContainer').find('.ldapFilterReadOnlyElement').text(filter);
+ },
+
+ /**
+ * updates the username attribute check box
+ *
+ * @param {string} useUsername contains an int
+ */
+ setLoginAttributeUsername: function(useUsername) {
+ this.setElementValue(
+ this.managedItems.ldap_loginfilter_username.$element, useUsername
+ );
+ },
+
+ /**
+ * updates the email attribute check box
+ *
+ * @param {string} useEmail contains an int
+ */
+ setLoginAttributeEmail: function(useEmail) {
+ this.setElementValue(
+ this.managedItems.ldap_loginfilter_email.$element, useEmail
+ );
+ },
+
+ /**
+ * presents the result of the login name test
+ *
+ * @param result
+ */
+ handleLoginTestResult: function(result) {
+ var message;
+ var isHtml = false;
+ if(result.status === 'success') {
+ var usersFound = parseInt(result.changes.ldap_test_loginname, 10);
+ if(usersFound < 1) {
+ var filter = result.changes.ldap_test_effective_filter;
+ message = t('user_ldap', 'User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>' + filter);
+ console.warn(filter);
+ isHtml = true;
+ } else if(usersFound === 1) {
+ message = t('user_ldap', 'User found and settings verified.');
+ } else if(usersFound > 1) {
+ message = t('user_ldap', 'Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter.');
+ }
+ } else {
+ message = t('user_ldap', 'An unspecified error occurred. Please check the settings and the log.');
+ if(!_.isUndefined(result.message) && result.message) {
+ message = result.message;
+ }
+ if(message === 'Bad search filter') {
+ message = t('user_ldap', 'The search filter is invalid, probably due to syntax issues like uneven number of opened and closed brackets. Please revise.');
+ } else if(message === 'connection error') {
+ message = t('user_ldap', 'A connection error to LDAP / AD occurred, please check host, port and credentials.');
+ } else if(message === 'missing placeholder') {
+ message = t('user_ldap', 'The %uid placeholder is missing. It will be replaced with the login name when querying LDAP / AD.');
+ }
+ }
+ OC.Notification.showTemporary(message, {isHTML: isHtml});
+ },
+
+ /**
+ * @inheritdoc
+ */
+ considerFeatureRequests: function() {
+ if(!this.isActive) {
+ return;
+ }
+ if(this.managedItems.ldap_loginfilter_attributes.$element.find('option').length === 0) {
+ this.disableElement(this.managedItems.ldap_loginfilter_attributes.$element);
+ if(this.parsedFilterMode === this.configModel.FILTER_MODE_ASSISTED) {
+ this.configModel.requestWizard('ldap_loginfilter_attributes');
+ }
+ }
+ },
+
+ /**
+ * @inheritdoc
+ */
+ onActivate: function() {
+ this.considerFeatureRequests();
+ },
+
+ /**
+ * resets the view when a configuration switch happened.
+ *
+ * @param {WizardTabLoginFilter} view
+ * @param {Object} configuration
+ */
+ onConfigSwitch: function(view, configuration) {
+ view.managedItems.ldap_loginfilter_attributes.$element.find('option').remove();
+
+ view.onConfigLoaded(view, configuration);
+ },
+
+ /**
+ * if UserObjectClasses are found, the corresponding element will be
+ * updated
+ *
+ * @param {WizardTabLoginFilter} view
+ * @param {FeaturePayload} payload
+ */
+ onFeatureReceived: function(view, payload) {
+ if(payload.feature === 'AvailableAttributes') {
+ view.equipMultiSelect(view.managedItems.ldap_loginfilter_attributes.$element, payload.data);
+ } else if(payload.feature === 'TestLoginName') {
+ view.handleLoginTestResult(payload.data);
+ }
+ },
+
+ /**
+ * request to test the provided login name
+ *
+ * @param {Event} event
+ */
+ onVerifyClick: function(event) {
+ event.preventDefault();
+ var testLogin = this.managedItems.ldap_test_loginname.$element.val();
+ if(!testLogin) {
+ OC.Notification.showTemporary(t('user_ldap', 'Please provide a login name to test against'), 3);
+ } else {
+ this.configModel.requestWizard('ldap_test_loginname', {ldap_test_loginname: testLogin});
+ }
+ }
+
+ });
+
+ OCA.LDAP.Wizard.WizardTabLoginFilter = WizardTabLoginFilter;
+})(); \ No newline at end of file
diff --git a/apps/user_ldap/js/wizard/wizardTabUserFilter.js b/apps/user_ldap/js/wizard/wizardTabUserFilter.js
new file mode 100644
index 00000000000..4ca1199b503
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardTabUserFilter.js
@@ -0,0 +1,136 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or later.
+ * See the COPYING-README file.
+ */
+
+OCA = OCA || {};
+
+(function() {
+
+ /**
+ * @classdesc This class represents the view belonging to the server tab
+ * in the LDAP wizard.
+ */
+ var WizardTabUserFilter = OCA.LDAP.Wizard.WizardTabAbstractFilter.subClass({
+ /**
+ * @inheritdoc
+ */
+ init: function (fotf, tabIndex, tabID) {
+ tabID = '#ldapWizard2';
+ var items = {
+ ldap_userfilter_objectclass: {
+ $element: $('#ldap_userfilter_objectclass'),
+ setMethod: 'setObjectClass',
+ keyName: 'ldap_userfilter_objectclass',
+ featureName: 'UserObjectClasses'
+ },
+ ldap_user_filter_mode: {
+ setMethod: 'setFilterMode'
+ },
+ ldap_userfilter_groups: {
+ $element: $('#ldap_userfilter_groups'),
+ setMethod: 'setGroups',
+ keyName: 'ldap_userfilter_groups',
+ featureName: 'GroupsForUsers',
+ $relatedElements: $(
+ tabID + ' .ldapGroupListAvailable,' +
+ tabID + ' .ldapGroupListSelected,' +
+ tabID + ' .ldapManyGroupsSearch'
+ )
+ },
+ ldap_userlist_filter: {
+ $element: $('#ldap_userlist_filter'),
+ setMethod: 'setFilter',
+ keyName: 'ldap_userlist_filter'
+ },
+ userFilterRawToggle: {
+ $element: $('#toggleRawUserFilter')
+ },
+ userFilterRawContainer: {
+ $element: $('#rawUserFilterContainer')
+ },
+ ldap_user_count: {
+ $element: $('#ldap_user_count'),
+ $relatedElements: $('.ldapGetUserCount'),
+ setMethod: 'setCount',
+ keyName: 'ldap_user_count'
+ }
+ };
+ this.setManagedItems(items);
+ this.manyGroupsSupport = true;
+ this._super(fotf, tabIndex, tabID);
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getObjectClassItem: function () {
+ return this.managedItems.ldap_userfilter_objectclass;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getGroupsItem: function () {
+ return this.managedItems.ldap_userfilter_groups;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getFilterItem: function () {
+ return this.managedItems.ldap_userlist_filter;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getToggleItem: function () {
+ return this.managedItems.userFilterRawToggle;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getRawFilterContainerItem: function () {
+ return this.managedItems.userFilterRawContainer;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {Object}
+ */
+ getCountItem: function () {
+ return this.managedItems.ldap_user_count;
+ },
+
+ /**
+ * @inheritdoc
+ * @returns {string}
+ */
+ getFilterModeKey: function () {
+ return 'ldap_user_filter_mode';
+ },
+
+ /**
+ * @inheritdoc
+ */
+ overrideErrorMessage: function(message, key) {
+ if( key === 'ldap_userfilter_groups'
+ && message === 'memberOf is not supported by the server'
+ ) {
+ message = t('user_ldap', 'The group box was disabled, because the LDAP / AD server does not support memberOf.');
+ }
+ return message;
+ }
+
+ });
+
+ OCA.LDAP.Wizard.WizardTabUserFilter = WizardTabUserFilter;
+})(); \ No newline at end of file
diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php
index e7fb4165c36..f38d11d4be3 100644
--- a/apps/user_ldap/lib/access.php
+++ b/apps/user_ldap/lib/access.php
@@ -596,6 +596,22 @@ class Access extends LDAPUtility implements user\IUserTools {
}
/**
+ * fetches a list of users according to a provided loginName and utilizing
+ * the login filter.
+ *
+ * @param string $loginName
+ * @param array $attributes optional, list of attributes to read
+ * @return array
+ */
+ public function fetchUsersByLoginName($loginName, $attributes = array('dn')) {
+ $loginName = $this->escapeFilterPart($loginName);
+ $filter = \OCP\Util::mb_str_replace(
+ '%uid', $loginName, $this->connection->ldapLoginFilter, 'UTF-8');
+ $users = $this->fetchListOfUsers($filter, $attributes);
+ return $users;
+ }
+
+ /**
* @param string $filter
* @param string|string[] $attr
* @param int $limit
@@ -687,6 +703,17 @@ class Access extends LDAPUtility implements user\IUserTools {
}
/**
+ * returns the number of available objects on the base DN
+ *
+ * @param int|null $limit
+ * @param int|null $offset
+ * @return int|bool
+ */
+ public function countObjects($limit = null, $offset = null) {
+ return $this->count('objectclass=*', $this->connection->ldapBase, array('dn'), $limit, $offset);
+ }
+
+ /**
* retrieved. Results will according to the order in the array.
* @param int $limit optional, maximum results to be counted
* @param int $offset optional, a starting point
diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php
index 9b01fd2e559..4621297595d 100644
--- a/apps/user_ldap/lib/configuration.php
+++ b/apps/user_ldap/lib/configuration.php
@@ -201,11 +201,14 @@ class Configuration {
case 'ldapAgentPassword':
$readMethod = 'getPwd';
break;
- case 'ldapUserDisplayName':
case 'ldapGroupDisplayName':
$readMethod = 'getLcValue';
break;
+ case 'ldapUserDisplayName':
default:
+ // user display name does not lower case because
+ // we rely on an upper case N as indicator whether to
+ // auto-detect it or not. FIXME
$readMethod = 'getValue';
break;
}
diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php
index 97f3002ccaf..cb3dd7f13aa 100644
--- a/apps/user_ldap/lib/wizard.php
+++ b/apps/user_ldap/lib/wizard.php
@@ -75,9 +75,11 @@ class Wizard extends LDAPUtility {
/**
* counts entries in the LDAP directory
+ *
* @param string $filter the LDAP search filter
* @param string $type a string being either 'users' or 'groups';
- * @return int|bool
+ * @return bool|int
+ * @throws \Exception
*/
public function countEntries($filter, $type) {
$reqs = array('ldapHost', 'ldapPort', 'ldapBase');
@@ -88,17 +90,36 @@ class Wizard extends LDAPUtility {
throw new \Exception('Requirements not met', 400);
}
+ $attr = array('dn'); // default
+ $limit = 1001;
if($type === 'groups') {
- $result = $this->access->countGroups($filter);
+ $result = $this->access->countGroups($filter, $attr, $limit);
} else if($type === 'users') {
- $result = $this->access->countUsers($filter);
+ $result = $this->access->countUsers($filter, $attr, $limit);
+ } else if ($type === 'objects') {
+ $result = $this->access->countObjects($limit);
} else {
- throw new \Exception('internal error: invald object type', 500);
+ throw new \Exception('internal error: invalid object type', 500);
}
return $result;
}
+ /**
+ * formats the return value of a count operation to the string to be
+ * inserted.
+ *
+ * @param bool|int $count
+ * @return int|string
+ */
+ private function formatCountResult($count) {
+ $formatted = ($count !== false) ? $count : 0;
+ if($formatted > 1000) {
+ $formatted = '> 1000';
+ }
+ return $formatted;
+ }
+
public function countGroups() {
$filter = $this->configuration->ldapGroupFilter;
@@ -109,7 +130,7 @@ class Wizard extends LDAPUtility {
}
try {
- $groupsTotal = $this->countEntries($filter, 'groups');
+ $groupsTotal = $this->formatCountResult($this->countEntries($filter, 'groups'));
} catch (\Exception $e) {
//400 can be ignored, 500 is forwarded
if($e->getCode() === 500) {
@@ -117,7 +138,6 @@ class Wizard extends LDAPUtility {
}
return false;
}
- $groupsTotal = ($groupsTotal !== false) ? $groupsTotal : 0;
$output = self::$l->n('%s group found', '%s groups found', $groupsTotal, array($groupsTotal));
$this->result->addChange('ldap_group_count', $output);
return $this->result;
@@ -130,14 +150,26 @@ class Wizard extends LDAPUtility {
public function countUsers() {
$filter = $this->access->getFilterForUserCount();
- $usersTotal = $this->countEntries($filter, 'users');
- $usersTotal = ($usersTotal !== false) ? $usersTotal : 0;
+ $usersTotal = $this->formatCountResult($this->countEntries($filter, 'users'));
$output = self::$l->n('%s user found', '%s users found', $usersTotal, array($usersTotal));
$this->result->addChange('ldap_user_count', $output);
return $this->result;
}
/**
+ * counts any objects in the currently set base dn
+ *
+ * @return WizardResult
+ * @throws \Exception
+ */
+ public function countInBaseDN() {
+ // we don't need to provide a filter in this case
+ $total = $this->countEntries(null, 'objects');
+ $this->result->addChange('ldap_test_base', $total);
+ return $this->result;
+ }
+
+ /**
* counts users with a specified attribute
* @param string $attr
* @param bool $existsCheck
@@ -282,45 +314,6 @@ class Wizard extends LDAPUtility {
}
/**
- * return the state of the Group Filter Mode
- * @return WizardResult
- */
- public function getGroupFilterMode() {
- $this->getFilterMode('ldapGroupFilterMode');
- return $this->result;
- }
-
- /**
- * return the state of the Login Filter Mode
- * @return WizardResult
- */
- public function getLoginFilterMode() {
- $this->getFilterMode('ldapLoginFilterMode');
- return $this->result;
- }
-
- /**
- * return the state of the User Filter Mode
- * @return WizardResult
- */
- public function getUserFilterMode() {
- $this->getFilterMode('ldapUserFilterMode');
- return $this->result;
- }
-
- /**
- * return the state of the mode of the specified filter
- * @param string $confKey contains the access key of the Configuration
- */
- private function getFilterMode($confKey) {
- $mode = $this->configuration->$confKey;
- if(is_null($mode)) {
- $mode = $this->LFILTER_MODE_ASSISTED;
- }
- $this->result->addChange($confKey, $mode);
- }
-
- /**
* detects the available LDAP attributes
* @return array|false The instance's WizardResult instance
* @throws \Exception
@@ -467,8 +460,9 @@ class Wizard extends LDAPUtility {
return false;
}
$this->configuration->setConfiguration(array('ldapGroupMemberAssocAttr' => $attribute));
+ $this->result->addChange('ldap_group_member_assoc_attribute', $attribute);
//so it will be saved on destruct
- $this->result->markChange();
+ //$this->result->markChange();
return $this->result;
}
@@ -604,6 +598,41 @@ class Wizard extends LDAPUtility {
}
/**
+ * @return bool|WizardResult
+ * @param string $loginName
+ * @throws \Exception
+ */
+ public function testLoginName($loginName) {
+ if(!$this->checkRequirements(array('ldapHost',
+ 'ldapPort',
+ 'ldapBase',
+ 'ldapLoginFilter',
+ ))) {
+ return false;
+ }
+
+ $cr = $this->access->connection->getConnectionResource();
+ if(!$this->ldap->isResource($cr)) {
+ throw new \Exception('connection error');
+ }
+
+ if(mb_strpos($this->access->connection->ldapLoginFilter, '%uid', 0, 'UTF-8')
+ === false) {
+ throw new \Exception('missing placeholder');
+ }
+
+ $users = $this->access->fetchUsersByLoginName($loginName);
+ if($this->ldap->errno($cr) !== 0) {
+ throw new \Exception($this->ldap->error($cr));
+ }
+ $filter = \OCP\Util::mb_str_replace(
+ '%uid', $loginName, $this->access->connection->ldapLoginFilter, 'UTF-8');
+ $this->result->addChange('ldap_test_loginname', count($users));
+ $this->result->addChange('ldap_test_effective_filter', $filter);
+ return $this->result;
+ }
+
+ /**
* Tries to determine the port, requires given Host, User DN and Password
* @return WizardResult|false WizardResult on success, false otherwise
* @throws \Exception
@@ -674,10 +703,13 @@ class Wizard extends LDAPUtility {
}
$dparts = explode('.', $domain);
- $base2 = implode('dc=', $dparts);
- if($base !== $base2 && $this->testBaseDN($base2)) {
- $this->applyFind('ldap_base', $base2);
- return $this->result;
+ while(count($dparts) > 0) {
+ $base2 = 'dc=' . implode(',dc=', $dparts);
+ if ($base !== $base2 && $this->testBaseDN($base2)) {
+ $this->applyFind('ldap_base', $base2);
+ return $this->result;
+ }
+ array_shift($dparts);
}
return false;
@@ -720,7 +752,7 @@ class Wizard extends LDAPUtility {
* @throws \Exception
*/
private function detectGroupMemberAssoc() {
- $possibleAttrs = array('uniqueMember', 'memberUid', 'member', 'unfugasdfasdfdfa');
+ $possibleAttrs = array('uniqueMember', 'memberUid', 'member');
$filter = $this->configuration->ldapGroupFilter;
if(empty($filter)) {
return false;
@@ -730,7 +762,7 @@ class Wizard extends LDAPUtility {
throw new \Exception('Could not connect to LDAP');
}
$base = $this->configuration->ldapBase[0];
- $rr = $this->ldap->search($cr, $base, $filter, $possibleAttrs);
+ $rr = $this->ldap->search($cr, $base, $filter, $possibleAttrs, 0, 1000);
if(!$this->ldap->isResource($rr)) {
return false;
}
@@ -1114,7 +1146,8 @@ class Wizard extends LDAPUtility {
//skip when the filter is a wildcard and results were found
continue;
}
- $rr = $this->ldap->search($cr, $base, $filter, array($attr));
+ // 20k limit for performance and reason
+ $rr = $this->ldap->search($cr, $base, $filter, array($attr), 0, 20000);
if(!$this->ldap->isResource($rr)) {
continue;
}
diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php
index 85bfbaa076f..f8efa378c7e 100644
--- a/apps/user_ldap/settings.php
+++ b/apps/user_ldap/settings.php
@@ -29,13 +29,52 @@
OC_Util::checkAdminUser();
-OCP\Util::addScript('user_ldap', 'ldapFilter');
-OCP\Util::addScript('user_ldap', 'experiencedAdmin');
-OCP\Util::addScript('user_ldap', 'settings');
\OC_Util::addVendorScript('user_ldap', 'ui-multiselect/src/jquery.multiselect');
-OCP\Util::addStyle('user_ldap', 'settings');
\OC_Util::addVendorStyle('user_ldap', 'ui-multiselect/jquery.multiselect');
+\OCP\Util::addScript('user_ldap', 'wizard/controller');
+\OCP\Util::addScript('user_ldap', 'wizard/configModel');
+\OCP\Util::addScript('user_ldap', 'wizard/view');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardObject');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardTabGeneric');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardTabElementary');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardTabAbstractFilter');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardTabUserFilter');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardTabLoginFilter');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardTabGroupFilter');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardTabAdvanced');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardTabExpert');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorQueue');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorGeneric');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorPort');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorBaseDN');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorFeatureAbstract');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorUserObjectClasses');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorGroupObjectClasses');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorGroupsForUsers');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorGroupsForGroups');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorSimpleRequestAbstract');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorFilterUser');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorFilterLogin');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorFilterGroup');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorUserCount');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorGroupCount');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorEmailAttribute');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorUserDisplayNameAttribute');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorUserGroupAssociation');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorAvailableAttributes');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorTestAbstract');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorTestLoginName');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorTestBaseDN');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorTestConfiguration');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorClearUserMappings');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardDetectorClearGroupMappings');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardFilterOnType');
+\OCP\Util::addScript('user_ldap', 'wizard/wizardFilterOnTypeFactory');
+\OCP\Util::addScript('user_ldap', 'wizard/wizard');
+
+OCP\Util::addStyle('user_ldap', 'settings');
+
// fill template
$tmpl = new OCP\Template('user_ldap', 'settings');
@@ -55,9 +94,9 @@ $l = \OC::$server->getL10N('user_ldap');
$wizTabs = array();
$wizTabs[] = array('tpl' => 'part.wizard-server', 'cap' => $l->t('Server'));
-$wizTabs[] = array('tpl' => 'part.wizard-userfilter', 'cap' => $l->t('User Filter'));
-$wizTabs[] = array('tpl' => 'part.wizard-loginfilter', 'cap' => $l->t('Login Filter'));
-$wizTabs[] = array('tpl' => 'part.wizard-groupfilter', 'cap' => $l->t('Group Filter'));
+$wizTabs[] = array('tpl' => 'part.wizard-userfilter', 'cap' => $l->t('Users'));
+$wizTabs[] = array('tpl' => 'part.wizard-loginfilter', 'cap' => $l->t('Login Attributes'));
+$wizTabs[] = array('tpl' => 'part.wizard-groupfilter', 'cap' => $l->t('Groups'));
$wizTabsCount = count($wizTabs);
for($i = 0; $i < $wizTabsCount; $i++) {
$tab = new OCP\Template('user_ldap', $wizTabs[$i]['tpl']);
@@ -81,4 +120,4 @@ foreach($defaults as $key => $default) {
$tmpl->assign($key.'_default', $default);
}
-return $tmpl->fetchPage();
+return $tmpl->fetchPage(); \ No newline at end of file
diff --git a/apps/user_ldap/templates/part.settingcontrols.php b/apps/user_ldap/templates/part.settingcontrols.php
index e67cea41d9c..bac00daa39f 100644
--- a/apps/user_ldap/templates/part.settingcontrols.php
+++ b/apps/user_ldap/templates/part.settingcontrols.php
@@ -1,5 +1,4 @@
<div class="ldapSettingControls">
- <input class="ldap_submit" value="<?php p($l->t('Save'));?>" type="submit">
<button type="button" class="ldap_action_test_connection" name="ldap_action_test_connection">
<?php p($l->t('Test Configuration'));?>
</button>
diff --git a/apps/user_ldap/templates/part.wizard-groupfilter.php b/apps/user_ldap/templates/part.wizard-groupfilter.php
index 1953d2eaa6e..bfcfd115218 100644
--- a/apps/user_ldap/templates/part.wizard-groupfilter.php
+++ b/apps/user_ldap/templates/part.wizard-groupfilter.php
@@ -5,31 +5,48 @@
</p>
<p>
<label for="ldap_groupfilter_objectclass">
- <?php p($l->t('only those object classes:'));?>
+ <?php p($l->t('Only these object classes:'));?>
</label>
<select id="ldap_groupfilter_objectclass" multiple="multiple"
- name="ldap_groupfilter_objectclass">
+ name="ldap_groupfilter_objectclass" class="multiSelectPlugin">
</select>
</p>
<p>
<label for="ldap_groupfilter_groups">
- <?php p($l->t('only from those groups:'));?>
+ <?php p($l->t('Only from these groups:'));?>
</label>
+ <input type="text" class="ldapManyGroupsSupport ldapManyGroupsSearch hidden" placeholder="<?php p($l->t('Search groups'));?>" />
+
<select id="ldap_groupfilter_groups" multiple="multiple"
- name="ldap_groupfilter_groups">
+ name="ldap_groupfilter_groups" class="multiSelectPlugin">
</select>
+
+ </p>
+ <p class="ldapManyGroupsSupport hidden">
+ <label></label>
+ <select class="ldapGroupList ldapGroupListAvailable" multiple="multiple"
+ title="<?php p($l->t('Available groups'));?>"></select>
+ <span>
+ <button class="ldapGroupListSelect" type="button">&gt;</button><br/>
+ <button class="ldapGroupListDeselect" type="button">&lt;</button>
+ </span>
+ <select class="ldapGroupList ldapGroupListSelected" multiple="multiple"
+ title="<?php p($l->t('Selected groups'));?>"></select>
</p>
<p>
- <label><a id='toggleRawGroupFilter'>↓ <?php p($l->t('Edit raw filter instead'));?></a></label>
+ <label><a id='toggleRawGroupFilter' class='ldapToggle'>↓ <?php p($l->t('Edit LDAP Query'));?></a></label>
+ </p>
+ <p id="ldapReadOnlyGroupFilterContainer" class="hidden ldapReadOnlyFilterContainer">
+ <label><?php p($l->t('LDAP Filter:'));?></label>
+ <span class="ldapFilterReadOnlyElement ldapInputColElement"></span>
</p>
<p id="rawGroupFilterContainer" class="invisible">
- <input type="text" id="ldap_group_filter" name="ldap_group_filter"
- class="lwautosave"
- placeholder="<?php p($l->t('Raw LDAP filter'));?>"
- title="<?php p($l->t('The filter specifies which LDAP groups shall have access to the %s instance.', $theme->getName()));?>"
- />
+ <textarea type="text" id="ldap_group_filter" name="ldap_group_filter"
+ placeholder="<?php p($l->t('Edit LDAP Query'));?>"
+ title="<?php p($l->t('The filter specifies which LDAP groups shall have access to the %s instance.', $theme->getName()));?>">
+ </textarea>
<button class="ldapGetEntryCount hidden" name="ldapGetEntryCount" type="button">
<?php p($l->t('Test Filter'));?>
</button>
@@ -38,7 +55,10 @@
<div class="ldapWizardInfo invisible">&nbsp;</div>
</p>
<p class="ldap_count">
- <span id="ldap_group_count">0 <?php p($l->t('groups found'));?></span>
+ <button class="ldapGetEntryCount ldapGetGroupCount" name="ldapGetEntryCount" type="button">
+ <?php p($l->t('Verify settings and count groups'));?>
+ </button>
+ <span id="ldap_group_count"></span>
</p>
<?php print_unescaped($_['wizardControls']); ?>
</div>
diff --git a/apps/user_ldap/templates/part.wizard-loginfilter.php b/apps/user_ldap/templates/part.wizard-loginfilter.php
index 3dde46fa979..fa17a9b430b 100644
--- a/apps/user_ldap/templates/part.wizard-loginfilter.php
+++ b/apps/user_ldap/templates/part.wizard-loginfilter.php
@@ -1,23 +1,25 @@
<fieldset id="ldapWizard3">
<div>
<p>
- <?php p($l->t('Users login with this attribute:'));?>
+ <?php p($l->t('When logging in, %s will find the user based on the following attributes:', $theme->getName()));?>
</p>
<p>
<label for="ldap_loginfilter_username">
- <?php p($l->t('LDAP Username:'));?>
+ <?php p($l->t('LDAP / AD Username:'));?>
</label>
<input type="checkbox" id="ldap_loginfilter_username"
- name="ldap_loginfilter_username" value="1" class="lwautosave" />
+ title="<?php p($l->t('Allows login against the LDAP / AD username, which is either uid or samaccountname and will be detected.'));?>"
+ name="ldap_loginfilter_username" value="1" />
</p>
<p>
<label for="ldap_loginfilter_email">
- <?php p($l->t('LDAP Email Address:'));?>
+ <?php p($l->t('LDAP / AD Email Address:'));?>
</label>
<input type="checkbox" id="ldap_loginfilter_email"
- name="ldap_loginfilter_email" value="1" class="lwautosave" />
+ title="<?php p($l->t('Allows login against an email attribute. Mail and mailPrimaryAddress will be allowed.'));?>"
+ name="ldap_loginfilter_email" value="1" />
</p>
<p>
<label for="ldap_loginfilter_attributes">
@@ -25,23 +27,35 @@
</label>
<select id="ldap_loginfilter_attributes" multiple="multiple"
- name="ldap_loginfilter_attributes">
+ name="ldap_loginfilter_attributes" class="multiSelectPlugin">
</select>
</p>
<p>
- <label><a id='toggleRawLoginFilter'>↓ <?php p($l->t('Edit raw filter instead'));?></a></label>
+ <label><a id='toggleRawLoginFilter' class='ldapToggle'>↓ <?php p($l->t('Edit LDAP Query'));?></a></label>
+ </p>
+ <p id="ldapReadOnlyLoginFilterContainer" class="hidden ldapReadOnlyFilterContainer">
+ <label><?php p($l->t('LDAP Filter:'));?></label>
+ <span class="ldapFilterReadOnlyElement ldapInputColElement"></span>
</p>
<p id="rawLoginFilterContainer" class="invisible">
- <input type="text" id="ldap_login_filter" name="ldap_login_filter"
- class="lwautosave"
- placeholder="<?php p($l->t('Raw LDAP filter'));?>"
- title="<?php p($l->t('Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: "uid=%%uid"'));?>"
- />
+ <textarea type="text" id="ldap_login_filter" name="ldap_login_filter"
+ class="ldapFilterInputElement"
+ placeholder="<?php p($l->t('Edit LDAP Query'));?>"
+ title="<?php p($l->t('Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: "uid=%%uid"'));?>">
+ </textarea>
</p>
<p>
<div class="ldapWizardInfo invisible">&nbsp;</div>
</p>
-
+ <p class="ldap_verify">
+ <input type="text" id="ldap_test_loginname" name="ldap_test_loginname"
+ placeholder="<?php p($l->t('Test Loginname'));?>"
+ class="ldapVerifyInput"
+ title="Attempts to receive a DN for the given loginname and the current login filter"/>
+ <button class="ldapVerifyLoginName" name="ldapTestLoginSettings" type="button">
+ <?php p($l->t('Verify settings'));?>
+ </button>
+ </p>
<?php print_unescaped($_['wizardControls']); ?>
</div>
</fieldset> \ No newline at end of file
diff --git a/apps/user_ldap/templates/part.wizard-server.php b/apps/user_ldap/templates/part.wizard-server.php
index c1744143f98..3ce912fac4a 100644
--- a/apps/user_ldap/templates/part.wizard-server.php
+++ b/apps/user_ldap/templates/part.wizard-server.php
@@ -22,32 +22,41 @@
}
}
?>
- <option value="NEW"><?php p($l->t('Add Server Configuration'));?></option>
</select>
+ <button type="button" id="ldap_action_add_configuration"
+ name="ldap_action_add_configuration" class="icon-add"
+ title="Adds a new and blank configuration">&nbsp;</button>
+ <button type="button" id="ldap_action_copy_configuration"
+ name="ldap_action_copy_configuration"
+ class="ldapIconCopy icon-default-style"
+ title="Copy current configuration into new directory binding">&nbsp;</button>
<button type="button" id="ldap_action_delete_configuration"
- name="ldap_action_delete_configuration"><?php p($l->t('Delete Configuration'));?></button>
+ name="ldap_action_delete_configuration" class="icon-delete"
+ title="Delete the current configuration">&nbsp;</button>
</p>
<div class="hostPortCombinator">
<div class="tablerow">
<div class="tablecell">
<div class="table">
- <input type="text" class="host tablecell lwautosave" id="ldap_host"
+ <input type="text" class="host" id="ldap_host"
name="ldap_host"
placeholder="<?php p($l->t('Host'));?>"
title="<?php p($l->t('You can omit the protocol, except you require SSL. Then start with ldaps://'));?>"
/>
<span>
<input type="number" id="ldap_port" name="ldap_port"
- class="lwautosave"
placeholder="<?php p($l->t('Port'));?>" />
+ <button class="ldapDetectPort" name="ldapDetectPort" type="button">
+ <?php p($l->t('Detect Port'));?>
+ </button>
</span>
</div>
</div>
</div>
<div class="tablerow">
<input type="text" id="ldap_dn" name="ldap_dn"
- class="tablecell lwautosave"
+ class="tablecell"
placeholder="<?php p($l->t('User DN'));?>" autocomplete="off"
title="<?php p($l->t('The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty.'));?>"
/>
@@ -55,7 +64,7 @@
<div class="tablerow">
<input type="password" id="ldap_agent_password"
- class="tablecell lwautosave" name="ldap_agent_password"
+ class="tablecell" name="ldap_agent_password"
placeholder="<?php p($l->t('Password'));?>" autocomplete="off"
title="<?php p($l->t('For anonymous access, leave DN and Password empty.'));?>"
/>
@@ -63,15 +72,21 @@
<div class="tablerow">
<textarea id="ldap_base" name="ldap_base"
- class="tablecell lwautosave"
+ class="tablecell"
placeholder="<?php p($l->t('One Base DN per line'));?>"
title="<?php p($l->t('You can specify Base DN for users and groups in the Advanced tab'));?>">
</textarea>
+ <button class="ldapDetectBase" name="ldapDetectBase" type="button">
+ <?php p($l->t('Detect Base DN'));?>
+ </button>
+ <button class="ldapTestBase" name="ldapTestBase" type="button">
+ <?php p($l->t('Test Base DN'));?>
+ </button>
</div>
<div class="tablerow left">
<input type="checkbox" id="ldap_experienced_admin" value="1"
- name="ldap_experienced_admin" class="tablecell lwautosave"
+ name="ldap_experienced_admin" class="tablecell"
title="<?php p($l->t('Avoids automatic LDAP requests. Better for bigger setups, but requires some LDAP knowledge.'));?>"
/>
<label for="ldap_experienced_admin" class="tablecell">
diff --git a/apps/user_ldap/templates/part.wizard-userfilter.php b/apps/user_ldap/templates/part.wizard-userfilter.php
index 99a6e75370b..691c41a66a6 100644
--- a/apps/user_ldap/templates/part.wizard-userfilter.php
+++ b/apps/user_ldap/templates/part.wizard-userfilter.php
@@ -5,40 +5,61 @@
</p>
<p>
<label for="ldap_userfilter_objectclass">
- <?php p($l->t('only those object classes:'));?>
+ <?php p($l->t('Only these object classes:'));?>
</label>
<select id="ldap_userfilter_objectclass" multiple="multiple"
- name="ldap_userfilter_objectclass">
+ name="ldap_userfilter_objectclass" class="multiSelectPlugin">
</select>
</p>
<p>
+ <label></label>
+ <span class="ldapInputColElement"><?php p($l->t('The most common object classes for users are organizationalPerson, person, user, and inetOrgPerson. If you are not sure which object class to select, please consult your directory admin.'));?></span>
+ </p>
+ <p>
<label for="ldap_userfilter_groups">
- <?php p($l->t('only from those groups:'));?>
+ <?php p($l->t('Only from these groups:'));?>
</label>
+ <input type="text" class="ldapManyGroupsSupport ldapManyGroupsSearch hidden" placeholder="<?php p($l->t('Search groups'));?>" />
+
<select id="ldap_userfilter_groups" multiple="multiple"
- name="ldap_userfilter_groups">
+ name="ldap_userfilter_groups" class="multiSelectPlugin">
</select>
</p>
+ <p class="ldapManyGroupsSupport hidden">
+ <label></label>
+ <select class="ldapGroupList ldapGroupListAvailable" multiple="multiple"
+ title="<?php p($l->t('Available groups'));?>"></select>
+ <span>
+ <button class="ldapGroupListSelect" type="button">&gt;</button><br/>
+ <button class="ldapGroupListDeselect" type="button">&lt;</button>
+ </span>
+ <select class="ldapGroupList ldapGroupListSelected" multiple="multiple"
+ title="<?php p($l->t('Selected groups'));?>"></select>
+ </p>
<p>
- <label><a id='toggleRawUserFilter'>↓ <?php p($l->t('Edit raw filter instead'));?></a></label>
- </p>
- <p id="rawUserFilterContainer" class="invisible">
- <input type="text" id="ldap_userlist_filter" name="ldap_userlist_filter"
- class="lwautosave"
- placeholder="<?php p($l->t('Raw LDAP filter'));?>"
- title="<?php p($l->t('The filter specifies which LDAP users shall have access to the %s instance.', $theme->getName()));?>"
- />
- <button class="ldapGetEntryCount hidden" name="ldapGetEntryCount" type="button">
- <?php p($l->t('Test Filter'));?>
- </button>
+ <label><a id='toggleRawUserFilter' class='ldapToggle'>↓ <?php p($l->t('Edit LDAP Query'));?></a></label>
+ </p>
+ <p id="ldapReadOnlyUserFilterContainer" class="hidden ldapReadOnlyFilterContainer">
+ <label><?php p($l->t('LDAP Filter:'));?></label>
+ <span class="ldapFilterReadOnlyElement ldapInputColElement"></span>
+ </p>
+ <p id="rawUserFilterContainer">
+ <textarea type="text" id="ldap_userlist_filter" name="ldap_userlist_filter"
+ class="ldapFilterInputElement"
+ placeholder="<?php p($l->t('Edit LDAP Query'));?>"
+ title="<?php p($l->t('The filter specifies which LDAP users shall have access to the %s instance.', $theme->getName()));?>">
+ </textarea>
</p>
<p>
<div class="ldapWizardInfo invisible">&nbsp;</div>
</p>
<p class="ldap_count">
- <span id="ldap_user_count">0 <?php p($l->t('users found'));?></span>
+ <button class="ldapGetEntryCount ldapGetUserCount" name="ldapGetEntryCount" type="button">
+ <?php p($l->t('Verify settings and count users'));?>
+ </button>
+ <span id="ldap_user_count"></span>
</p>
<?php print_unescaped($_['wizardControls']); ?>
</div>
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index 6aa2183726b..833bef8c24d 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -65,5 +65,6 @@
<?php print_unescaped($_['settingControls']); ?>
</fieldset>
</div>
-
+ <!-- Spinner Template -->
+ <img class="ldapSpinner hidden" src="<?php p(\OCP\Util::imagePath('core', 'loading.gif')); ?>">
</form>
diff --git a/apps/user_ldap/templates/wizard-container.php b/apps/user_ldap/templates/wizard-container.php
new file mode 100644
index 00000000000..fbfa8899de6
--- /dev/null
+++ b/apps/user_ldap/templates/wizard-container.php
@@ -0,0 +1,3 @@
+<form id="ldapWizard" class="section" action="#" method="post">
+ <h2><?php p($l->t('LDAP2')); ?></h2>
+</form> \ No newline at end of file
diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php
index ea1371c14d3..54e14c093f3 100644
--- a/apps/user_ldap/user_ldap.php
+++ b/apps/user_ldap/user_ldap.php
@@ -79,14 +79,10 @@ class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserIn
* Check if the password is correct without logging in the user
*/
public function checkPassword($uid, $password) {
- $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');
- $users = $this->access->fetchListOfUsers($filter, $attrs);
+ $users = $this->access->fetchUsersByLoginName($uid, $attrs);
if(count($users) < 1) {
return false;
}