mirror of
https://github.com/dducret/kopano-webapp-passwd
synced 2026-07-27 10:32:26 +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
|
||||
/** Enable the passwd plugin for all clients **/
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
|
||||
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()
|
||||
{
|
||||
// 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="debug">js/passwd-debug.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>
|
||||
</client>
|
||||
<!-- <resources>
|
||||
|
|
|
|||
|
|
@ -3,29 +3,20 @@
|
|||
* Passwd module.
|
||||
*
|
||||
*/
|
||||
|
||||
class PasswdModule extends Module
|
||||
{
|
||||
public function __construct($id, $data) {
|
||||
parent::Module($id, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the incoming events that were fire by the client.
|
||||
*
|
||||
* @return boolean True if everything was processed correctly.
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$result = false;
|
||||
|
||||
foreach($this->data as $actionType => $actionData)
|
||||
{
|
||||
if(isset($actionType)) {
|
||||
try {
|
||||
switch($actionType)
|
||||
{
|
||||
case "save":
|
||||
case 'save':
|
||||
$this->save($actionData);
|
||||
break;
|
||||
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