mirror of
https://github.com/hardillb/node-red-alexa-home-skill-web.git
synced 2025-12-11 09:29:44 +01:00
Added password reset
This commit is contained in:
80
index.js
80
index.js
@@ -117,6 +117,8 @@ var Account = require('./models/account');
|
||||
var oauthModels = require('./models/oauth');
|
||||
var Devices = require('./models/devices');
|
||||
var Topics = require('./models/topics');
|
||||
var LostPassword = require('./models/lostPassword');
|
||||
|
||||
|
||||
Account.findOne({username: mqtt_user}, function(error, account){
|
||||
if (!error && !account) {
|
||||
@@ -331,6 +333,84 @@ app.post('/newuser', function(req,res){
|
||||
});
|
||||
|
||||
|
||||
app.get('/changePassword/:key',function(req, res, next){
|
||||
var uuid = req.params.key;
|
||||
LostPassword.findOne({uuid: uuid}).populate('user').exec(function(error, lostPassword){
|
||||
if (!error && lostPassword) {
|
||||
req.login(lostPassword.user, function(err){
|
||||
if (!err){
|
||||
lostPassword.remove();
|
||||
res.redirect('/changePassword');
|
||||
} else {
|
||||
console.log(err);
|
||||
res.redirect('/');
|
||||
}
|
||||
})
|
||||
} else {
|
||||
res.redirect('/');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/changePassword', ensureAuthenticated, function(req, res, next){
|
||||
res.render('pages/changePassword', {user: req.user});
|
||||
});
|
||||
|
||||
app.post('/changePassword', ensureAuthenticated, function(req, res, next){
|
||||
Account.findOne({username: req.user.username}, function (err, user){
|
||||
if (!err && user) {
|
||||
user.setPassword(req.body.password, function(e,u){
|
||||
// var s = Buffer.from(account.salt, 'hex').toString('base64');
|
||||
// var h = Buffer.from(account.hash, 'hex').toString(('base64'));
|
||||
var mqttPass = "PBKDF2$sha256$901$" + user.salt + "$" + user.hash;
|
||||
u.mqttPass = mqttPass;
|
||||
u.save(function(error){
|
||||
if (!error) {
|
||||
console.log("Chagned %s's password", u.username);
|
||||
res.status(200).send();
|
||||
} else {
|
||||
console.log(error);
|
||||
res.status(400).send("Problem setting new password");
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.log(err);
|
||||
res.status(400).send("Problem setting new password");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/lostPassword', function(req, res, next){
|
||||
res.render('pages/lostPassword', { user: req.user});
|
||||
});
|
||||
|
||||
var sendemail = require('./sendemail');
|
||||
var mailer = new sendemail();
|
||||
|
||||
app.post('/lostPassword', function(req, res, next){
|
||||
var email = req.body.email;
|
||||
Account.findOne({email: email}, function(error, user){
|
||||
if (!error){
|
||||
if (user){
|
||||
var lostPassword = new LostPassword({user: user});
|
||||
console.log(lostPassword);
|
||||
lostPassword.save(function(err){
|
||||
if (!err) {
|
||||
res.status(200).send();
|
||||
}
|
||||
console.log(lostPassword.uuid);
|
||||
console.log(lostPassword.user.username);
|
||||
var body = mailer.buildLostPasswordBody(lostPassword.uuid, lostPassword.user.username);
|
||||
mailer.send(email, 'alexa-node-red@hardill.me.uk', 'Password Reset for Alexa Node-RED', body.text, body.html);
|
||||
});
|
||||
} else {
|
||||
res.status(404).send("No user found with that email address");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/auth/start',oauthServer.authorize(function(applicationID, redirectURI,done){
|
||||
oauthModels.Application.findOne({ oauth_id: applicationID }, function(error, application) {
|
||||
if (application) {
|
||||
|
||||
15
models/lostPassword.js
Normal file
15
models/lostPassword.js
Normal file
@@ -0,0 +1,15 @@
|
||||
var uid = require('uid2');
|
||||
var mongoose = require('mongoose');
|
||||
var Schema = mongoose.Schema;
|
||||
|
||||
var LostPassword = new Schema({
|
||||
uuid: { type: String, unique: true, required: true, default: function() {
|
||||
return uid(42);
|
||||
}},
|
||||
user: { type: Schema.Types.ObjectId, ref: 'Account' },
|
||||
createdDate: { type: Date, expires: 86400 , default: function(){
|
||||
return new Date();
|
||||
}}
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('LostPassword', LostPassword);
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "home-skill-web",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@@ -25,6 +25,7 @@
|
||||
"mongoose-sequence": "^3.1.0",
|
||||
"morgan": "^1.7.0",
|
||||
"mqtt": "^2.0.1",
|
||||
"nodemailer": "^1.11.0",
|
||||
"oauth2orize": "^1.5.1",
|
||||
"passport": "^0.3.2",
|
||||
"passport-http": "^0.3.0",
|
||||
|
||||
59
sendemail.js
Normal file
59
sendemail.js
Normal file
@@ -0,0 +1,59 @@
|
||||
var fs = require("fs");
|
||||
var ejs = require('ejs');
|
||||
var path = require('path');
|
||||
var nodemailer = require('nodemailer');
|
||||
|
||||
var smtpOptions = {
|
||||
host: process.env.MAIL_SERVER,
|
||||
port: 587,
|
||||
secure: false,
|
||||
auth: {
|
||||
user: process.env.MAIL_USER,
|
||||
pass: process.env.MAIL_PASSWORD
|
||||
}
|
||||
}
|
||||
|
||||
var lostPasswordTxtTemplate;
|
||||
var lostPasswordHTMLTemplate;
|
||||
|
||||
fs.readFile(
|
||||
path.join(__dirname, 'views', 'email', 'resetPasswordText.ejs'),
|
||||
"utf-8",
|
||||
function(err, file){
|
||||
lostPasswordTxtTemplate = file;
|
||||
});
|
||||
|
||||
|
||||
fs.readFile(
|
||||
path.join(__dirname, 'views', 'email', 'resetPasswordHTML.ejs'),
|
||||
"utf-8",
|
||||
function(err, file){
|
||||
lostPasswordHTMLTemplate = file;
|
||||
});
|
||||
|
||||
var transporter = nodemailer.createTransport(smtpOptions);
|
||||
|
||||
var Mailer = function() {
|
||||
|
||||
};
|
||||
|
||||
Mailer.prototype.send = function send(to, from, subject, text, html){
|
||||
var message = {
|
||||
to: to,
|
||||
from: from,
|
||||
subject: subject,
|
||||
text: text,
|
||||
html: html
|
||||
};
|
||||
|
||||
transporter.sendMail(message);
|
||||
}
|
||||
|
||||
Mailer.prototype.buildLostPasswordBody = function buildLostBody(uuid, userid){
|
||||
var body = ejs.render(lostPasswordTxtTemplate, {uuid: uuid, username: userid});
|
||||
var htmlBody = ejs.render(lostPasswordHTMLTemplate, {uuid: uuid, username: userid});
|
||||
|
||||
return {text: body, html: htmlBody };
|
||||
}
|
||||
|
||||
module.exports = Mailer;
|
||||
16
views/email/resetPasswordHTML.ejs
Normal file
16
views/email/resetPasswordHTML.ejs
Normal file
@@ -0,0 +1,16 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<p>Hello</p>
|
||||
|
||||
<p>A request was recently made to reset the password for your Node-RED Alexa Home Skill account.</p>
|
||||
|
||||
<p>Your username is <%= username %>.<p>
|
||||
|
||||
<p>Follow this link to reset your password</p>
|
||||
|
||||
<a href="https://alexa-node-red.bm.hardill.me.uk/changePassword/<%= uuid %>">https://alexa-node-red.bm.hardill.me.uk/changePassword/<%= uuid %></a>
|
||||
|
||||
<p>This link will only be valid for the next 24hrs and will only work once.</p>
|
||||
</body>
|
||||
</html>
|
||||
11
views/email/resetPasswordText.ejs
Normal file
11
views/email/resetPasswordText.ejs
Normal file
@@ -0,0 +1,11 @@
|
||||
Hello
|
||||
|
||||
A request was recently made to reset the password for your Node-RED Alexa Home Skill account.
|
||||
|
||||
Your username is <%= username %>.
|
||||
|
||||
Follow this link to reset your password
|
||||
|
||||
https://alexa-node-red.bm.hardill.me.uk/changePassword/<%= uuid %>
|
||||
|
||||
This link will only be valid for the next 24hrs and will only work once.
|
||||
49
views/pages/changePassword.ejs
Normal file
49
views/pages/changePassword.ejs
Normal file
@@ -0,0 +1,49 @@
|
||||
<% include ../fragments/header.ejs %>
|
||||
<div class="container main-content">
|
||||
<div id="changePassword">
|
||||
<h3>Enter New Password</h3>
|
||||
<label style="width: 75px" for="password">Password:</label>
|
||||
<input type="password" id="password"/>
|
||||
<br>
|
||||
<label style="width: 75px" for="password">Password:</label>
|
||||
<input type="password" id="passwordAgain"/>
|
||||
<br>
|
||||
<button id="registerButton">Submit</button>
|
||||
<script type="application/javascript">
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
var button = document.getElementById('registerButton');
|
||||
button.onclick = function(){
|
||||
var password = document.getElementById('password').value;
|
||||
var passwordAgain = document.getElementById('passwordAgain').value;
|
||||
|
||||
if (password !== passwordAgain) {
|
||||
alert("Passwords don't match");
|
||||
return;
|
||||
}
|
||||
|
||||
if (password.length < 1) {
|
||||
alert("Zero length passwords are note really a good idea");
|
||||
return;
|
||||
}
|
||||
|
||||
var params = "password=" + encodeURIComponent(password);
|
||||
xhr.open('POST', '/changePassword',true);
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xhr.onreadystatechange = function () {
|
||||
if( xhr.readyState == 4 && xhr.status == 200) {
|
||||
//new user created
|
||||
window.location = '/';
|
||||
} else if (xhr.readyState == 4 && xhr.status == 400) {
|
||||
//show error
|
||||
alert(xhr.responseText);
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send(params);
|
||||
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
<% include ../fragments/footer.ejs %>
|
||||
@@ -14,5 +14,6 @@
|
||||
<input type="submit" value="Login">
|
||||
</form>
|
||||
</div>
|
||||
<p>If you have forgetten your password click <a href="/lostPassword">here</a></p>
|
||||
</div>
|
||||
<% include ../fragments/footer.ejs %>
|
||||
39
views/pages/lostPassword.ejs
Normal file
39
views/pages/lostPassword.ejs
Normal file
@@ -0,0 +1,39 @@
|
||||
<% include ../fragments/header.ejs %>
|
||||
<div class="container main-content">
|
||||
<div id="changePassword">
|
||||
<h3>Enter email address</h3>
|
||||
<label style="width: 75px" for="email">Email:</label>
|
||||
<input type="email" id="email"/>
|
||||
<br>
|
||||
<button id="registerButton">Submit</button>
|
||||
<script type="application/javascript">
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
var button = document.getElementById('registerButton');
|
||||
button.onclick = function(){
|
||||
var email = document.getElementById('email').value;
|
||||
|
||||
if (email.indexOf('@') == -1) {
|
||||
alert("That doesn't look like a valid email address");
|
||||
return;
|
||||
} else {
|
||||
var params = 'email=' + encodeURIComponent(email);
|
||||
xhr.open('POST', '/lostPassword',true);
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xhr.onreadystatechange = function () {
|
||||
if( xhr.readyState == 4 && xhr.status == 200) {
|
||||
//new lostpassword token created
|
||||
window.location = '/';
|
||||
} else if (xhr.readyState == 4 && xhr.status == 404) {
|
||||
//show error
|
||||
alert(xhr.responseText);
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send(params);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
<% include ../fragments/footer.ejs %>
|
||||
@@ -33,6 +33,12 @@
|
||||
alert("Passwords don't match");
|
||||
return;
|
||||
}
|
||||
|
||||
if (password.length < 1) {
|
||||
alert("Zero length passwords are note really a good idea");
|
||||
return;
|
||||
}
|
||||
|
||||
var email = document.getElementById('email').value;
|
||||
//need to try validate the email address here:
|
||||
if (email.indexOf('@') == -1) {
|
||||
|
||||
Reference in New Issue
Block a user