mirror of
https://github.com/silentsakky/zarafa-webapp-passwd
synced 2026-08-07 16:01:56 +02:00
Compare commits
31 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e919be0553 | ||
|
|
8310d7fb12 | ||
|
|
fffa1ddbbb | ||
|
|
3bcef6e388 | ||
|
|
a9549464e9 | ||
|
|
3cafedcf3a | ||
|
|
dd305cca3b | ||
|
|
db34d7f872 | ||
|
|
2e39b60f5b | ||
|
|
a0b6a813fc | ||
|
|
f0756b10ce | ||
|
|
eefb5fbc96 | ||
|
|
bc3800e618 | ||
|
|
3978f311da | ||
|
|
33d35759a3 | ||
|
|
ceebc4174e | ||
|
|
d5a505c131 | ||
|
|
e177d9a30a | ||
|
|
2aea28c4f9 | ||
|
|
589cd7a3b0 | ||
|
|
95615a68c4 | ||
|
|
7badd3b802 | ||
|
|
4f16e8cdc0 | ||
|
|
9083de7790 | ||
|
|
c8b27fe56a | ||
|
|
739b1da2ac | ||
|
|
1161ec7a32 | ||
|
|
6f047d4c7f | ||
|
|
4a3d715321 | ||
|
|
dead7d6955 | ||
|
|
bdc7071085 |
24 changed files with 782 additions and 298 deletions
15
CHANGELOG.md
15
CHANGELOG.md
|
|
@ -1,3 +1,18 @@
|
|||
## 1.0 (17th Dec 2013)
|
||||
|
||||
- Password change functionality when using DB or LDAP plugin
|
||||
|
||||
## 1.1 (19th Dec 2013)
|
||||
|
||||
- Bug fixes for LDAP plugin
|
||||
|
||||
## 1.2 (20th May 2015)
|
||||
|
||||
- Bug fixes for LDAP plugin
|
||||
- Improved UI
|
||||
|
||||
## 1.3 (6th July 2017)
|
||||
|
||||
- Add config to enable/disable strict password checking
|
||||
- use encryptionstore to retrieve/store passwords
|
||||
- move strict password checking to client side
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
Zarafa Webapp Password Change Plugin
|
||||
Copyright (C) 2013 Saket Patel silentsakky@gmail.com
|
||||
Copyright (C) 2013 - 2017 Saket Patel <silentsakky@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
32
README.md
32
README.md
|
|
@ -7,32 +7,46 @@ This plugin is largely based on the Passwd plugin by Andreas Brodowski.
|
|||
For his original work check this [link](https://community.zarafa.com/pg/plugins/project/157/developer/dw2412/passwd-plugin)
|
||||
|
||||
## How to install
|
||||
1. If you want to use this plugin with production / debug version of webapp then please download package from [community](https://community.zarafa.com/pg/plugins/project/23147/developer/silentsakky/webapp-password-change)
|
||||
1. If you want to use this plugin with production / debug version of webapp then please download package from [release page](https://github.com/silentsakky/zarafa-webapp-passwd/releases)
|
||||
2. If you want to use this plugin with source copy of webapp then you can just download this whole project
|
||||
3. Extract contents of this plugin to <webapp_path>/plugins directory
|
||||
3. Extract contents of this plugin to <webapp_path>/plugins directory, in Ubuntu 16 <webapp_path> refers to /usr/share/kopano-webapp
|
||||
4. Give read permissions to apache for <webapp_path>/plugins/passwd directory
|
||||
5. If you are using LDAP plugin then change PLUGIN_PASSWD_LDAP to true and also set proper values for PLUGIN_PASSWD_LDAP_BASEDN and PLUGIN_PASSWD_LDAP_URI configurations
|
||||
6. If you are using DB plugin then no need to change anything, default configurations should be fine
|
||||
5. Restart apache, reload webapp after clearing cache
|
||||
6. If you want to enable this plugin by default for all users then edit config.php file and change PLUGIN_PASSWD_USER_DEFAULT_ENABLE setting to true
|
||||
|
||||
|
||||
## How to enable
|
||||
1. Go to settings section
|
||||
2. Go to Plugins tab
|
||||
3. Enable password change plugin and reload webapp
|
||||
4. Go to Change Password tab of settings section
|
||||
5. Provide current password and new password
|
||||
6. Click on apply
|
||||
|
||||
|
||||
## How to disable
|
||||
1. Go to settings section
|
||||
2. Go to Plugins tab
|
||||
3. Disable password change plugin and reload webapp
|
||||
|
||||
|
||||
## How to use
|
||||
1. Go to Change Password tab of settings section
|
||||
2. Provide current password and new password
|
||||
3. Click on apply
|
||||
|
||||
|
||||
## Notes
|
||||
- Feedback/Bug Reports are welcome
|
||||
- If anyone is good at creating icons then please help me add a good icon to change password tab (credits will be given)
|
||||
- thanks to h44z for adding password meter and icon for the plugin
|
||||
|
||||
## Todo
|
||||
- Add password strength meter on client side, so user can create complex passwords
|
||||
- Check on client side for empty fields
|
||||
|
||||
## Dependencies:
|
||||
- php ldap extension is required if you are using LDAP plugin
|
||||
- if you have ubuntu 16 then follow below steps (this should ideally work with all distros)
|
||||
1) sudo apt-get install php-ldap
|
||||
2) sudo phpenmod ldap
|
||||
3) check if ldap extension is enabled using below command
|
||||
php -i "(command-line 'phpinfo()')" | grep ldap
|
||||
|
||||
|
||||
Initially releases of this plugin were maintained in [community](https://community.zarafa.com/pg/plugins/project/23147/developer/silentsakky/webapp-password-change), but now users can download latest builds from [github release page](https://github.com/silentsakky/zarafa-webapp-passwd/releases)
|
||||
48
build.xml
48
build.xml
|
|
@ -3,6 +3,7 @@
|
|||
<property name="root-folder" value="${basedir}/../../"/>
|
||||
<property name="tools-folder" value="${root-folder}/tools/"/>
|
||||
<property name="target-folder" value="${root-folder}/deploy/plugins"/>
|
||||
<property name="language-folder" value="${basedir}/language"/>
|
||||
|
||||
<import file="${tools-folder}/antutil.xml"/>
|
||||
|
||||
|
|
@ -42,6 +43,10 @@
|
|||
<include name="${plugin-file}"/>
|
||||
<include name="${plugin-debugfile}"/>
|
||||
</fileset>
|
||||
<!-- Delete the .mo files -->
|
||||
<fileset dir="${language-folder}">
|
||||
<include name="**/LC_MESSAGES/*.mo"/>
|
||||
</fileset>
|
||||
</delete>
|
||||
</target>
|
||||
|
||||
|
|
@ -156,8 +161,40 @@
|
|||
</exec>
|
||||
</target>
|
||||
|
||||
<!-- Generate language files -->
|
||||
<target name="language">
|
||||
<if>
|
||||
<available file="msgfmt" filepath="${env.PATH}" />
|
||||
<then>
|
||||
<foreach target="msgfmt" param="file">
|
||||
<path>
|
||||
<fileset dir="${language-folder}">
|
||||
<include name="**/LC_MESSAGES/*.po"/>
|
||||
</fileset>
|
||||
</path>
|
||||
</foreach>
|
||||
</then>
|
||||
<else>
|
||||
<echo message="WARNING: msgfmt not available, not generating *.mo files for translations"/>
|
||||
</else>
|
||||
</if>
|
||||
</target>
|
||||
|
||||
<target name="msgfmt">
|
||||
<propertyregex property="outfile" input="${file}" regexp=".*\/(language\/.*)\.po" replace="${target-folder}/${plugin-folder}/\1\.mo"/>
|
||||
<echo message="Converting ${file} to ${outfile}"/>
|
||||
<dirname property="outdir" file="${outfile}"/>
|
||||
<mkdir dir="${outdir}"/>
|
||||
<exec executable="msgfmt" failonerror="true">
|
||||
<arg value="-v"/>
|
||||
<arg value="-o"/>
|
||||
<arg value="${outfile}"/>
|
||||
<arg value="${file}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<!-- Install all files into the target folder -->
|
||||
<target name="deploy" depends="compress, validate">
|
||||
<target name="deploy" depends="compress, validate, language">
|
||||
<mkdir dir="${target-folder}/${plugin-folder}"/>
|
||||
|
||||
<!-- Copy (and validate) manifest.xml -->
|
||||
|
|
@ -193,7 +230,16 @@
|
|||
<exclude name="build.xml"/>
|
||||
<!-- CSS is generated during build -->
|
||||
<exclude name="resources/css/*.*"/>
|
||||
<exclude name="**/LC_MESSAGES/*.po"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<!-- Create zip file for release (ant -Drelease=true) -->
|
||||
<if>
|
||||
<isset property="release" />
|
||||
<then>
|
||||
<zip destfile="${target-folder}/${plugin}.zip" update="true" basedir="${target-folder}/${plugin}" />
|
||||
</then>
|
||||
</if>
|
||||
</target>
|
||||
</project>
|
||||
|
|
|
|||
Binary file not shown.
20
config.php
20
config.php
|
|
@ -2,12 +2,28 @@
|
|||
/** Enable the passwd plugin for all clients **/
|
||||
define('PLUGIN_PASSWD_USER_DEFAULT_ENABLE', false);
|
||||
|
||||
/** Define zarafa installtion uses LDAP **/
|
||||
/** Enable the passwd plugin for all clients **/
|
||||
define('PLUGIN_PASSWD_STRICT_CHECK_ENABLE', true);
|
||||
|
||||
/** Define passwd plugin installation uses LDAP **/
|
||||
define('PLUGIN_PASSWD_LDAP', false);
|
||||
|
||||
/** Base DN to access LDAP users **/
|
||||
define('PLUGIN_PASSWD_LDAP_BASEDN', 'dc=example,dc=com');
|
||||
|
||||
/** URI to access LDAP server **/
|
||||
define('PLUGIN_PASSWD_LDAP_URI', 'localhost');
|
||||
define('PLUGIN_PASSWD_LDAP_URI', 'ldap://localhost');
|
||||
|
||||
/** Use TLS to access LDAP server **/
|
||||
define('PLUGIN_PASSWD_LDAP_USE_TLS', true);
|
||||
|
||||
/** Bind DN to access LDAP server (keep empty for anonymous bind) **/
|
||||
define('PLUGIN_PASSWD_LDAP_BIND_DN', "");
|
||||
|
||||
/** Bind password to access LDAP server (keep empty for anonymous bind) **/
|
||||
define('PLUGIN_PASSWD_LDAP_BIND_PW', "");
|
||||
|
||||
/** Set to true if you login with username@tenantname **/
|
||||
define('PLUGIN_PASSWD_LOGIN_WITH_TENANT', false);
|
||||
|
||||
?>
|
||||
|
|
@ -6,7 +6,7 @@ Ext.namespace('Zarafa.plugins.passwd');
|
|||
* The copyright string holding the copyright notice for the Zarafa passwd Plugin.
|
||||
*/
|
||||
Zarafa.plugins.passwd.ABOUT = ""
|
||||
+ "<p>Copyright (C) 2013 Saket Patel <silentsakky@gmail.com></p>"
|
||||
+ "<p>Copyright (C) 2013 - 2017 Saket Patel <silentsakky@gmail.com></p>"
|
||||
|
||||
+ "<p>This program is free software: you can redistribute it and/or modify "
|
||||
+ "it under the terms of the GNU Affero General Public License as "
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ Zarafa.plugins.passwd.PasswdPlugin = Ext.extend(Zarafa.core.Plugin, {
|
|||
Zarafa.onReady(function() {
|
||||
container.registerPlugin(new Zarafa.core.PluginMetaData({
|
||||
name : 'passwd',
|
||||
displayName : _('Password Change Plugin'),
|
||||
displayName : dgettext("plugin_passwd", 'Password Change Plugin'),
|
||||
about : Zarafa.plugins.passwd.ABOUT,
|
||||
pluginConstructor : Zarafa.plugins.passwd.PasswdPlugin
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@ Zarafa.plugins.passwd.data.PasswdResponseHandler = Ext.extend(Zarafa.core.data.A
|
|||
*/
|
||||
doError : function(response)
|
||||
{
|
||||
var displayMessage = _('An unknown error occurred while changing password.');
|
||||
var displayMessage = dgettext("plugin_passwd", 'An unknown error occurred while changing password.');
|
||||
|
||||
if(response.info) {
|
||||
displayMessage = response.info.display_message;
|
||||
}
|
||||
|
||||
Ext.MessageBox.alert(_('Error'), displayMessage);
|
||||
Ext.MessageBox.alert(dgettext("plugin_passwd", 'Error'), displayMessage);
|
||||
|
||||
this.callbackFn.apply(this.scope || this, [ false, response ]);
|
||||
},
|
||||
|
|
@ -41,13 +41,13 @@ Zarafa.plugins.passwd.data.PasswdResponseHandler = Ext.extend(Zarafa.core.data.A
|
|||
*/
|
||||
doSuccess : function(response)
|
||||
{
|
||||
var displayMessage = _('Password is changed successfully.');
|
||||
var displayMessage = dgettext("plugin_passwd", 'Password is changed successfully.');
|
||||
|
||||
if(response.info) {
|
||||
displayMessage = response.info.display_message;
|
||||
}
|
||||
|
||||
Ext.MessageBox.alert(_('Success'), displayMessage);
|
||||
Ext.MessageBox.alert(dgettext("plugin_passwd", 'Success'), displayMessage);
|
||||
|
||||
this.callbackFn.apply(this.scope || this, [ true, response ]);
|
||||
}
|
||||
|
|
|
|||
192
js/external/PasswordMeter.js
vendored
Normal file
192
js/external/PasswordMeter.js
vendored
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
Ext.namespace('Ext.ux.form.field');
|
||||
|
||||
/**
|
||||
* @class Ext.ux.form.field.PasswordMeter
|
||||
* @extends Ext.form.TextField
|
||||
* @xtype ux.passwordmeterfield
|
||||
*
|
||||
* @author Christoph Haas <christoph.h@sprinternet.at>
|
||||
* @version 0.1
|
||||
* @license MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* This implementation of the password fields shows a nice graph of how
|
||||
* secure the password is.
|
||||
* Original implementation for ExtJS 1.1 from http://testcases.pagebakers.com/PasswordMeter/.
|
||||
*/
|
||||
Ext.ux.form.field.PasswordMeter = Ext.extend(Ext.form.TextField, {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Object} config configuration object
|
||||
*/
|
||||
constructor : function(config)
|
||||
{
|
||||
config = config || {};
|
||||
|
||||
Ext.applyIf(config, {
|
||||
xtype : 'ux.passwordmeterfield',
|
||||
inputType: 'password',
|
||||
enableKeyEvents: true
|
||||
});
|
||||
|
||||
Ext.ux.form.field.PasswordMeter.superclass.constructor.call(this, config);
|
||||
},
|
||||
|
||||
// private
|
||||
initComponent:function()
|
||||
{
|
||||
Ext.ux.form.field.PasswordMeter.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
// private
|
||||
reset: function()
|
||||
{
|
||||
Ext.ux.form.field.PasswordMeter.superclass.reset.call(this);
|
||||
this.updateMeter();
|
||||
},
|
||||
|
||||
// private
|
||||
onKeyUp : function(event)
|
||||
{
|
||||
Ext.ux.form.field.PasswordMeter.superclass.onKeyUp.call(this);
|
||||
|
||||
this.updateMeter(this.getValue());
|
||||
|
||||
this.fireEvent('keyup', this, event);
|
||||
},
|
||||
|
||||
// private
|
||||
afterRender: function()
|
||||
{
|
||||
Ext.ux.form.field.PasswordMeter.superclass.afterRender.call(this);
|
||||
|
||||
|
||||
var width = this.getEl().getWidth();
|
||||
var newID = Ext.id();
|
||||
this.strengthMeterID = newID;
|
||||
this.scoreBarID = Ext.id();
|
||||
var objMeter = Ext.DomHelper.insertAfter(this.getEl(), {
|
||||
tag: "div",
|
||||
'class': "x-form-strengthmeter",
|
||||
'id': this.strengthMeterID,
|
||||
'style' : {
|
||||
width: width + 'px'
|
||||
}
|
||||
});
|
||||
Ext.DomHelper.append(objMeter, {
|
||||
tag: "div",
|
||||
'class': "x-form-strengthmeter-scorebar",
|
||||
'id': this.scoreBarID
|
||||
});
|
||||
|
||||
this.fireEvent('afterrender', this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the score of the entered password.
|
||||
* It is a number between 0 and 100 where 100 is a very safe password.
|
||||
*
|
||||
* @returns {Number}
|
||||
*/
|
||||
getScore : function()
|
||||
{
|
||||
return this.calcStrength(this.getValue());
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the width of the meter, based on the score
|
||||
*
|
||||
* @param {String} val The current password
|
||||
*/
|
||||
updateMeter : function(val)
|
||||
{
|
||||
var maxWidth, score, scoreWidth, objMeter, scoreBar;
|
||||
|
||||
objMeter = Ext.get(this.strengthMeterID);
|
||||
scoreBar = Ext.get(this.scoreBarID);
|
||||
|
||||
maxWidth = objMeter.getWidth();
|
||||
if (val){
|
||||
score = this.calcStrength(val);
|
||||
scoreWidth = maxWidth - (maxWidth / 100) * score;
|
||||
scoreBar.applyStyles({margin: "0 0 0 " + (maxWidth - scoreWidth) + "px"}); // move the overlay to the right
|
||||
scoreBar.setWidth(scoreWidth, false); // downsize the overlay
|
||||
} else {
|
||||
scoreBar.applyStyles({margin: "0"});
|
||||
scoreBar.setWidth(maxWidth, false);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
// PASSWORD LENGTH
|
||||
var len = p.length, score = len;
|
||||
|
||||
if (len > 0 && len <= 4) { // length 4 or
|
||||
// less
|
||||
score += len
|
||||
} else if (len >= 5 && len <= 7) {
|
||||
// length between 5 and 7
|
||||
score += 6;
|
||||
} else if (len >= 8 && len <= 15) {
|
||||
// length between 8 and 15
|
||||
score += 12;
|
||||
} else if (len >= 16) { // length 16 or more
|
||||
score += 18;
|
||||
}
|
||||
|
||||
// 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
|
||||
score += 1;
|
||||
}
|
||||
if (p.match(/[A-Z]/)) { // [verified] at least one upper
|
||||
// case letter
|
||||
score += 5;
|
||||
}
|
||||
// NUMBERS
|
||||
if (p.match(/\d/)) { // [verified] at least one
|
||||
// number
|
||||
score += 5;
|
||||
}
|
||||
if (p.match(/(?:.*?\d){3}/)) {
|
||||
// [verified] at least three numbers
|
||||
score += 5;
|
||||
}
|
||||
|
||||
// SPECIAL CHAR
|
||||
if (p.match(/[\!,@,#,$,%,\^,&,\*,\?,_,~]/)) {
|
||||
// [verified] at least one special character
|
||||
score += 5;
|
||||
}
|
||||
// [verified] at least two special characters
|
||||
if (p.match(/(?:.*?[\!,@,#,$,%,\^,&,\*,\?,_,~]){2}/)) {
|
||||
score += 5;
|
||||
}
|
||||
|
||||
// COMBOS
|
||||
if (p.match(/(?=.*[a-z])(?=.*[A-Z])/)) {
|
||||
// [verified] both upper and lower case
|
||||
score += 2;
|
||||
}
|
||||
if (p.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/)) {
|
||||
// [verified] both letters and numbers
|
||||
score += 2;
|
||||
}
|
||||
// [verified] letters, numbers, and special characters
|
||||
if (p.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\!,@,#,$,%,\^,&,\*,\?,_,~])/)) {
|
||||
score += 2;
|
||||
}
|
||||
|
||||
return Math.min(Math.round(score * 2), 100);
|
||||
}
|
||||
});
|
||||
|
||||
Ext.reg('ux.passwordmeterfield', Ext.ux.form.field.PasswordMeter);
|
||||
|
|
@ -18,7 +18,7 @@ Zarafa.plugins.passwd.settings.PasswdPanel = Ext.extend(Ext.form.FormPanel, {
|
|||
|
||||
Ext.applyIf(config, {
|
||||
xtype : 'zarafa.passwdpanel',
|
||||
labelWidth : 150,
|
||||
labelWidth : 200,
|
||||
defaults : {
|
||||
width : 200
|
||||
},
|
||||
|
|
@ -26,30 +26,34 @@ Zarafa.plugins.passwd.settings.PasswdPanel = Ext.extend(Ext.form.FormPanel, {
|
|||
items : [{
|
||||
xtype : 'displayfield',
|
||||
name : 'username',
|
||||
fieldLabel : 'User name'
|
||||
fieldLabel : dgettext("plugin_passwd", 'User name')
|
||||
}, {
|
||||
xtype : 'textfield',
|
||||
name : 'current_password',
|
||||
fieldLabel : 'Current password',
|
||||
ref : 'current_password',
|
||||
fieldLabel : dgettext("plugin_passwd", 'Current password'),
|
||||
inputType : 'password',
|
||||
allowBlank : false,
|
||||
listeners : {
|
||||
change : this.onFieldChange,
|
||||
scope : this
|
||||
}
|
||||
}, {
|
||||
xtype : 'textfield',
|
||||
xtype : 'ux.passwordmeterfield',
|
||||
name : 'new_password',
|
||||
fieldLabel : 'New password',
|
||||
inputType : 'password',
|
||||
ref : 'new_password',
|
||||
allowBlank : false,
|
||||
fieldLabel : dgettext("plugin_passwd", 'New password'),
|
||||
listeners : {
|
||||
change : this.onFieldChange,
|
||||
scope : this
|
||||
}
|
||||
}, {
|
||||
xtype : 'textfield',
|
||||
xtype : 'ux.passwordmeterfield',
|
||||
name : 'new_password_repeat',
|
||||
fieldLabel : 'Retype new password',
|
||||
inputType : 'password',
|
||||
allowBlank : false,
|
||||
ref : 'new_password_repeat',
|
||||
fieldLabel : dgettext("plugin_passwd", 'Retype new password'),
|
||||
listeners : {
|
||||
change : this.onFieldChange,
|
||||
scope : this
|
||||
|
|
|
|||
|
|
@ -17,13 +17,16 @@ Zarafa.plugins.passwd.settings.SettingsPasswdCategory = Ext.extend(Zarafa.settin
|
|||
config = config || {};
|
||||
|
||||
Ext.applyIf(config, {
|
||||
title : _('Change Password'),
|
||||
title : dgettext("plugin_passwd", 'Change Password'),
|
||||
categoryIndex : 9997,
|
||||
iconCls : 'zarafa-settings-category-passwd',
|
||||
xtype : 'zarafa.settingspasswdcategory',
|
||||
items : [{
|
||||
xtype : 'zarafa.settingspasswdwidget',
|
||||
settingsContext : config.settingsContext
|
||||
}]
|
||||
},
|
||||
container.populateInsertionPoint('context.settings.category.passwd', this)
|
||||
]
|
||||
});
|
||||
|
||||
Zarafa.plugins.passwd.settings.SettingsPasswdCategory.superclass.constructor.call(this, config);
|
||||
|
|
|
|||
|
|
@ -19,14 +19,9 @@ Zarafa.plugins.passwd.settings.SettingsPasswdWidget = Ext.extend(Zarafa.settings
|
|||
config = config || {};
|
||||
|
||||
Ext.applyIf(config, {
|
||||
height : 175,
|
||||
width : 400,
|
||||
title : _('Change Password'),
|
||||
title : dgettext("plugin_passwd", 'Change Password'),
|
||||
xtype : 'zarafa.settingspasswdwidget',
|
||||
layout : {
|
||||
// override from SettingsWidget
|
||||
type : 'fit'
|
||||
},
|
||||
layout: 'form',
|
||||
items : [{
|
||||
xtype : 'zarafa.passwdpanel',
|
||||
ref : 'passwdPanel',
|
||||
|
|
@ -51,10 +46,43 @@ Zarafa.plugins.passwd.settings.SettingsPasswdWidget = Ext.extend(Zarafa.settings
|
|||
// listen to savesettings and discardsettings to save/discard delegation data
|
||||
var contextModel = this.settingsContext.getModel();
|
||||
|
||||
this.mon(contextModel, 'beforesavesettings', this.onBeforeSaveSettings, this);
|
||||
this.mon(contextModel, 'savesettings', this.onSaveSettings, this);
|
||||
this.mon(contextModel, 'discardsettings', this.onDiscardSettings, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler will be called when {@link Zarafa.settings.SettingsContextModel#beforesavesettings} event is fired.
|
||||
* This function will validate the formdata.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
onBeforeSaveSettings : function()
|
||||
{
|
||||
// do some quick checks before submitting
|
||||
if(this.passwdPanel.new_password.getValue() != this.passwdPanel.new_password_repeat.getValue()) {
|
||||
Ext.MessageBox.alert(dgettext("plugin_passwd", 'Error'), dgettext("plugin_passwd", 'New passwords do not match.'));
|
||||
return false;
|
||||
} else if(Ext.isEmpty(this.passwdPanel.current_password.getValue())) {
|
||||
Ext.MessageBox.alert(dgettext("plugin_passwd", 'Error'), dgettext("plugin_passwd", 'Current password is empty.'));
|
||||
return false;
|
||||
} else if(Ext.isEmpty(this.passwdPanel.new_password.getValue()) || Ext.isEmpty(this.passwdPanel.new_password_repeat.getValue())) {
|
||||
Ext.MessageBox.alert(dgettext("plugin_passwd", 'Error'), dgettext("plugin_passwd", 'New password is empty.'));
|
||||
return false;
|
||||
} else if(!this.passwdPanel.getForm().isValid()) {
|
||||
Ext.MessageBox.alert(dgettext("plugin_passwd", 'Error'), dgettext("plugin_passwd", 'One or more fields does contain errors.'));
|
||||
return false;
|
||||
} else if (container.getSettingsModel().get("zarafa/v1/plugins/passwd/enable_strict_check")) {
|
||||
// do a quick score check:
|
||||
if(this.passwdPanel.new_password.getScore() < 70) {
|
||||
Ext.MessageBox.alert(dgettext("plugin_passwd", 'Error'), dgettext("plugin_passwd", 'Password is weak. Password should contain capital, non-capital letters and numbers. Password should have 8 to 20 characters.'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler will be called when {@link Zarafa.settings.SettingsContextModel#savesettings} event is fired.
|
||||
* This will relay this event to {@link Zarafa.plugins.passwd.settings.PasswdPanel PasswdPanel} so it can
|
||||
|
|
@ -73,6 +101,9 @@ Zarafa.plugins.passwd.settings.SettingsPasswdWidget = Ext.extend(Zarafa.settings
|
|||
container.getRequest().singleRequest('passwdmodule', 'save', data, new Zarafa.plugins.passwd.data.PasswdResponseHandler({
|
||||
callbackFn: function (success, response) {
|
||||
this.ownerCt.hideSavingMask(success);
|
||||
if(success) {
|
||||
this.passwdPanel.getForm().reset();
|
||||
}
|
||||
},
|
||||
scope : this
|
||||
}));
|
||||
|
|
|
|||
93
language/de_DE.UTF-8/LC_MESSAGES/plugin_passwd.po
Normal file
93
language/de_DE.UTF-8/LC_MESSAGES/plugin_passwd.po
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: zarafa-webapp-plugin-passwd\n"
|
||||
"POT-Creation-Date: 2014-03-04 13:53+0100\n"
|
||||
"PO-Revision-Date: 2014-03-04 14:34+0100\n"
|
||||
"Last-Translator: Robert Scheck <zarafa@robert-scheck.de>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Language: de\n"
|
||||
|
||||
# php/class.passwdmodule.php:44:
|
||||
msgid "No data received."
|
||||
msgstr "Keine Daten empfangen!"
|
||||
|
||||
# php/class.passwdmodule.php:48:
|
||||
msgid "User name is empty."
|
||||
msgstr "Benutzername ist leer!"
|
||||
|
||||
# php/class.passwdmodule.php:52:
|
||||
msgid "Current password is empty."
|
||||
msgstr "Aktuelles Passwort ist leer!"
|
||||
|
||||
# php/class.passwdmodule.php:56:
|
||||
msgid "New password is empty."
|
||||
msgstr "Neues Passwort ist leer!"
|
||||
|
||||
# php/class.passwdmodule.php:60:
|
||||
msgid "New passwords do not match."
|
||||
msgstr "Neue Passwörter stimmen nicht überein!"
|
||||
|
||||
# php/class.passwdmodule.php:137:
|
||||
# php/class.passwdmodule.php:196:
|
||||
# js/data/PasswdResponseHandler.js:44:
|
||||
msgid "Password is changed successfully."
|
||||
msgstr "Passwort wurde erfolgreich geändert!"
|
||||
|
||||
# php/class.passwdmodule.php:141:
|
||||
# php/class.passwdmodule.php:200:
|
||||
msgid "Password is not changed."
|
||||
msgstr "Passwort wurde nicht geändert!"
|
||||
|
||||
# php/class.passwdmodule.php:144:
|
||||
# php/class.passwdmodule.php:203:
|
||||
msgid ""
|
||||
"Password is weak. Password should contain capital, non-capital letters and "
|
||||
"numbers. Password should have 8 to 20 characters."
|
||||
msgstr ""
|
||||
"Das eingegebene Passwort ist schwach; es sollte große und kleine Buchstaben "
|
||||
"sowie Ziffern enthalten und zwischen 8 und 20 Zeichen lang sein!"
|
||||
|
||||
# php/class.passwdmodule.php:147:
|
||||
msgid "Current password does not match."
|
||||
msgstr "Aktuelles Passwort ist falsch!"
|
||||
|
||||
# js/data/PasswdResponseHandler.js:27:
|
||||
msgid "An unknown error occurred while changing password."
|
||||
msgstr "Beim Ändern des Passworts ist ein unbekannter Fehler aufgetreten!"
|
||||
|
||||
# js/data/PasswdResponseHandler.js:33:
|
||||
msgid "Error"
|
||||
msgstr "Fehler"
|
||||
|
||||
# js/data/PasswdResponseHandler.js:50:
|
||||
msgid "Success"
|
||||
msgstr "Erfolg"
|
||||
|
||||
# js/settings/SettingsPasswdWidget.js:24:
|
||||
# js/settings/SettingsPasswdCategory.js:20:
|
||||
msgid "Change Password"
|
||||
msgstr "Passwort ändern"
|
||||
|
||||
# js/PasswdPlugin.js:50:
|
||||
msgid "Password Change Plugin"
|
||||
msgstr "Passwortänderungsplugin"
|
||||
|
||||
# js/settings/PasswdPanel.js:29:
|
||||
msgid "User name"
|
||||
msgstr "Benutzername"
|
||||
|
||||
# js/settings/PasswdPanel.js:33:
|
||||
msgid "Current password"
|
||||
msgstr "Aktuelles Passwort"
|
||||
|
||||
# js/settings/PasswdPanel.js:42:
|
||||
msgid "New password"
|
||||
msgstr "Neues Passwort"
|
||||
|
||||
#js/settings/PasswdPanel.js:51:
|
||||
msgid "Retype new password"
|
||||
msgstr "Wiederholung"
|
||||
BIN
language/hu_HU.UTF-8/LC_MESSAGES/plugin_passwd.mo
Normal file
BIN
language/hu_HU.UTF-8/LC_MESSAGES/plugin_passwd.mo
Normal file
Binary file not shown.
94
language/hu_HU.UTF-8/LC_MESSAGES/plugin_passwd.po
Normal file
94
language/hu_HU.UTF-8/LC_MESSAGES/plugin_passwd.po
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: zarafa-webapp-plugin-passwd\n"
|
||||
"POT-Creation-Date: 2014-03-04 13:53+0100\n"
|
||||
"PO-Revision-Date: 2016-04-08 21:28+0200\n"
|
||||
"Last-Translator: David Horvath <dacr@dacr.hu>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Language: hu\n"
|
||||
"X-Generator: Poedit 1.8.7.1\n"
|
||||
|
||||
# php/class.passwdmodule.php:44:
|
||||
msgid "No data received."
|
||||
msgstr "Nem érkezett adat."
|
||||
|
||||
# php/class.passwdmodule.php:48:
|
||||
msgid "User name is empty."
|
||||
msgstr "Felhasználónév mező üres."
|
||||
|
||||
# php/class.passwdmodule.php:52:
|
||||
msgid "Current password is empty."
|
||||
msgstr "Jelenlegi jelszó mező üres."
|
||||
|
||||
# php/class.passwdmodule.php:56:
|
||||
msgid "New password is empty."
|
||||
msgstr "Új jelszó mező üres."
|
||||
|
||||
# php/class.passwdmodule.php:60:
|
||||
msgid "New passwords do not match."
|
||||
msgstr "Az új jelszavak nem egyeznek."
|
||||
|
||||
# php/class.passwdmodule.php:137:
|
||||
# php/class.passwdmodule.php:196:
|
||||
# js/data/PasswdResponseHandler.js:44:
|
||||
msgid "Password is changed successfully."
|
||||
msgstr "A jelszót sikeresen módosította."
|
||||
|
||||
# php/class.passwdmodule.php:141:
|
||||
# php/class.passwdmodule.php:200:
|
||||
msgid "Password is not changed."
|
||||
msgstr "A jelszó nem módosult."
|
||||
|
||||
# php/class.passwdmodule.php:144:
|
||||
# php/class.passwdmodule.php:203:
|
||||
msgid ""
|
||||
"Password is weak. Password should contain capital, non-capital letters and "
|
||||
"numbers. Password should have 8 to 20 characters."
|
||||
msgstr ""
|
||||
"A jelszó gyenge. Tartalmaznia kell számot, nagy- és kisbetűt. A jelszó "
|
||||
"minimum 8, maximum 20 karakter legyen."
|
||||
|
||||
# php/class.passwdmodule.php:147:
|
||||
msgid "Current password does not match."
|
||||
msgstr "A jelenlegi jelszó nem megfelelő."
|
||||
|
||||
# js/data/PasswdResponseHandler.js:27:
|
||||
msgid "An unknown error occurred while changing password."
|
||||
msgstr "Ismeretlen hiba történt a jelszó megváltoztatásakor."
|
||||
|
||||
# js/data/PasswdResponseHandler.js:33:
|
||||
msgid "Error"
|
||||
msgstr "Hiba"
|
||||
|
||||
# js/data/PasswdResponseHandler.js:50:
|
||||
msgid "Success"
|
||||
msgstr "Sikeres"
|
||||
|
||||
# js/settings/SettingsPasswdWidget.js:24:
|
||||
# js/settings/SettingsPasswdCategory.js:20:
|
||||
msgid "Change Password"
|
||||
msgstr "Jelszó megváltoztatása"
|
||||
|
||||
# js/PasswdPlugin.js:50:
|
||||
msgid "Password Change Plugin"
|
||||
msgstr "Jelszóváltoztatás kiegészítő"
|
||||
|
||||
# js/settings/PasswdPanel.js:29:
|
||||
msgid "User name"
|
||||
msgstr "Felhasználónév"
|
||||
|
||||
# js/settings/PasswdPanel.js:33:
|
||||
msgid "Current password"
|
||||
msgstr "Jelenlegi jelszó"
|
||||
|
||||
# js/settings/PasswdPanel.js:42:
|
||||
msgid "New password"
|
||||
msgstr "Új jelszó"
|
||||
|
||||
# js/settings/PasswdPanel.js:51:
|
||||
msgid "Retype new password"
|
||||
msgstr "Új jelszó mégegyszer"
|
||||
95
language/nl_NL.UTF-8/LC_MESSAGES/plugin_passwd.po
Normal file
95
language/nl_NL.UTF-8/LC_MESSAGES/plugin_passwd.po
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: zarafa-webapp-plugin-passwd\n"
|
||||
"POT-Creation-Date: 2014-03-04 13:53+0100\n"
|
||||
"PO-Revision-Date: 2014-03-04 14:34+0100\n"
|
||||
"Last-Translator: Sander Hoentjen <sander@hoentjen.eu>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Language: nl\n"
|
||||
|
||||
# php/class.passwdmodule.php:44:
|
||||
msgid "No data received."
|
||||
msgstr "Geen data ontvangen."
|
||||
|
||||
# php/class.passwdmodule.php:48:
|
||||
msgid "User name is empty."
|
||||
msgstr "Gebruikersnaam is leeg."
|
||||
|
||||
# php/class.passwdmodule.php:52:
|
||||
msgid "Current password is empty."
|
||||
msgstr "Huidig wachtwoord is leeg."
|
||||
|
||||
# php/class.passwdmodule.php:56:
|
||||
msgid "New password is empty."
|
||||
msgstr "Nieuw wachtwoord is leeg."
|
||||
|
||||
# php/class.passwdmodule.php:60:
|
||||
msgid "New passwords do not match."
|
||||
msgstr "Nieuwe wachtwoorden zijn niet gelijk."
|
||||
|
||||
# php/class.passwdmodule.php:137:
|
||||
# php/class.passwdmodule.php:196:
|
||||
# js/data/PasswdResponseHandler.js:44:
|
||||
msgid "Password is changed successfully."
|
||||
msgstr "Wachtwoord succesvol gewijzigd."
|
||||
|
||||
# php/class.passwdmodule.php:141:
|
||||
# php/class.passwdmodule.php:200:
|
||||
msgid "Password is not changed."
|
||||
msgstr "Wachtwoord is niet aangepast."
|
||||
|
||||
# php/class.passwdmodule.php:144:
|
||||
# php/class.passwdmodule.php:203:
|
||||
msgid ""
|
||||
"Password is weak. Password should contain capital, non-capital letters and "
|
||||
"numbers. Password should have 8 to 20 characters."
|
||||
msgstr ""
|
||||
"Wachtwoord is zwak. Een wachtwoord moet hoofdletters, kleine letters en "
|
||||
"cijfers bevatten. Een wachtwoord moet 8 tot 20 karakters bevatten."
|
||||
|
||||
# php/class.passwdmodule.php:147:
|
||||
msgid "Current password does not match."
|
||||
msgstr "Huidig wachtwoord klopt niet."
|
||||
|
||||
# js/data/PasswdResponseHandler.js:27:
|
||||
msgid "An unknown error occurred while changing password."
|
||||
msgstr "Er is een onbekende fout opgetreden tijdens de wachtwoord wijziging."
|
||||
|
||||
# js/data/PasswdResponseHandler.js:33:
|
||||
msgid "Error"
|
||||
msgstr "Fout"
|
||||
|
||||
# js/data/PasswdResponseHandler.js:50:
|
||||
msgid "Success"
|
||||
msgstr "Succes"
|
||||
|
||||
# js/settings/SettingsPasswdWidget.js:24:
|
||||
# js/settings/SettingsPasswdCategory.js:20:
|
||||
msgid "Change Password"
|
||||
msgstr "Wijzig wachtwoord"
|
||||
|
||||
# js/PasswdPlugin.js:50:
|
||||
msgid "Password Change Plugin"
|
||||
msgstr "Wachtwoord wijzigen plugin"
|
||||
|
||||
# js/settings/PasswdPanel.js:29:
|
||||
msgid "User name"
|
||||
msgstr "Gebruikersnaam"
|
||||
|
||||
# js/settings/PasswdPanel.js:33:
|
||||
msgid "Current password"
|
||||
msgstr "Huidig wachtwoord"
|
||||
|
||||
# js/settings/PasswdPanel.js:42:
|
||||
msgid "New password"
|
||||
msgstr "Nieuw wachtwoord"
|
||||
|
||||
#js/settings/PasswdPanel.js:51:
|
||||
msgid "Retype new password"
|
||||
msgstr "Herhaal nieuw wachtwoord"
|
||||
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
// 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');
|
||||
}
|
||||
}
|
||||
});
|
||||
28
manifest.xml
28
manifest.xml
|
|
@ -2,30 +2,21 @@
|
|||
<!DOCTYPE plugin SYSTEM "manifest.dtd">
|
||||
<plugin version="2">
|
||||
<info>
|
||||
<version>1.0</version>
|
||||
<version>1.3</version>
|
||||
<name>Passwd</name>
|
||||
<title>Password Change Plugin</title>
|
||||
<author>Saket Patel</author>
|
||||
<authorURL>https://github.com/silentsakky</authorURL>
|
||||
<description>Change your password from zarafa webapp</description>
|
||||
<description>Change your password from webapp</description>
|
||||
</info>
|
||||
<config>
|
||||
<configfile>config.php</configfile>
|
||||
</config>
|
||||
<translations>
|
||||
<translationsdir>language</translationsdir>
|
||||
</translations>
|
||||
|
||||
<components>
|
||||
<!-- <component>
|
||||
<info>
|
||||
<name>passwordmeter</name>
|
||||
<title>PasswordMeter</title>
|
||||
<author>Eelco Wiersma</author>
|
||||
<description>Ext user extension to check password strength</description>
|
||||
</info>
|
||||
<files>
|
||||
<client>
|
||||
<clientfile>lib/PasswordMeter.js</clientfile>
|
||||
</client>
|
||||
</files>
|
||||
</component> -->
|
||||
<component>
|
||||
<files>
|
||||
<server>
|
||||
|
|
@ -35,13 +26,20 @@
|
|||
<client>
|
||||
<clientfile load="release">js/passwd.js</clientfile>
|
||||
<clientfile load="debug">js/passwd-debug.js</clientfile>
|
||||
|
||||
<clientfile load="source">js/PasswdPlugin.js</clientfile>
|
||||
<clientfile load="source">js/settings/SettingsPasswdCategory.js</clientfile>
|
||||
<clientfile load="source">js/settings/SettingsPasswdWidget.js</clientfile>
|
||||
<clientfile load="source">js/settings/PasswdPanel.js</clientfile>
|
||||
<clientfile load="source">js/data/PasswdResponseHandler.js</clientfile>
|
||||
<clientfile load="source">js/ABOUT.js</clientfile>
|
||||
<clientfile load="source">js/external/PasswordMeter.js</clientfile>
|
||||
</client>
|
||||
<resources>
|
||||
<resourcefile load="release">resources/css/passwd.css</resourcefile>
|
||||
<resourcefile load="debug">resources/css/passwd.css</resourcefile>
|
||||
<resourcefile load="source">resources/css/passwd-main.css</resourcefile>
|
||||
</resources>
|
||||
</files>
|
||||
</component>
|
||||
</components>
|
||||
|
|
|
|||
|
|
@ -41,23 +41,23 @@ class PasswdModule extends Module
|
|||
|
||||
// some sanity checks
|
||||
if(empty($data)) {
|
||||
$errorMessage = _('No data received.');
|
||||
$errorMessage = dgettext("plugin_passwd", 'No data received.');
|
||||
}
|
||||
|
||||
if(empty($data['username'])) {
|
||||
$errorMessage = _('User name is empty.');
|
||||
$errorMessage = dgettext("plugin_passwd", 'User name is empty.');
|
||||
}
|
||||
|
||||
if(empty($data['current_password'])) {
|
||||
$errorMessage = _('Current password is empty.');
|
||||
$errorMessage = dgettext("plugin_passwd", 'Current password is empty.');
|
||||
}
|
||||
|
||||
if(empty($data['new_password']) || empty($data['new_password_repeat'])) {
|
||||
$errorMessage = _('New password is empty.');
|
||||
$errorMessage = dgettext("plugin_passwd", 'New password is empty.');
|
||||
}
|
||||
|
||||
if($data['new_password'] !== $data['new_password_repeat']) {
|
||||
$errorMessage = _('New passwords does not match.');
|
||||
$errorMessage = dgettext("plugin_passwd", 'New passwords do not match.');
|
||||
}
|
||||
|
||||
if(empty($errorMessage)) {
|
||||
|
|
@ -83,6 +83,9 @@ class PasswdModule extends Module
|
|||
public function saveInLDAP($data)
|
||||
{
|
||||
$errorMessage = '';
|
||||
$userName = $data['username'];
|
||||
$newPassword = $data['new_password'];
|
||||
$sessionPass = '';
|
||||
|
||||
// connect to LDAP server
|
||||
$ldapconn = ldap_connect(PLUGIN_PASSWD_LDAP_URI);
|
||||
|
|
@ -90,57 +93,74 @@ class PasswdModule extends Module
|
|||
// check connection is successfull
|
||||
if(ldap_errno($ldapconn) === 0) {
|
||||
// get the users uid, if we have a multi tenant installation then remove company name from user name
|
||||
$parts = explode('@', $data['username']);
|
||||
if (PLUGIN_PASSWD_LOGIN_WITH_TENANT){
|
||||
$parts = explode('@', $userName);
|
||||
$uid = $parts[0];
|
||||
} else {
|
||||
$uid = $userName;
|
||||
}
|
||||
|
||||
// check if we should use tls!
|
||||
if(strrpos(PLUGIN_PASSWD_LDAP_URI, "ldaps://", -strlen(PLUGIN_PASSWD_LDAP_URI)) === FALSE && PLUGIN_PASSWD_LDAP_USE_TLS === true) {
|
||||
ldap_start_tls($ldapconn);
|
||||
}
|
||||
|
||||
// set connection parametes
|
||||
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
|
||||
|
||||
// now bind to the ldap server to search the user dn
|
||||
ldap_bind($ldapconn, PLUGIN_PASSWD_LDAP_BIND_DN, PLUGIN_PASSWD_LDAP_BIND_PW);
|
||||
|
||||
// search for the user dn that will be used to do login into LDAP
|
||||
$userdn = ldap_search (
|
||||
$ldapconn, // connection-identify
|
||||
PLUGIN_PASSWD_LDAP_BASEDN, // basedn
|
||||
'uid=' . $uid, // search filter
|
||||
array('dn') // needed attributes. we need the dn
|
||||
array('dn', 'objectClass') // needed attributes. we need dn and objectclass
|
||||
);
|
||||
|
||||
if ($userdn) {
|
||||
$userdn = ldap_get_entries($ldapconn, $userdn);
|
||||
$userdn = $userdn[0]['dn'];
|
||||
$entries = ldap_get_entries($ldapconn, $userdn);
|
||||
$userdn = $entries[0]['dn'];
|
||||
|
||||
// bind to ldap directory
|
||||
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
|
||||
// login with current password if that fails then current password is wrong
|
||||
$bind = ldap_bind($ladpconn, $userdn, $data['current_password']);
|
||||
ldap_bind($ldapconn, $userdn, $data['current_password']);
|
||||
|
||||
if(ldap_errno($ldapconn) === 0) {
|
||||
$passwd = $data['new_password'];
|
||||
$passwdRepeat = $data['new_password_repeat'];
|
||||
|
||||
if($this->checkPasswordStrenth($passwd)) {
|
||||
$password_hash = $this->sshaEncode($passwd);
|
||||
$password_hash = $this->sshaEncode($newPassword);
|
||||
$entry = array('userPassword' => $password_hash);
|
||||
$return_mod = ldap_modify($ldapconn, $userdn, $entry);
|
||||
|
||||
if (in_array('sambaSamAccount', $entries[0]['objectclass'])) {
|
||||
$nthash = strtoupper(bin2hex(mhash(MHASH_MD4, iconv("UTF-8", "UTF-16LE", $newPassword))));
|
||||
$entry['sambaNTPassword'] = $nthash;
|
||||
$entry['sambaPwdLastSet'] = strval(time());
|
||||
}
|
||||
|
||||
ldap_modify($ldapconn, $userdn, $entry);
|
||||
if (ldap_errno($ldapconn) === 0) {
|
||||
// password changed successfully
|
||||
|
||||
// write new password to session because we don't want user to re-authenticate
|
||||
session_start();
|
||||
$_SESSION['password'] = $passwd;
|
||||
session_write_close();
|
||||
|
||||
// send feedback to client
|
||||
$this->sendFeedback(true, array(
|
||||
'info' => array(
|
||||
'display_message' => _('Password is changed successfully.')
|
||||
'display_message' => dgettext("plugin_passwd", 'Password is changed successfully.')
|
||||
)
|
||||
));
|
||||
|
||||
// write new password to session because we don't want user to re-authenticate
|
||||
session_start();
|
||||
$encryptionStore = EncryptionStore::getInstance();
|
||||
$encryptionStore->add('password', $newPassword);
|
||||
session_write_close();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
$errorMessage = _('Password is not changed.');
|
||||
$errorMessage = dgettext("plugin_passwd", 'Password is not changed.');
|
||||
}
|
||||
} else {
|
||||
$errorMessage = _('Password is weak. Password should contain capital, non capital letters and numbers. Password shuold have 8 to 20 characters.');
|
||||
}
|
||||
} else {
|
||||
$errorMessage = _('Current password does not match.');
|
||||
$errorMessage = dgettext("plugin_passwd", 'Current password does not match.');
|
||||
}
|
||||
|
||||
// release ldap-bind
|
||||
|
|
@ -152,8 +172,8 @@ class PasswdModule extends Module
|
|||
$this->sendFeedback(false, array(
|
||||
'type' => ERROR_ZARAFA,
|
||||
'info' => array(
|
||||
'ldap_error' => ldap_errno(),
|
||||
'ldap_error_name' => ldap_error(),
|
||||
'ldap_error' => ldap_errno($ldapconn),
|
||||
'ldap_error_name' => ldap_error($ldapconn),
|
||||
'display_message' => $errorMessage
|
||||
)
|
||||
));
|
||||
|
|
@ -161,42 +181,56 @@ class PasswdModule extends Module
|
|||
}
|
||||
|
||||
/**
|
||||
* Function will execute zarafa-passwd command and will try to change user's password,
|
||||
* this method is unsecure and unreliable.
|
||||
* Function will try to change user's password via MAPI in SOAP connection.
|
||||
* @param {Array} $data data sent by client.
|
||||
*/
|
||||
public function saveInDB($data)
|
||||
{
|
||||
$errorMessage = '';
|
||||
$passwd = $data['new_password'];
|
||||
$passwdRepeat = $data['new_password_repeat'];
|
||||
$userName = $data['username'];
|
||||
$newPassword = $data['new_password'];
|
||||
$sessionPass = '';
|
||||
|
||||
if($this->checkPasswordStrenth($passwd)) {
|
||||
$passwd_cmd = '/usr/bin/zarafa-passwd -u %s -o %s -p %s';
|
||||
// get current session password
|
||||
// if this plugin is used on a webapp version with EncryptionStore,
|
||||
// $_SESSION['password'] is no longer available. User EncryptionStore
|
||||
// in this case.
|
||||
// EncryptionStore was introduced in webapp core somewhere after
|
||||
// version 2.1.2, and with or before version 2.2.0.414.
|
||||
// tested with Zarafa WebApp 2.2.1.43-199.1 running with
|
||||
// Zarafa Server 7.2.4.29-99.1
|
||||
if(class_exists("EncryptionStore")) {
|
||||
$encryptionStore = EncryptionStore::getInstance();
|
||||
$sessionPass = $encryptionStore->get("password");
|
||||
}
|
||||
|
||||
if($data['current_password'] === $sessionPass) {
|
||||
// all information correct, change password
|
||||
$cmd = sprintf($passwd_cmd, $data['username'], $data['current_password'], $passwd);
|
||||
exec($cmd, $arrayout, $retval);
|
||||
$store = $GLOBALS['mapisession']->getDefaultMessageStore();
|
||||
$userinfo = mapi_zarafa_getuser_by_name($store, $userName);
|
||||
|
||||
if ($retval === 0) {
|
||||
if (mapi_zarafa_setuser($store, $userinfo['userid'], $userName, $userinfo['fullname'], $userinfo['emailaddress'], $newPassword, 0, $userinfo['admin'])) {
|
||||
// password changed successfully
|
||||
|
||||
// write new password to session because we don't want user to re-authenticate
|
||||
session_start();
|
||||
$_SESSION['password'] = $passwd;
|
||||
session_write_close();
|
||||
|
||||
// send feedback to client
|
||||
$this->sendFeedback(true, array(
|
||||
'info' => array(
|
||||
'display_message' => _('Password is changed successfully.')
|
||||
'display_message' => dgettext("plugin_passwd", 'Password is changed successfully.')
|
||||
)
|
||||
));
|
||||
|
||||
// write new password to session because we don't want user to re-authenticate
|
||||
session_start();
|
||||
$encryptionStore = EncryptionStore::getInstance();
|
||||
$encryptionStore->add('password', $newPassword);
|
||||
session_write_close();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
$errorMessage = _('Password is not changed.');
|
||||
$errorMessage = dgettext("plugin_passwd", 'Password is not changed.');
|
||||
}
|
||||
} else {
|
||||
$errorMessage = _('Password is weak. Password should contain capital, non capital letters and numbers. Password shuold have 8 to 20 characters.');
|
||||
$errorMessage = dgettext("plugin_passwd", 'Current password does not match.');
|
||||
}
|
||||
|
||||
if(!empty($errorMessage)) {
|
||||
|
|
@ -209,26 +243,6 @@ class PasswdModule extends Module
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function will check strength of the password and if it does not meet minimum requirements then
|
||||
* will return false.
|
||||
* Password should meet the following criteria:
|
||||
* - min. 8 chars, max. 20
|
||||
* - contain caps and noncaps characters
|
||||
* - contain numbers
|
||||
* @param {String} $password password which should be checked.
|
||||
* @return {Boolean} true if password passes the minimum requirement else false.
|
||||
*/
|
||||
public function checkPasswordStrenth($password)
|
||||
{
|
||||
// @FIXME should be moved to client side
|
||||
if (preg_match("#.*^(?=.{8,20})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).*$#", $password)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function will generate SSHA hash to use to store user's password in LDAP.
|
||||
* @param {String} $text text based on which hash will be generated.
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@ class Pluginpasswd extends Plugin {
|
|||
'zarafa' => Array(
|
||||
'v1' => Array(
|
||||
'plugins' => Array(
|
||||
'sugarcrm' => Array(
|
||||
'passwd' => Array(
|
||||
'enable' => PLUGIN_PASSWD_USER_DEFAULT_ENABLE,
|
||||
'enable_strict_check' => PLUGIN_PASSWD_STRICT_CHECK_ENABLE,
|
||||
)
|
||||
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
|||
27
resources/css/passwd-main.css
Normal file
27
resources/css/passwd-main.css
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
.zarafa-settings-category-passwd {
|
||||
background-image: url(../images/icon_lock.png) !important;
|
||||
}
|
||||
|
||||
/* STYLES FOR THE PASSWORD METER */
|
||||
.x-form-strengthmeter {
|
||||
width : 100%;
|
||||
height: 5px;
|
||||
/*float: right;*/
|
||||
background: #ff4c00; /* Old browsers */
|
||||
/* IE9 SVG, needs conditional override of 'filter' to 'none' */
|
||||
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmNGMwMCIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iI2VkZDcxMiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMxYWZmMDAiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
|
||||
background: -moz-linear-gradient(left, #ff4c00 0%, #edd712 50%, #1aff00 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, right top, color-stop(0%,#ff4c00), color-stop(50%,#edd712), color-stop(100%,#1aff00)); /* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(left, #ff4c00 0%,#edd712 50%,#1aff00 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(left, #ff4c00 0%,#edd712 50%,#1aff00 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(left, #ff4c00 0%,#edd712 50%,#1aff00 100%); /* IE10+ */
|
||||
background: linear-gradient(left, #ff4c00 0%,#edd712 50%,#1aff00 100%); /* W3C */
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff4c00', endColorstr='#1aff00',GradientType=1 ); /* IE6-8 */
|
||||
}
|
||||
|
||||
.x-form-strengthmeter-scorebar {
|
||||
background-color: white;
|
||||
opacity: 0.7;
|
||||
height: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
BIN
resources/images/icon_lock.png
Normal file
BIN
resources/images/icon_lock.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 452 B |
BIN
resources/images/icon_lock.xcf
Normal file
BIN
resources/images/icon_lock.xcf
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue