Password recovery fixes
gitea/hedera-web/pipeline/head This commit looks good
Details
gitea/hedera-web/pipeline/head This commit looks good
Details
This commit is contained in:
parent
66875ce193
commit
f9c8cd0e83
|
@ -1,4 +1,4 @@
|
|||
hedera-web (1.407.40) stable; urgency=low
|
||||
hedera-web (1.407.41) stable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
|
||||
|
|
|
@ -1,77 +1,81 @@
|
|||
|
||||
Hedera.Conf = new Class
|
||||
({
|
||||
Hedera.Conf = new Class({
|
||||
Extends: Hedera.Form
|
||||
|
||||
,activate: function ()
|
||||
{
|
||||
this.$('user-model').setInfo ('c', 'myClient', 'hedera');
|
||||
,activate: function() {
|
||||
this.$('user-model').setInfo('c', 'myClient', 'hedera');
|
||||
|
||||
console.log(this.hash.get('verificationToken'));
|
||||
|
||||
if (this.hash.get('verificationToken'))
|
||||
this.onPassChangeClick();
|
||||
}
|
||||
|
||||
,onPassChangeClick: function ()
|
||||
{
|
||||
,onPassChangeClick: function() {
|
||||
this.$('old-password').value = '';
|
||||
this.$('new-password').value = '';
|
||||
this.$('repeat-password').value = '';
|
||||
|
||||
var recoverPass = this.$('user-form').get ('recoverPass');
|
||||
this.$('old-password').style.display = recoverPass ? 'none' : 'block';
|
||||
this.$('change-password').show ();
|
||||
var verificationToken = this.hash.get('verificationToken');
|
||||
this.$('old-password').style.display = verificationToken ? 'none' : 'block';
|
||||
this.$('change-password').show();
|
||||
|
||||
if (recoverPass)
|
||||
this.$('new-password').focus ();
|
||||
if (verificationToken)
|
||||
this.$('new-password').focus();
|
||||
else
|
||||
this.$('old-password').focus ();
|
||||
this.$('old-password').focus();
|
||||
}
|
||||
|
||||
,onPassModifyClick: function ()
|
||||
{
|
||||
,onPassModifyClick: function() {
|
||||
try {
|
||||
var oldPassword = this.$('old-password').value;
|
||||
var newPassword = this.$('new-password').value;
|
||||
var repeatedPassword = this.$('repeat-password').value;
|
||||
|
||||
if (newPassword == '' && repeatedPassword == '')
|
||||
throw new Error (_('Passwords empty'));
|
||||
throw new Error(_('Passwords empty'));
|
||||
if (newPassword !== repeatedPassword)
|
||||
throw new Error (_('Passwords doesn\'t match'));
|
||||
throw new Error(_('Passwords doesn\'t match'));
|
||||
|
||||
var params = {
|
||||
oldPassword: oldPassword,
|
||||
newPassword: newPassword
|
||||
};
|
||||
this.conn.send ('core/change-password', params,
|
||||
this._onPassChange.bind (this));
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
Htk.Toast.showError (e.message);
|
||||
var verificationToken = this.hash.get('verificationToken');
|
||||
var params = {newPassword: newPassword};
|
||||
|
||||
if (verificationToken) {
|
||||
params.verificationToken = verificationToken;
|
||||
this.conn.send('core/restore-password', params,
|
||||
this._onPassChange.bind(this));
|
||||
} else {
|
||||
params.oldPassword = oldPassword;
|
||||
this.conn.send('core/change-password', params,
|
||||
this._onPassChange.bind(this));
|
||||
}
|
||||
} catch (e) {
|
||||
Htk.Toast.showError(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
,_onPassChange: function (json, error)
|
||||
{
|
||||
if (json)
|
||||
{
|
||||
this.$('change-password').hide ();
|
||||
Htk.Toast.showMessage (_('Password changed!'));
|
||||
this.$('user-form').refresh ();
|
||||
}
|
||||
else
|
||||
{
|
||||
Htk.Toast.showError (error.message);
|
||||
this.$('old-password').select ();
|
||||
,_onPassChange: function(json, error) {
|
||||
if (json) {
|
||||
this.$('change-password').hide();
|
||||
this.hash.unset('verificationToken');
|
||||
Htk.Toast.showMessage(_('Password changed!'));
|
||||
this.$('user-form').refresh();
|
||||
} else {
|
||||
Htk.Toast.showError(error.message);
|
||||
|
||||
if (this.hash.get('verificationToken'))
|
||||
this.$('new-password').select();
|
||||
else
|
||||
this.$('old-password').select();
|
||||
}
|
||||
}
|
||||
|
||||
,onPassInfoClick: function ()
|
||||
{
|
||||
this.$('password-info').show ();
|
||||
,onPassInfoClick: function() {
|
||||
this.$('password-info').show();
|
||||
}
|
||||
|
||||
,onAddressesClick: function ()
|
||||
{
|
||||
this.hash.set ({form: 'account/address-list'});
|
||||
,onAddressesClick: function() {
|
||||
this.hash.set({form: 'account/address-list'});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
<db-form id="user-form">
|
||||
<db-model property="model" id="user-model" updatable="true">
|
||||
<custom>
|
||||
SELECT u.id, u.name, u.email, u.recoverPass,
|
||||
u.nickname, u.lang, c.isToBeMailed, c.id clientFk
|
||||
SELECT u.id, u.name, u.email, u.nickname,
|
||||
u.lang, c.isToBeMailed, c.id clientFk
|
||||
FROM account.myUser u
|
||||
LEFT JOIN myClient c
|
||||
ON u.id = c.id
|
||||
|
|
|
@ -35,6 +35,15 @@ module.exports =
|
|||
return this._hashMap[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets a hash key.
|
||||
*
|
||||
* @param {string} key The variable name
|
||||
**/
|
||||
,unset: function(key) {
|
||||
this.add({[key]: undefined});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the hash part of the URL, respecting the current hash variables.
|
||||
*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "hedera-web",
|
||||
"version": "1.407.40",
|
||||
"version": "1.407.41",
|
||||
"description": "Verdnatura web page",
|
||||
"license": "GPL-3.0",
|
||||
"repository": {
|
||||
|
|
|
@ -6,11 +6,11 @@ include __DIR__.'/account.php';
|
|||
* Updates the user password.
|
||||
**/
|
||||
class ChangePassword extends Vn\Web\JsonRequest {
|
||||
const PARAMS = ['newPassword'];
|
||||
const PARAMS = ['oldPassword', 'newPassword'];
|
||||
|
||||
function run($db) {
|
||||
$newPassword = $_REQUEST['newPassword'];
|
||||
$oldPassword = $_REQUEST['oldPassword'];
|
||||
$newPassword = $_REQUEST['newPassword'];
|
||||
|
||||
$db->query('CALL account.myUser_changePassword(#, #)',
|
||||
[$oldPassword, $newPassword]);
|
||||
|
|
|
@ -6,61 +6,31 @@ class RecoverPassword extends Vn\Web\JsonRequest {
|
|||
const PARAMS = ['recoverUser'];
|
||||
|
||||
function run($db) {
|
||||
$recoverUser = $_REQUEST['recoverUser'];
|
||||
|
||||
$user = $db->getRow(
|
||||
'SELECT email, active FROM account.user WHERE name = #',
|
||||
[$_REQUEST['recoverUser']]
|
||||
[$recoverUser]
|
||||
);
|
||||
|
||||
if (!($user['active'] && $user['email']))
|
||||
return TRUE;
|
||||
|
||||
$verificationToken = bin2hex(random_bytes(16));
|
||||
$db->query(
|
||||
'UPDATE account.user SET verificationToken = #
|
||||
WHERE name = #',
|
||||
[$verificationToken, $recoverUser]
|
||||
);
|
||||
|
||||
$service = $this->service;
|
||||
$token = $service->createToken($_REQUEST['recoverUser'], FALSE, TRUE);
|
||||
$url = $service->getUrl() ."#!form=account/conf&token=$token";
|
||||
$token = $service->createToken($recoverUser);
|
||||
$url = $service->getUrl() ."#!form=account/conf&verificationToken=$verificationToken&token=$token";
|
||||
|
||||
$report = new Vn\Web\Report($db, 'recover-password', ['url' => $url]);
|
||||
$report->sendMail($user['email']);
|
||||
|
||||
return \Vn\Lib\Locale::get();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const LOWERS = 'abcdefghijklmnopqrstuvwxyz';
|
||||
const UPPERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
const DIGITS = '1234567890';
|
||||
const SYMBOLS = '!$%&()=.';
|
||||
|
||||
function genPassword($db) {
|
||||
$restrictions = $db->getRow(
|
||||
'SELECT length, nUpper, nDigits, nPunct FROM account.userPassword');
|
||||
|
||||
$pass = [];
|
||||
$newPass = '';
|
||||
|
||||
$nAlpha = $restrictions['length'] -(
|
||||
$restrictions['nUpper'] +
|
||||
$restrictions['nDigits'] +
|
||||
$restrictions['nPunct']);
|
||||
|
||||
$this->genRands($pass, self::LOWERS, $nAlpha);
|
||||
$this->genRands($pass, self::UPPERS, $restrictions['nUpper']);
|
||||
$this->genRands($pass, self::DIGITS, $restrictions['nDigits']);
|
||||
$this->genRands($pass, self::SYMBOLS, $restrictions['nPunct']);
|
||||
|
||||
for ($i = count($pass) - 1; $i >= 0; $i--) {
|
||||
$rand = rand(0, $i);
|
||||
$newPass .= $pass[$rand];
|
||||
array_splice($pass, $rand, 1);
|
||||
}
|
||||
|
||||
return $newPass;
|
||||
}
|
||||
|
||||
function genRands(&$pass, $chars, $max) {
|
||||
$len = strlen($chars) - 1;
|
||||
|
||||
for ($i = 0; $i < $max; $i++)
|
||||
$pass[] = $chars[rand(0, $len)];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
use Vn\Web;
|
||||
|
||||
/**
|
||||
* Restores the user password.
|
||||
**/
|
||||
class RestorePassword extends Vn\Web\JsonRequest {
|
||||
const PARAMS = ['verificationToken', 'newPassword'];
|
||||
|
||||
function run($db) {
|
||||
$verificationToken = $_REQUEST['verificationToken'];
|
||||
$newPassword = $_REQUEST['newPassword'];
|
||||
|
||||
$db->query('CALL account.myUser_restorePassword(#, #)',
|
||||
[$verificationToken, $newPassword]);
|
||||
Account::sync($db, $_SESSION['user'], $newPassword);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -180,13 +180,6 @@ abstract class Service {
|
|||
throw new SessionExpiredException();
|
||||
|
||||
$user = $jwtPayload['sub'];
|
||||
|
||||
if (!empty($jwtPayload['recover']))
|
||||
$db->query(
|
||||
'UPDATE account.user SET recoverPass = TRUE
|
||||
WHERE name = #',
|
||||
[$user]
|
||||
);
|
||||
}
|
||||
else {
|
||||
$user = $db->getValue('SELECT guestUser FROM config');
|
||||
|
@ -263,7 +256,7 @@ abstract class Service {
|
|||
* @param {boolean} $recover Wether to enable recovery mode on login
|
||||
* @return {string} The JWT generated token
|
||||
*/
|
||||
function createToken($user, $remember = FALSE, $recover = FALSE) {
|
||||
function createToken($user, $remember = FALSE) {
|
||||
if ($remember)
|
||||
$tokenLife = WEEK;
|
||||
else
|
||||
|
@ -274,9 +267,6 @@ abstract class Service {
|
|||
'exp' => time() + $tokenLife
|
||||
];
|
||||
|
||||
if ($recover)
|
||||
$payload['recover'] = 'TRUE';
|
||||
|
||||
$key = $this->db->getValue('SELECT jwtKey FROM config');
|
||||
return Jwt::encode($payload, $key);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue