mirror of
https://github.com/dducret/kopano-webapp-passwd
synced 2026-08-05 23:13:01 +02:00
added dialog for password change
implemented skeleton for php code
This commit is contained in:
parent
843f674854
commit
b434706684
7 changed files with 340 additions and 12 deletions
|
|
@ -1,4 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
/** Enable the passwd plugin for all clients **/
|
/** Enable the passwd plugin for all clients **/
|
||||||
define('PLUGIN_PASSWD_USER_DEFAULT_ENABLE', true);
|
define('PLUGIN_PASSWD_USER_DEFAULT_ENABLE', true);
|
||||||
|
|
||||||
|
/** Define zarafa installtion uses LDAP **/
|
||||||
|
define('PLUGIN_PASSWD_LDAP', true);
|
||||||
|
|
||||||
|
/** 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');
|
||||||
?>
|
?>
|
||||||
|
|
@ -5,4 +5,4 @@ Ext.namespace('Zarafa.plugins.passwd');
|
||||||
*
|
*
|
||||||
* The copyright string holding the copyright notice for the Zarafa passwd Plugin.
|
* The copyright string holding the copyright notice for the Zarafa passwd Plugin.
|
||||||
*/
|
*/
|
||||||
Zarafa.plugins.sugarcrm.ABOUT = "Something should be here";
|
Zarafa.plugins.passwd.ABOUT = "Something should be here";
|
||||||
|
|
|
||||||
34
js/PasswdContentPanel.js
Normal file
34
js/PasswdContentPanel.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
Ext.namespace('Zarafa.plugins.passwd');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Zarafa.plugins.passwd.PasswdContentPanel
|
||||||
|
* @extends Zarafa.core.ui.ContentPanel
|
||||||
|
*
|
||||||
|
* Content panel that will layout the container
|
||||||
|
*/
|
||||||
|
Zarafa.plugins.passwd.PasswdContentPanel = Ext.extend(Zarafa.core.ui.ContentPanel, {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} config configuration object that needs to be used when creating this dialog
|
||||||
|
*/
|
||||||
|
constructor : function(config)
|
||||||
|
{
|
||||||
|
config = config || {};
|
||||||
|
|
||||||
|
Ext.applyIf(config, {
|
||||||
|
xtype : 'zarafa.passwdcontentpanel',
|
||||||
|
layout : 'fit',
|
||||||
|
height : 175,
|
||||||
|
width : 400,
|
||||||
|
title : _('Change password'),
|
||||||
|
items : [{
|
||||||
|
xtype : 'zarafa.passwdpanel'
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
Zarafa.plugins.passwd.PasswdContentPanel.superclass.constructor.apply(this, arguments);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ext.reg('zarafa.passwdcontentpanel', Zarafa.plugins.passwd.PasswdContentPanel);
|
||||||
96
js/PasswdPanel.js
Normal file
96
js/PasswdPanel.js
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
Ext.namespace('Zarafa.plugins.passwd');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Zarafa.plugins.passwd.PasswdPanel
|
||||||
|
* @extends Ext.form.FormPanel
|
||||||
|
*
|
||||||
|
* Panel which holds a form that will be used to change the password
|
||||||
|
*/
|
||||||
|
Zarafa.plugins.passwd.PasswdPanel = Ext.extend(Ext.form.FormPanel, {
|
||||||
|
/**
|
||||||
|
* @property
|
||||||
|
* @type Ext.LoadMask
|
||||||
|
*/
|
||||||
|
saveMask : undefined,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} config configuration object that needs to be used when creating this dialog
|
||||||
|
*/
|
||||||
|
constructor : function(config)
|
||||||
|
{
|
||||||
|
config = config || {};
|
||||||
|
|
||||||
|
Ext.applyIf(config, {
|
||||||
|
xtype : 'zarafa.passwdpanel',
|
||||||
|
labelWidth : 150,
|
||||||
|
defaults : {
|
||||||
|
width : 200
|
||||||
|
},
|
||||||
|
items : [{
|
||||||
|
xtype : 'displayfield',
|
||||||
|
ref : 'userNameField',
|
||||||
|
fieldLabel : 'User name'
|
||||||
|
}, {
|
||||||
|
xtype : 'textfield',
|
||||||
|
ref : 'oldPasswdField',
|
||||||
|
fieldLabel : 'Current password',
|
||||||
|
inputType : 'password'
|
||||||
|
}, {
|
||||||
|
xtype : 'textfield',
|
||||||
|
ref : 'newPasswdField',
|
||||||
|
fieldLabel : 'New password',
|
||||||
|
inputType : 'password'
|
||||||
|
}, {
|
||||||
|
xtype : 'textfield',
|
||||||
|
ref : 'newPasswdRepeatField',
|
||||||
|
fieldLabel : 'Retype new password',
|
||||||
|
inputType : 'password'
|
||||||
|
}],
|
||||||
|
buttons : [{
|
||||||
|
text : 'Ok',
|
||||||
|
handler : this.onOk,
|
||||||
|
scope : this
|
||||||
|
}, {
|
||||||
|
text : 'Cancel',
|
||||||
|
handler : this.onCancel,
|
||||||
|
scope : this
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
Zarafa.plugins.passwd.PasswdPanel.superclass.constructor.apply(this, arguments);
|
||||||
|
|
||||||
|
this.on('afterrender', this.initialize, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize : function()
|
||||||
|
{
|
||||||
|
this.userNameField.setValue(container.getUser().getUserName());
|
||||||
|
|
||||||
|
this.saveMask = new Ext.LoadMask(this.getEl(), {
|
||||||
|
msg : _('Saving please wait ...')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onOk : function()
|
||||||
|
{
|
||||||
|
// send request
|
||||||
|
|
||||||
|
this.saveMask.show();
|
||||||
|
|
||||||
|
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());
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onCancel : function()
|
||||||
|
{
|
||||||
|
this.dialog.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ext.reg('zarafa.passwdpanel', Zarafa.plugins.passwd.PasswdPanel);
|
||||||
|
|
@ -19,6 +19,49 @@ Zarafa.plugins.passwd.PasswdPlugin = Ext.extend(Zarafa.core.Plugin, {
|
||||||
Zarafa.plugins.passwd.PasswdPlugin.superclass.initPlugin.apply(this, arguments);
|
Zarafa.plugins.passwd.PasswdPlugin.superclass.initPlugin.apply(this, arguments);
|
||||||
|
|
||||||
this.registerInsertionPoint('main.maintabbar.right', this.putTabbarButton, this);
|
this.registerInsertionPoint('main.maintabbar.right', this.putTabbarButton, this);
|
||||||
|
|
||||||
|
// Register common specific dialog types
|
||||||
|
Zarafa.core.data.SharedComponentType.addProperty('plugins.passwd.passwdpanel');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bid for the type of shared component and the given record.
|
||||||
|
* @param {Zarafa.core.data.SharedComponentType} type Type of component a context can bid for.
|
||||||
|
* @param {Ext.data.Record} record Optionally passed record.
|
||||||
|
* @return {Number} The bid for the shared component
|
||||||
|
*/
|
||||||
|
bidSharedComponent: function(type, record)
|
||||||
|
{
|
||||||
|
var bid = -1;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
// Bid for password dialog
|
||||||
|
case Zarafa.core.data.SharedComponentType['plugins.passwd.passwdpanel']:
|
||||||
|
bid = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bid;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will return the reference to the shared component.
|
||||||
|
* Based on the type of component requested a component is returned.
|
||||||
|
* @param {Zarafa.core.data.SharedComponentType} type Type of component a context can bid for.
|
||||||
|
* @param {Ext.data.Record} record Optionally passed record.
|
||||||
|
* @return {Ext.Component} Component
|
||||||
|
*/
|
||||||
|
getSharedComponent: function(type, record)
|
||||||
|
{
|
||||||
|
var component;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case Zarafa.core.data.SharedComponentType['plugins.passwd.passwdpanel']:
|
||||||
|
component = Zarafa.plugins.passwd.PasswdContentPanel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return component;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -42,7 +85,10 @@ Zarafa.plugins.passwd.PasswdPlugin = Ext.extend(Zarafa.core.Plugin, {
|
||||||
*/
|
*/
|
||||||
clickPasswdButton : function()
|
clickPasswdButton : function()
|
||||||
{
|
{
|
||||||
// open a dialog
|
var componentType = Zarafa.core.data.SharedComponentType['plugins.passwd.passwdpanel'];
|
||||||
|
Zarafa.core.data.UIFactory.openLayerComponent(componentType, undefined, {
|
||||||
|
modal : true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
<clientfile load="release">js/passwd.js</clientfile>
|
<clientfile load="release">js/passwd.js</clientfile>
|
||||||
<clientfile load="debug">js/passwd-debug.js</clientfile>
|
<clientfile load="debug">js/passwd-debug.js</clientfile>
|
||||||
<clientfile load="source">js/PasswdPlugin.js</clientfile>
|
<clientfile load="source">js/PasswdPlugin.js</clientfile>
|
||||||
|
<clientfile load="source">js/PasswdContentPanel.js</clientfile>
|
||||||
|
<clientfile load="source">js/PasswdPanel.js</clientfile>
|
||||||
<clientfile load="source">js/ABOUT.js</clientfile>
|
<clientfile load="source">js/ABOUT.js</clientfile>
|
||||||
</client>
|
</client>
|
||||||
<!-- <resources>
|
<!-- <resources>
|
||||||
|
|
|
||||||
|
|
@ -3,29 +3,20 @@
|
||||||
* Passwd module.
|
* Passwd module.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PasswdModule extends Module
|
class PasswdModule extends Module
|
||||||
{
|
{
|
||||||
public function __construct($id, $data) {
|
|
||||||
parent::Module($id, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the incoming events that were fire by the client.
|
* Process the incoming events that were fire by the client.
|
||||||
*
|
|
||||||
* @return boolean True if everything was processed correctly.
|
|
||||||
*/
|
*/
|
||||||
public function execute()
|
public function execute()
|
||||||
{
|
{
|
||||||
$result = false;
|
|
||||||
|
|
||||||
foreach($this->data as $actionType => $actionData)
|
foreach($this->data as $actionType => $actionData)
|
||||||
{
|
{
|
||||||
if(isset($actionType)) {
|
if(isset($actionType)) {
|
||||||
try {
|
try {
|
||||||
switch($actionType)
|
switch($actionType)
|
||||||
{
|
{
|
||||||
case "save":
|
case 'save':
|
||||||
$this->save($actionData);
|
$this->save($actionData);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -38,5 +29,155 @@ class PasswdModule extends Module
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function save($data)
|
||||||
|
{
|
||||||
|
// some sanity checks
|
||||||
|
if(empty($data)) {
|
||||||
|
$this->sendFeedback(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(empty($data['username']) || empty($data['current_password']) || empty($data['new_password']) || empty($data['new_password_repeat'])) {
|
||||||
|
$this->sendFeedback(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(PLUGIN_PASSWD_LDAP) {
|
||||||
|
$this->saveInLDAP($data);
|
||||||
|
} else {
|
||||||
|
$this->saveInDB($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveInLDAP($data)
|
||||||
|
{
|
||||||
|
$errorMessage = '';
|
||||||
|
|
||||||
|
// connect to LDAP server
|
||||||
|
$ldapconn = ldap_connect(PLUGIN_PASSWD_LDAP_URI);
|
||||||
|
|
||||||
|
// check connection is successfull
|
||||||
|
if(ldap_errno($ldapconn) === 0) {
|
||||||
|
// 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
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($userdn) {
|
||||||
|
$userdn = ldap_get_entries($ldapconn, $userdn);
|
||||||
|
$userdn = $userdn[0]['dn'];
|
||||||
|
|
||||||
|
// bind to ldap directory
|
||||||
|
ldap_set_option($ds, 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']);
|
||||||
|
|
||||||
|
if(ldap_errno($ldapconn) === 0) {
|
||||||
|
$passwd = $data['new_password'];
|
||||||
|
$passwdRepeat = $data['new_password_repeat'];
|
||||||
|
|
||||||
|
if($passwd === $passwdRepeat) {
|
||||||
|
if(checkPasswordStrenth($passwd)) {
|
||||||
|
$password_hash = sshaEncode($passwd);
|
||||||
|
$entry = array('userPassword' => $password_hash);
|
||||||
|
$return_mod = ldap_modify($ldapconn, $userdn, $entry);
|
||||||
|
if (ldap_errno($ldapconn) === 0) {
|
||||||
|
// password changed successfully
|
||||||
|
$this->sendFeedback(true, {
|
||||||
|
'info' => array(
|
||||||
|
'display_message' => _('Password is changed successfully.')
|
||||||
|
)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$errorMessage = _('Password is not changed.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$errorMessage = _('Password is weak.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$errorMessage = _('New passwords does not match.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$errorMessage = _('Current password does not match.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// release ldap-bind
|
||||||
|
ldap_unbind($ldapconn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!empty($errorMessage)) {
|
||||||
|
$this->sendFeedback(false, {
|
||||||
|
'type' => 999, // ERROR_LDAP
|
||||||
|
'info' => array(
|
||||||
|
'ldap_error' => ldap_errno(),
|
||||||
|
'ldap_error_name' => ldap_error(),
|
||||||
|
'display_message' => $errorMessage
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveInDB($data)
|
||||||
|
{
|
||||||
|
$passwd = $data['new_password'];
|
||||||
|
$passwdRepeat = $data['new_password_repeat'];
|
||||||
|
|
||||||
|
$passwd_cmd = "/usr/bin/zarafa-passwd -u %s -o %s -p %s";
|
||||||
|
|
||||||
|
if($passwd === $passwdRepeat) {
|
||||||
|
if(checkPasswordStrenth($passwd)) {
|
||||||
|
// all information correct, change password
|
||||||
|
$cmd = sprintf($passwd_cmd, $data['username'], $data['current_passwd'], $passwd);
|
||||||
|
exec($cmd, $arrayout, $retval);
|
||||||
|
|
||||||
|
if ($retval === 0) {
|
||||||
|
// password changed successfully
|
||||||
|
$this->sendFeedback(true, {
|
||||||
|
'info' => array(
|
||||||
|
'display_message' => _('Password is changed successfully.')
|
||||||
|
)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$errorMessage = _('Password is not changed.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$errorMessage = _('Password is weak.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$errorMessage = _('New passwords does not match.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check passwords. They should meet the following criteria:
|
||||||
|
// - min. 8 chars, max. 20
|
||||||
|
// - contain caps und noncaps characters
|
||||||
|
// - contain numbers
|
||||||
|
// return FALSE if not all criteria are met
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a ldap-password-hash from $text
|
||||||
|
function sshaEncode($text)
|
||||||
|
{
|
||||||
|
$salt = '';
|
||||||
|
for ($i=1; $i<=10; $i++) {
|
||||||
|
$salt .= substr('0123456789abcdef', rand(0, 15), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash = '{SSHA}' . base64_encode(pack("H*",sha1($text . $salt)) . $salt);
|
||||||
|
|
||||||
|
return $hash;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue