From 5064cf5742e8ab0acdaa6f4f795b41ae7a9b57cc Mon Sep 17 00:00:00 2001 From: Saket Patel Date: Thu, 4 Jul 2013 03:22:31 +0530 Subject: [PATCH] added most of the basic functionalities --- build.xml | 1 + config.php | 2 +- js/PasswdPanel.js | 41 +++++++- js/data/PasswdResponseHandler.js | 54 +++++++++++ lib/PasswordMeter.js | 158 +++++++++++++++++++++++++++++++ manifest.xml | 14 +++ php/class.passwdmodule.php | 150 +++++++++++++++++++---------- 7 files changed, 364 insertions(+), 56 deletions(-) create mode 100644 js/data/PasswdResponseHandler.js create mode 100644 lib/PasswordMeter.js diff --git a/build.xml b/build.xml index e283f2d..ee538f7 100644 --- a/build.xml +++ b/build.xml @@ -185,6 +185,7 @@ + diff --git a/config.php b/config.php index b015301..a9c340c 100644 --- a/config.php +++ b/config.php @@ -3,7 +3,7 @@ define('PLUGIN_PASSWD_USER_DEFAULT_ENABLE', true); /** Define zarafa installtion uses LDAP **/ -define('PLUGIN_PASSWD_LDAP', true); +define('PLUGIN_PASSWD_LDAP', false); /** Base DN to access LDAP users **/ define('PLUGIN_PASSWD_LDAP_BASEDN', 'dc=example,dc=com'); diff --git a/js/PasswdPanel.js b/js/PasswdPanel.js index 18bdeca..1bb2476 100644 --- a/js/PasswdPanel.js +++ b/js/PasswdPanel.js @@ -10,6 +10,8 @@ Zarafa.plugins.passwd.PasswdPanel = Ext.extend(Ext.form.FormPanel, { /** * @property * @type Ext.LoadMask + * Save mask that will be displayed when request has been sent to server for password change + * and waiting for the response. */ saveMask : undefined, @@ -63,6 +65,10 @@ Zarafa.plugins.passwd.PasswdPanel = Ext.extend(Ext.form.FormPanel, { this.on('afterrender', this.initialize, this); }, + /** + * Function will initialize this dialog with some default values and will + * also create object of {@link #saveMask}. + */ initialize : function() { this.userNameField.setValue(container.getUser().getUserName()); @@ -72,24 +78,51 @@ Zarafa.plugins.passwd.PasswdPanel = Ext.extend(Ext.form.FormPanel, { }) }, + /** + * Handler function that will be called when user presses ok button + * to change password. + */ onOk : function() { - // send request - + // show load mask this.saveMask.show(); + // send request container.getRequest().singleRequest('passwdmodule', 'save', { username : this.userNameField.getValue(), current_password : this.oldPasswdField.getValue(), new_password : this.newPasswdField.getValue(), new_password_repeat : this.newPasswdRepeatField.getValue() - //}, new Zarafa.plugins.sugarcrm.data.SugarCRMResponseHandler()); - }); + }, new Zarafa.plugins.passwd.data.PasswdResponseHandler({ + callbackFn : this.callbackFn, + scope : this + })); }, + /** + * Handler function that will be called when user presses cancel button + * to close the dialog. + */ onCancel : function() { + // close the dialog this.dialog.close(); + }, + + /** + * Callback function that will be executed after response is received from server. + * @param {Boolean} success boolean to indicate response contains success/failure data. + * @param {Object} response response sent by server. + */ + callbackFn : function(success, response) + { + // hide load mask + this.saveMask.hide(); + + // close the dialog + if(success) { + this.dialog.close(); + } } }); diff --git a/js/data/PasswdResponseHandler.js b/js/data/PasswdResponseHandler.js new file mode 100644 index 0000000..0577515 --- /dev/null +++ b/js/data/PasswdResponseHandler.js @@ -0,0 +1,54 @@ +Ext.namespace('Zarafa.plugins.passwd.data'); + +/** + * @class Zarafa.plugins.passwd.data.ResponseHandler + * @extends Zarafa.core.data.AbstractResponseHandler + * + * Passwd plugin specific response handler. + */ +Zarafa.plugins.passwd.data.PasswdResponseHandler = Ext.extend(Zarafa.core.data.AbstractResponseHandler, { + + /** + * @cfg {Function} callbackFn The function which will be called after success/failure response. + */ + callbackFn : undefined, + + /** + * @cfg {Object} scope The function scope that will be used when calling {@link #callbackFn}. + */ + scope : undefined, + + /** + * In case exception happened on server, server will return exception response with the display message. + * @param {Object} response Object contained the response data. + */ + doError : function(response) + { + var displayMessage = _('An unknown error occurred while changing password.'); + + if(response.info) { + displayMessage = response.info.display_message; + } + + Ext.MessageBox.alert(_('Error'), displayMessage); + + this.callbackFn.apply(this.scope || this, [ false, response ]); + }, + + /** + * When password change is successfull server will send a success response including display message. + * @param {Object} response Object contained the response data. + */ + doSuccess : function(response) + { + var displayMessage = _('Password is changed successfully.'); + + if(response.info) { + displayMessage = response.info.display_message; + } + + Ext.MessageBox.alert(_('Success'), displayMessage); + + this.callbackFn.apply(this.scope || this, [ true, response ]); + } +}); \ No newline at end of file diff --git a/lib/PasswordMeter.js b/lib/PasswordMeter.js new file mode 100644 index 0000000..7406beb --- /dev/null +++ b/lib/PasswordMeter.js @@ -0,0 +1,158 @@ +// Create user extensions namespace (Ext.ux) +Ext.namespace('Ext.ux'); + +/** + * Ext.ux.PasswordMeter Extension Class + * + * @author Eelco Wiersma + * @version 0.2 + * + * Algorithm based on code of Tane + * http://digitalspaghetti.me.uk/index.php?q=jquery-pstrength + * and Steve Moitozo + * http://www.geekwisdom.com/dyn/passwdmeter + * + * @license MIT License: http://www.opensource.org/licenses/mit-license.php + * + * @class Ext.ux.PasswordMeter + * @extends Ext.form.TextField + * @constructor + * Creates new Ext.ux.PasswordMeter + */ +Ext.ux.PasswordMeter = function(config) { + + // call parent constructor + Ext.ux.PasswordMeter.superclass.constructor.call(this, config); + +}; + +Ext.extend(Ext.ux.PasswordMeter, Ext.form.TextField, { + /** + * @cfg {String} inputType The type attribute for input fields -- e.g. text, password (defaults to "password"). + */ + inputType: 'text', + // private + onRender: function(ct, position) { + Ext.ux.PasswordMeter.superclass.onRender.call(this, ct, position); + + var elp = this.el.findParent('.x-form-element', 5, true); + this.objMeter = ct.createChild({tag: "div", 'class': "strengthMeter"}); + + this.objMeter.setWidth(elp.getWidth(true)-17); + this.scoreBar = this.objMeter.createChild({tag: "div", 'class': "scoreBar"}); + + if(Ext.isIE && !Ext.isIE7) { // Fix style for IE6 + this.objMeter.setStyle('margin-left', '3px'); + } + }, + // private + initEvents: function() { + Ext.ux.PasswordMeter.superclass.initEvents.call(this); + + this.el.on('keyup', this.updateMeter, this); + }, + /** + * Sets the width of the meter, based on the score + * @param {Object} e + * Private function + */ + updateMeter: function(e) { + var score = 0 + var p = e.target.value; + + var maxWidth = this.objMeter.getWidth() - 2; + + var nScore = this.calcStrength(p); + + // Set new width + var nRound = Math.round(nScore * 2); + + if (nRound > 100) { + nRound = 100; + } + + var scoreWidth = (maxWidth / 100) * nRound; + this.scoreBar.setWidth(scoreWidth, true); + }, + /** + * Calculates the strength of a password + * @param {Object} p The password that needs to be calculated + * @return {int} intScore The strength score of the password + */ + calcStrength: function(p) { + var intScore = 0; + + // PASSWORD LENGTH + intScore += p.length; + + if(p.length > 0 && p.length <= 4) { // length 4 or less + intScore += p.length; + } + else if (p.length >= 5 && p.length <= 7) { // length between 5 and 7 + intScore += 6; + } + else if (p.length >= 8 && p.length <= 15) { // length between 8 and 15 + intScore += 12; + //alert(intScore); + } + else if (p.length >= 16) { // length 16 or more + intScore += 18; + //alert(intScore); + } + + // LETTERS (Not exactly implemented as dictacted above because of my limited understanding of Regex) + if (p.match(/[a-z]/)) { // [verified] at least one lower case letter + intScore += 1; + } + if (p.match(/[A-Z]/)) { // [verified] at least one upper case letter + intScore += 5; + } + // NUMBERS + if (p.match(/\d/)) { // [verified] at least one number + intScore += 5; + } + if (p.match(/.*\d.*\d.*\d/)) { // [verified] at least three numbers + intScore += 5; + } + + // SPECIAL CHAR + if (p.match(/[!,@,#,$,%,^,&,*,?,_,~]/)) { // [verified] at least one special character + intScore += 5; + } + // [verified] at least two special characters + if (p.match(/.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~]/)) { + intScore += 5; + } + + // COMBOS + if (p.match(/(?=.*[a-z])(?=.*[A-Z])/)) { // [verified] both upper and lower case + intScore += 2; + } + if (p.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/)) { // [verified] both letters and numbers + intScore += 2; + } + // [verified] letters, numbers, and special characters + if (p.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!,@,#,$,%,^,&,*,?,_,~])/)) { + intScore += 2; + } + + return intScore; + + }, + // private + onFocus: function() { + Ext.ux.PasswordMeter.superclass.onFocus.call(this); + + if(!Ext.isOpera) { // don't touch in Opera + this.objMeter.addClass('strengthMeter-focus'); + } + }, + // private + onBlur: function() { + Ext.ux.PasswordMeter.superclass.onBlur.call(this); + + if(!Ext.isOpera) { // don't touch in Opera + this.objMeter.removeClass('strengthMeter-focus'); + } + } +}); \ No newline at end of file diff --git a/manifest.xml b/manifest.xml index c39dcd9..53b8cc3 100644 --- a/manifest.xml +++ b/manifest.xml @@ -13,6 +13,19 @@ config.php + @@ -25,6 +38,7 @@ js/PasswdPlugin.js js/PasswdContentPanel.js js/PasswdPanel.js + js/data/PasswdResponseHandler.js js/ABOUT.js