Password changing now works.

Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
James Ketr 2018-12-04 19:31:06 -08:00
parent 2186862e2f
commit 0e750d5931
4 changed files with 213 additions and 33 deletions

View File

@ -790,8 +790,13 @@
},
profile: function(event) {
this.$.profile.user = this.user;
this.mode = "profile";
if (this.mode == "profile") {
this.mode = this.lastMode;
} else {
this.$.profile.user = this.user;
this.lastMode = this.mode;
this.mode = "profile";
}
},
logout: function(event) {

View File

@ -5,31 +5,51 @@ const config = require("config"),
hb = require("handlebars");
const templates = {
"html": [
"<p>Hello {{username}},</p>",
"",
"<p>Welcome to <b>ketrenos.com</b>. You are almost done creating your account. ",
"Before you can access the system, you must verify your email address.</p>",
"",
"<p>To do so, simply access this link:</p>",
"<p><a href=\"{{url}}{{secret}}\">VERIFY {{mail}} ADDRESS</a></p>",
"",
"<p>Sincerely,</p>",
"<p>James</p>"
].join("\n"),
"text": [
"Hello {{username}},",
"",
"Welcome to ketrenos.com. You are almost done creating your account. ",
"Before you can access the system, you must verify your email address.",
"",
"To do so, simply access this link:",
"",
"{{url}}{{secret}}",
"",
"Sincerely,",
"James"
].join("\n")
"verify": {
"html": [
"<p>Hello {{username}},</p>",
"",
"<p>Welcome to <b>ketrenos.com</b>. You are almost done creating your account. ",
"Before you can access the system, you must verify your email address.</p>",
"",
"<p>To do so, simply access this link:</p>",
"<p><a href=\"{{url}}{{secret}}\">VERIFY {{mail}} ADDRESS</a></p>",
"",
"<p>Sincerely,</p>",
"<p>James</p>"
].join("\n"),
"text": [
"Hello {{username}},",
"",
"Welcome to ketrenos.com. You are almost done creating your account. ",
"Before you can access the system, you must verify your email address.",
"",
"To do so, simply access this link:",
"",
"{{url}}{{secret}}",
"",
"Sincerely,",
"James"
].join("\n")
},
"password": {
"html": [
"<p>Hello {{username}},</p>",
"",
"<p>You changed your password on <b>ketrenos.com</b>.</p>",
"",
"<p>Sincerely,</p>",
"<p>James</p>"
].join("\n"),
"text": [
"Hello {{username}},",
"",
"You changed your password on ketrenos.com.",
"",
"Sincerely,</p>",
"James"
].join("\n")
}
};
const sendVerifyMail = function(userDB, req, user) {
@ -79,8 +99,8 @@ const sendVerifyMail = function(userDB, req, user) {
subject: "Request to ketrenos.com create account for '" + data.username + "'",
cc: "",
bcc: config.get("admin.mail"),
text: hb.compile(templates.text)(data),
html: hb.compile(templates.html)(data)
text: hb.compile(templates.verify.text)(data),
html: hb.compile(templates.verify.html)(data)
};
return new Promise(function (resolve, reject) {
let attempts = 10;
@ -111,6 +131,53 @@ const sendVerifyMail = function(userDB, req, user) {
});
};
const sendPasswordChangedMail = function(userDB, req, user) {
const transporter = req.app.get("transporter");
if (!transporter) {
console.log("Not sending VERIFY email; SMTP not configured.");
return;
}
let data = {
username: user.displayName,
mail: user.mail,
url: req.protocol + "://" + req.hostname + req.app.get("basePath")
}, envelope = {
to: data.mail,
from: config.get("smtp.sender"),
subject: "Password changed on ketrenos.com for '" + data.username + "'",
cc: "",
bcc: config.get("admin.mail"),
text: hb.compile(templates.password.text)(data),
html: hb.compile(templates.password.html)(data)
};
return new Promise(function (resolve, reject) {
let attempts = 10;
function send(envelope) {
/* Rate limit to ten per second */
transporter.sendMail(envelope, function (error, info) {
if (!error) {
console.log('Message sent: ' + info.response);
return resolve();
}
if (attempts == 0) {
console.log("Error sending email: ", error);
return reject(error);
}
attempts--;
console.log("Unable to send mail. Trying again in 100ms (" + attempts + " attempts remain): ", error);
setTimeout(send.bind(undefined, envelope), 100);
});
}
send(envelope);
});
};
module.exports = {
sendVerifyMail
sendVerifyMail,
sendPasswordChangedMail
}

View File

@ -108,8 +108,6 @@ function init(moment) {
if (ds.length) { return ds.join('|'); }
}
});
console.log("Pascha initialized");
}
module.exports = init;

View File

@ -3,7 +3,7 @@
const express = require("express"),
config = require("config"),
LdapAuth = require("ldapauth-fork"),
{ sendVerifyMail } = require("../lib/mail"),
{ sendVerifyMail, sendPasswordChangedMail } = require("../lib/mail"),
crypto = require("crypto");
const router = express.Router();
@ -45,6 +45,116 @@ function ldapPromise(username, password) {
});
}
const ldapJS = require("ldapjs"),
ldapConfig = config.get("ldap");
const ldapSetPassword = function(username, password) {
const client = ldapJS.createClient({
url: ldapConfig.url
});
return new Promise(function(resolve, reject) {
client.bind(ldapConfig.bindDn, ldapConfig.bindCredentials, function(err) {
if (err) {
return reject("Error binding to LDAP: " + err);
}
var change = new ldapJS.Change({
operation: "replace",
modification: {
userPassword : password,
}
});
client.modify("uid=" + username + ",ou=people," + ldapConfig.searchBase, change, function(err) {
if (err) {
return reject("Error changing password: " + err);
}
return resolve();
});
});
}).catch(function(error) {
console.error(error);
}).then(function() {
client.unbind(function(err) {
if (err) {
console.error("Error unbinding: " + err);
}
});
});
};
router.put("/password", function(req, res) {
console.log("/users/password");
const changes = {
currentPassword: req.query.c || req.body.c,
newPassword: req.query.n || req.body.n
};
if (!changes.currentPassword || !changes.newPassword) {
return res.status(400).send("Missing current password and/or new password.");
}
if (changes.currentPassword == changes.newPassword) {
return res.status(400).send("Attempt to set new password to current password.");
}
return getSessionUser(req).then(function(user) {
if (req.session.userId == "LDAP") {
return ldapPromise(user.username, changes.currentPassword).then(function() {
return user;
}).catch(function() {
return null;
});
}
/* Not an LDAP user, so query in the DB */
return userDB.sequelize.query("SELECT id FROM users " +
"WHERE uid=:username AND password=:password", {
replacements: {
username: user.username,
password: crypto.createHash('sha256').update(changes.currentPassword).digest('base64')
},
type: userDB.Sequelize.QueryTypes.SELECT,
raw: true
}).then(function(users) {
if (users.length != 1) {
return null;
}
return user;
});
}).then(function(user) {
if (!user) {
console.log("Invalid password");
/* Invalid password */
res.status(401).send("Invalid password");
return null;
}
let updatePromise;
if (req.session.userId == "LDAP") {
updatePromise = ldapSetPassword(user.username, changes.newPassword);
} else {
updatePromise = userDB.sequelize.query("UPDATE users SET password=:password WHERE uid=:username", {
replacements: {
username: user.username,
password: crypto.createHash('sha256').update(changes.newPassword).digest('base64')
}
});
}
updatePromise.then(function() {
console.log("Password changed for user " + user.username + " to '" + changes.newPassword + "'.");
res.status(200).send(user);
user.id = req.session.userId;
return sendPasswordChangedMail(userDB, req, user);
});
});
});
router.post("/create", function(req, res) {
console.log("/users/create");