Add password change form

This commit is contained in:
Bartek Fabiszewski 2017-04-06 23:23:25 +02:00
parent 79a31aab21
commit 0ebadb8939
7 changed files with 231 additions and 4 deletions

73
changepass.php Normal file
View File

@ -0,0 +1,73 @@
<?php
/* μlogger
*
* Copyright(C) 2017 Bartek Fabiszewski (www.fabiszewski.net)
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
require_once("auth.php"); // sets $mysqli, $user
function exitWithError($errorMessage) {
return exitWithStatus(true, $errorMessage);
}
/**
* Exit with xml response
* @param boolean $isError Error if true
* @param string $errorMessage Optional error message
*/
function exitWithStatus($isError = false, $errorMessage = NULL) {
header("Content-type: text/xml");
$xml = new XMLWriter();
$xml->openURI("php://output");
$xml->startDocument("1.0");
$xml->setIndent(true);
$xml->startElement('root');
$xml->writeElement("error", (int) $isError);
if ($isError) {
$xml->writeElement("message", $errorMessage);
}
$xml->endElement();
$xml->endDocument();
$xml->flush();
exit;
}
$login = isset($_REQUEST['login']) ? trim($_REQUEST['login']) : NULL;
$oldpass = isset($_REQUEST['oldpass']) ? $_REQUEST['oldpass'] : NULL;
$hash = isset($_REQUEST['pass']) ? password_hash($_REQUEST['pass'], PASSWORD_DEFAULT) : NULL;
if (empty($hash)) {
exitWithError("Empty password");
}
if ($user->isAdmin && !empty($login)) {
// different user, only admin
$passUser = new uUser($login);
if (!$passUser->valid) {
exitWithError("User unknown");
}
} else {
// current user
$passUser = $user;
if (!$passUser->validPassword($oldpass)) {
exitWithError("Wrong old password");
}
}
if ($passUser->setPass($hash) === false) {
exitWithError("Server error");
}
exitWithStatus();
?>

View File

@ -63,6 +63,19 @@ class uUser {
return $userid;
}
public function setPass($hash) {
$ret = false;
$sql = "UPDATE users SET password = ? WHERE login = ?";
$stmt = self::$db->prepare($sql);
$stmt->bind_param('ss', $hash, $this->login);
$stmt->execute();
if (!self::$db->error && !$stmt->errno) {
$ret = true;
}
$stmt->close();
return $ret;
}
public function validPassword($password) {
return password_verify($password, $this->hash);
}

View File

@ -19,7 +19,16 @@
*/
require_once ("auth.php");
if ($user->isValid) {
$userHeader = $user->login . ' (<a href="logout.php">' . $lang_logout . '</a>)';
$itemPass = '<a href="javascript:void(0)" onclick="changePass()">' . $lang_changepass . '</a>';
$itemLogout = '<a href="logout.php">' . $lang_logout . '</a>';
$userHeader = '
<div id="user_menu">
<a href="javascript:void(0);" onclick="userMenu()">' . $user->login . '</a>
<div id="user_dropdown" class="dropdown">
' . $itemPass . '
' . $itemLogout . '
</div>
</div>';
} else {
$userHeader = '<a href="index.php?force_login=1">' . $lang_login . '</a>';
}
@ -153,6 +162,9 @@ print '<!DOCTYPE html>
var lang_passwordrepeat = "' . $lang_passwordrepeat . '";
var lang_passwordenter = "' . $lang_passwordenter . '";
var lang_usernameenter = "' . $lang_usernameenter . '";
var lang_oldpassword = "' . $lang_oldpassword . '";
var lang_newpassword = "' . $lang_newpassword . '";
var lang_newpasswordrepeat = "' . $lang_newpasswordrepeat . '";
var lang_cancel = "' . $lang_cancel . '";
var lang_submit = "' . $lang_submit . '";
var units = "' . $config::$units . '";

View File

@ -57,6 +57,10 @@ switch($config::$lang) {
$lang_passwordrepeat = "Repeat password";
$lang_passwordenter = "Enter password";
$lang_usernameenter = "Enter username";
$lang_oldpassword = "Old password";
$lang_newpassword = "New password";
$lang_newpasswordrepeat = "Repeat new password";
$lang_changepass = "Change password";
$lang_adduser = "Add user";
$lang_userexists = "User exists";
$lang_cancel ="Cancel";
@ -100,6 +104,10 @@ switch($config::$lang) {
$lang_passwordrepeat = "Ripeti password";
$lang_passwordenter = "Immetti password";
$lang_usernameenter = "Immetti nome utente";
$lang_oldpassword = "Old password"; // todo: translate
$lang_newpassword = "New password"; // todo: translate
$lang_newpasswordrepeat = "Repeat new password"; // todo: translate
$lang_changepass = "Change password"; // todo: translate
$lang_adduser = "Aggiungi utente";
$lang_userexists = "L'utente esiste già";
$lang_cancel ="Annulla";
@ -144,6 +152,10 @@ switch($config::$lang) {
$lang_passwordrepeat = "Powtórz hasło";
$lang_passwordenter = "Podaj hasło";
$lang_usernameenter = "Podaj użytkownika";
$lang_oldpassword = "Obecne hasło";
$lang_newpassword = "Nowe hasło";
$lang_newpasswordrepeat = "Powtórz nowe hasło";
$lang_changepass = "Zmień hasło";
$lang_adduser = "Dodaj użytkownika";
$lang_userexists = "Użytkownik istnieje";
$lang_cancel ="Anuluj";
@ -188,6 +200,10 @@ switch($config::$lang) {
$lang_passwordrepeat = "Repeat password"; // todo: translate
$lang_passwordenter = "Enter password"; // todo: translate
$lang_usernameenter = "Enter username"; // todo: translate
$lang_oldpassword = "Old password"; // todo: translate
$lang_newpassword = "New password"; // todo: translate
$lang_newpasswordrepeat = "Repeat new password"; // todo: translate
$lang_changepass = "Change password"; // todo: translate
$lang_adduser = "Add user"; // todo: translate
$lang_userexists = "User exists"; // todo: translate
$lang_cancel ="Cancel"; // todo: translate
@ -232,6 +248,10 @@ switch($config::$lang) {
$lang_passwordrepeat = "Repeat password"; // todo: translate
$lang_passwordenter = "Enter password"; // todo: translate
$lang_usernameenter = "Enter username"; // todo: translate
$lang_oldpassword = "Old password"; // todo: translate
$lang_newpassword = "New password"; // todo: translate
$lang_newpasswordrepeat = "Repeat new password"; // todo: translate
$lang_changepass = "Change password"; // todo: translate
$lang_adduser = "Add user"; // todo: translate
$lang_userexists = "User exists"; // todo: translate
$lang_cancel ="Cancel"; // todo: translate
@ -276,6 +296,10 @@ switch($config::$lang) {
$lang_passwordrepeat = "Répetez le mot de passe";
$lang_passwordenter = "Entrez votre mot de passe";
$lang_usernameenter = "Entrez votre nom d'utilisateur";
$lang_oldpassword = "Old password"; // todo: translate
$lang_newpassword = "New password"; // todo: translate
$lang_newpasswordrepeat = "Repeat new password"; // todo: translate
$lang_changepass = "Change password"; // todo: translate
$lang_adduser = "Ajouter un utilisateur";
$lang_userexists = "Cet utilisateur existe déjà";
$lang_cancel ="Annuler";

View File

@ -242,4 +242,23 @@ select {
-webkit-border-radius: 5px;
}
button { cursor:pointer; }
button {
cursor: pointer;
}
.dropdown {
display: none;
position: absolute;
background-color: gray;
padding: 1em;
width: 130px;
border: 1px solid #888;
}
.dropdown a {
display: block;
padding-bottom: .5em;
padding-top: .5em;
}
.show { display: block; }

24
main.js
View File

@ -405,8 +405,8 @@ function setUnits(unit) {
}
function showModal(contentHTML) {
var div = document.createElement("div");
div.setAttribute("id", "modal");
var div = document.createElement('div');
div.setAttribute('id', 'modal');
div.innerHTML = '<div id="modal-header"><button type="button" onclick="removeModal()">&times;</button></div><div id="modal-body"></div>';
document.body.appendChild(div);
var modalBody = document.getElementById('modal-body');
@ -415,4 +415,24 @@ function showModal(contentHTML) {
function removeModal() {
document.body.removeChild(document.getElementById('modal'));
}
function userMenu() {
var dropdown = document.getElementById('user_dropdown');
if (dropdown.classList.contains('show')) {
dropdown.classList.remove('show');
} else {
dropdown.classList.add('show');
window.addEventListener('click', removeOnClick, true);
}
}
function removeOnClick(event) {
var parent = event.target.parentElement;
var dropdown = document.getElementById('user_dropdown');
dropdown.classList.remove('show');
window.removeEventListener('click', removeOnClick, true);
if (!parent.classList.contains('dropdown')) {
event.stopPropagation();
}
}

66
pass.js Normal file
View File

@ -0,0 +1,66 @@
/* μlogger
*
* Copyright(C) 2017 Bartek Fabiszewski (www.fabiszewski.net)
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
function changePass() {
var form = '<form id="passForm" method="post" onsubmit="submitPass(); return false">';
form += '<label><b>' + lang_oldpassword + '</b></label><input type="password" placeholder="' + lang_passwordenter + '" name="oldpass" required>';
form += '<label><b>' + lang_newpassword + '</b></label><input type="password" placeholder="' + lang_passwordenter + '" name="pass" required>';
form += '<label><b>' + lang_newpasswordrepeat + '</b></label><input type="password" placeholder="' + lang_passwordenter + '" name="pass2" required>';
form += '<button type="button" onclick="removeModal()">' + lang_cancel + '</button><button type="submit">' + lang_submit + '</button>';
form += '</form>';
showModal(form);
}
function submitPass() {
var form = document.getElementById('passForm');
var oldpass = form.elements['oldpass'].value;
var pass = form.elements['pass'].value;
var pass2 = form.elements['pass2'].value;
if (!oldpass || !pass || !pass2) {
alert("All fields are required");
return;
}
if (pass != pass2) {
alert("Passwords don't match");
return;
}
var xhr = getXHR();
xhr.onreadystatechange = function() {
if (xhr.readyState==4 && xhr.status==200) {
var xml = xhr.responseXML;
var message = "";
if (xml) {
var root = xml.getElementsByTagName('root');
if (root.length && getNode(root[0], 'error') == 0) {
removeModal();
alert("Password successfully changed");
return;
}
errorMsg = getNode(root[0], 'message');
if (errorMsg) { message = errorMsg; }
}
alert("Something went wrong\n" + message);
xhr = null;
}
}
xhr.open('POST', 'changepass.php', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send('oldpass=' + oldpass + '&pass=' + pass);
return;
}