diff --git a/apps/user_ldap/ajax/getNewServerConfigPrefix.php b/apps/user_ldap/ajax/getNewServerConfigPrefix.php
index 7d1434a8fb..d013591788 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 ab521b5bf0..267b9568a2 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 8f0916f768..a918a2aa18 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 8f339451c6..b351f9ae2a 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 0000000000..283d627a5a
Binary files /dev/null and b/apps/user_ldap/img/copy.png differ
diff --git a/apps/user_ldap/img/copy.svg b/apps/user_ldap/img/copy.svg
new file mode 100644
index 0000000000..2e19d8066e
--- /dev/null
+++ b/apps/user_ldap/img/copy.svg
@@ -0,0 +1,120 @@
+
+
diff --git a/apps/user_ldap/js/experiencedAdmin.js b/apps/user_ldap/js/experiencedAdmin.js
deleted file mode 100644
index 7dc5a4e503..0000000000
--- a/apps/user_ldap/js/experiencedAdmin.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * Copyright (c) 2014, Arthur Schiwon
- * 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 dc65858217..0000000000
--- 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 768d62a18d..0000000000
--- 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 = '';
- $('#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: '',
- 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(
- "");
- }
- 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("");
- }
- 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("");
- }
- 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 0000000000..c3f1e85b59
--- /dev/null
+++ b/apps/user_ldap/js/wizard/configModel.js
@@ -0,0 +1,606 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..7c1f0d5d81
--- /dev/null
+++ b/apps/user_ldap/js/wizard/controller.js
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..8eb10c5801
--- /dev/null
+++ b/apps/user_ldap/js/wizard/view.js
@@ -0,0 +1,433 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..faa9de918a
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizard.js
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..f027235174
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorAvailableAttributes.js
@@ -0,0 +1,59 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..70b9923e58
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorBaseDN.js
@@ -0,0 +1,52 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..c6ef0a9cab
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorClearGroupMappings.js
@@ -0,0 +1,30 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..0e4811b39e
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorClearUserMappings.js
@@ -0,0 +1,30 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..5f17773468
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorEmailAttribute.js
@@ -0,0 +1,38 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..e025d8d624
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorFeatureAbstract.js
@@ -0,0 +1,52 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..cca889839e
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorFilterGroup.js
@@ -0,0 +1,31 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..310f261e05
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorFilterLogin.js
@@ -0,0 +1,32 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..63dff4e298
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorFilterUser.js
@@ -0,0 +1,31 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..fd80018943
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorGeneric.js
@@ -0,0 +1,117 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..12d7df7514
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorGroupCount.js
@@ -0,0 +1,27 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..6d6048b798
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorGroupObjectClasses.js
@@ -0,0 +1,29 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..fbb3f02e10
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorGroupsForGroups.js
@@ -0,0 +1,29 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..fe67854c79
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorGroupsForUsers.js
@@ -0,0 +1,29 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..ba07518966
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorPort.js
@@ -0,0 +1,44 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..448dfc1803
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorQueue.js
@@ -0,0 +1,89 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..37e41f42a6
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorSimpleRequestAbstract.js
@@ -0,0 +1,44 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..df0b0a2200
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorTestAbstract.js
@@ -0,0 +1,63 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..52848819bd
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorTestBaseDN.js
@@ -0,0 +1,29 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..1308c18290
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorTestConfiguration.js
@@ -0,0 +1,31 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..cf992df43b
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorTestLoginName.js
@@ -0,0 +1,30 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..bcff2cf3b1
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorUserCount.js
@@ -0,0 +1,26 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..ae734480c1
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorUserDisplayNameAttribute.js
@@ -0,0 +1,39 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..953a0b909a
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorUserGroupAssociation.js
@@ -0,0 +1,40 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..0fa324a080
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardDetectorUserObjectClasses.js
@@ -0,0 +1,29 @@
+
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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 0000000000..f3f1368982
--- /dev/null
+++ b/apps/user_ldap/js/wizard/wizardFilterOnType.js
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2015, Arthur Schiwon
+ * 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($('
@@ -55,7 +64,7 @@
@@ -63,15 +72,21 @@
+
+
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index 6aa2183726..833bef8c24 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -65,5 +65,6 @@
-
+
+
diff --git a/apps/user_ldap/templates/wizard-container.php b/apps/user_ldap/templates/wizard-container.php
new file mode 100644
index 0000000000..fbfa8899de
--- /dev/null
+++ b/apps/user_ldap/templates/wizard-container.php
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php
index ea1371c14d..54e14c093f 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;
}