diff --git a/app.js b/app.js index 6ef91e92e0..8bfd67d362 100755 --- a/app.js +++ b/app.js @@ -21,8 +21,6 @@ var homeController = require('./controllers/home'); var userController = require('./controllers/user'); var apiController = require('./controllers/api'); var contactController = require('./controllers/contact'); -var forgotController = require('./controllers/forgot'); -var resetController = require('./controllers/reset'); /** * API keys + Passport configuration. @@ -103,10 +101,10 @@ app.get('/', homeController.index); app.get('/login', userController.getLogin); app.post('/login', userController.postLogin); app.get('/logout', userController.logout); -app.get('/forgot', forgotController.getForgot); -app.post('/forgot', forgotController.postForgot); -app.get('/reset/:token', resetController.getReset); -app.post('/reset/:token', resetController.postReset); +app.get('/forgot', userController.getForgot); +app.post('/forgot', userController.postForgot); +app.get('/reset/:token', userController.getReset); +app.post('/reset/:token', userController.postReset); app.get('/signup', userController.getSignup); app.post('/signup', userController.postSignup); app.get('/contact', contactController.getContact); diff --git a/controllers/forgot.js b/controllers/forgot.js deleted file mode 100644 index d4431efd91..0000000000 --- a/controllers/forgot.js +++ /dev/null @@ -1,85 +0,0 @@ -var async = require('async'); -var crypto = require('crypto'); -var nodemailer = require("nodemailer"); -var User = require('../models/User'); -var secrets = require('../config/secrets'); - -/** - * GET /forgot - * Forgot Password page. - */ - -exports.getForgot = function(req, res) { - if (req.isAuthenticated()) { - return res.redirect('/'); - } - res.render('account/forgot', { - title: 'Forgot Password' - }); -}; - -/** - * POST /forgot - * Create a random token, then the send user an email with a reset link. - * @param email - */ - -exports.postForgot = function(req, res, next) { - req.assert('email', 'Please enter a valid email address.').isEmail(); - - var errors = req.validationErrors(); - - if (errors) { - req.flash('errors', errors); - return res.redirect('/forgot'); - } - - async.waterfall([ - function(done) { - crypto.randomBytes(16, function(err, buf) { - var token = buf.toString('hex'); - done(err, token); - }); - }, - function(token, done) { - User.findOne({ email: req.body.email.toLowerCase() }, function(err, user) { - if (!user) { - req.flash('errors', { msg: 'No account with that email address exists.' }); - return res.redirect('/forgot'); - } - - user.resetPasswordToken = token; - user.resetPasswordExpires = Date.now() + 3600000; // 1 hour - - user.save(function(err) { - done(err, token, user); - }); - }); - }, - function(token, user, done) { - var smtpTransport = nodemailer.createTransport('SMTP', { - service: 'SendGrid', - auth: { - user: secrets.sendgrid.user, - pass: secrets.sendgrid.password - } - }); - var mailOptions = { - to: user.email, - from: 'hackathon@starter.com', - subject: 'Reset your password on Hackathon Starter', - text: 'You are receiving this email because you (or someone else) have requested the reset of the password for your account.\n\n' + - 'Please click on the following link, or paste this into your browser to complete the process:\n\n' + - 'http://' + req.headers.host + '/reset/' + token + '\n\n' + - 'If you did not request this, please ignore this email and your password will remain unchanged.\n' - }; - smtpTransport.sendMail(mailOptions, function(err) { - req.flash('info', { msg: 'An e-mail has been sent to ' + user.email + ' with further instructions.' }); - done(err, 'done'); - }); - } - ], function(err) { - if (err) return next(err); - res.redirect('/forgot'); - }); -}; diff --git a/controllers/reset.js b/controllers/reset.js deleted file mode 100644 index fd28614e59..0000000000 --- a/controllers/reset.js +++ /dev/null @@ -1,93 +0,0 @@ -var async = require('async'); -var nodemailer = require('nodemailer'); -var User = require('../models/User'); -var secrets = require('../config/secrets'); - -/** - * GET /reset/:token - * Reset Password page. - */ - -exports.getReset = function(req, res) { - if (req.isAuthenticated()) { - return res.redirect('/'); - } - - User - .findOne({ resetPasswordToken: req.params.token }) - .where('resetPasswordExpires').gt(Date.now()) - .exec(function(err, user) { - if (!user) { - req.flash('errors', { msg: 'Password reset token is invalid or has expired.' }); - return res.redirect('/forgot'); - } - res.render('account/reset', { - title: 'Password Reset' - }); - }); -}; - -/** - * POST /reset/:token - * Process the reset password request. - */ - -exports.postReset = function(req, res, next) { - req.assert('password', 'Password must be at least 4 characters long.').len(4); - req.assert('confirm', 'Passwords must match.').equals(req.body.password); - - var errors = req.validationErrors(); - - if (errors) { - req.flash('errors', errors); - return res.redirect('back'); - } - - async.waterfall([ - function(done) { - User - .findOne({ resetPasswordToken: req.params.token }) - .where('resetPasswordExpires').gt(Date.now()) - .exec(function(err, user) { - if (!user) { - req.flash('errors', { msg: 'Password reset token is invalid or has expired.' }); - return res.redirect('back'); - } - - user.password = req.body.password; - user.resetPasswordToken = undefined; - user.resetPasswordExpires = undefined; - - user.save(function(err) { - if (err) return next(err); - req.logIn(user, function(err) { - done(err, user); - }); - }); - }); - }, - function(user, done) { - var smtpTransport = nodemailer.createTransport('SMTP', { - service: 'SendGrid', - auth: { - user: secrets.sendgrid.user, - pass: secrets.sendgrid.password - } - }); - var mailOptions = { - to: user.email, - from: 'hackathon@starter.com', - subject: 'Your Hackathon Starter password has been changed', - text: 'Hello,\n\n' + - 'This is a confirmation that the password for your account ' + user.email + ' has just been changed.\n' - }; - smtpTransport.sendMail(mailOptions, function(err) { - req.flash('success', { msg: 'Success! Your password has been changed.' }); - done(err); - }); - } - ], function(err) { - if (err) return next(err); - res.redirect('/'); - }); -}; diff --git a/controllers/user.js b/controllers/user.js index 0d6c53b816..f6941f985a 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -1,6 +1,10 @@ -var passport = require('passport'); var _ = require('underscore'); +var async = require('async'); +var crypto = require('crypto'); +var nodemailer = require('nodemailer'); +var passport = require('passport'); var User = require('../models/User'); +var secrets = require('../config/secrets'); /** * GET /login @@ -206,3 +210,172 @@ exports.getOauthUnlink = function(req, res, next) { }); }); }; + +/** + * GET /reset/:token + * Reset Password page. + */ + +exports.getReset = function(req, res) { + if (req.isAuthenticated()) { + return res.redirect('/'); + } + + User + .findOne({ resetPasswordToken: req.params.token }) + .where('resetPasswordExpires').gt(Date.now()) + .exec(function(err, user) { + if (!user) { + req.flash('errors', { msg: 'Password reset token is invalid or has expired.' }); + return res.redirect('/forgot'); + } + res.render('account/reset', { + title: 'Password Reset' + }); + }); +}; + +/** + * POST /reset/:token + * Process the reset password request. + */ + +exports.postReset = function(req, res, next) { + req.assert('password', 'Password must be at least 4 characters long.').len(4); + req.assert('confirm', 'Passwords must match.').equals(req.body.password); + + var errors = req.validationErrors(); + + if (errors) { + req.flash('errors', errors); + return res.redirect('back'); + } + + async.waterfall([ + function(done) { + User + .findOne({ resetPasswordToken: req.params.token }) + .where('resetPasswordExpires').gt(Date.now()) + .exec(function(err, user) { + if (!user) { + req.flash('errors', { msg: 'Password reset token is invalid or has expired.' }); + return res.redirect('back'); + } + + user.password = req.body.password; + user.resetPasswordToken = undefined; + user.resetPasswordExpires = undefined; + + user.save(function(err) { + if (err) return next(err); + req.logIn(user, function(err) { + done(err, user); + }); + }); + }); + }, + function(user, done) { + var smtpTransport = nodemailer.createTransport('SMTP', { + service: 'SendGrid', + auth: { + user: secrets.sendgrid.user, + pass: secrets.sendgrid.password + } + }); + var mailOptions = { + to: user.email, + from: 'hackathon@starter.com', + subject: 'Your Hackathon Starter password has been changed', + text: 'Hello,\n\n' + + 'This is a confirmation that the password for your account ' + user.email + ' has just been changed.\n' + }; + smtpTransport.sendMail(mailOptions, function(err) { + req.flash('success', { msg: 'Success! Your password has been changed.' }); + done(err); + }); + } + ], function(err) { + if (err) return next(err); + res.redirect('/'); + }); +}; + +/** + * GET /forgot + * Forgot Password page. + */ + +exports.getForgot = function(req, res) { + if (req.isAuthenticated()) { + return res.redirect('/'); + } + res.render('account/forgot', { + title: 'Forgot Password' + }); +}; + +/** + * POST /forgot + * Create a random token, then the send user an email with a reset link. + * @param email + */ + +exports.postForgot = function(req, res, next) { + req.assert('email', 'Please enter a valid email address.').isEmail(); + + var errors = req.validationErrors(); + + if (errors) { + req.flash('errors', errors); + return res.redirect('/forgot'); + } + + async.waterfall([ + function(done) { + crypto.randomBytes(16, function(err, buf) { + var token = buf.toString('hex'); + done(err, token); + }); + }, + function(token, done) { + User.findOne({ email: req.body.email.toLowerCase() }, function(err, user) { + if (!user) { + req.flash('errors', { msg: 'No account with that email address exists.' }); + return res.redirect('/forgot'); + } + + user.resetPasswordToken = token; + user.resetPasswordExpires = Date.now() + 3600000; // 1 hour + + user.save(function(err) { + done(err, token, user); + }); + }); + }, + function(token, user, done) { + var smtpTransport = nodemailer.createTransport('SMTP', { + service: 'SendGrid', + auth: { + user: secrets.sendgrid.user, + pass: secrets.sendgrid.password + } + }); + var mailOptions = { + to: user.email, + from: 'hackathon@starter.com', + subject: 'Reset your password on Hackathon Starter', + text: 'You are receiving this email because you (or someone else) have requested the reset of the password for your account.\n\n' + + 'Please click on the following link, or paste this into your browser to complete the process:\n\n' + + 'http://' + req.headers.host + '/reset/' + token + '\n\n' + + 'If you did not request this, please ignore this email and your password will remain unchanged.\n' + }; + smtpTransport.sendMail(mailOptions, function(err) { + req.flash('info', { msg: 'An e-mail has been sent to ' + user.email + ' with further instructions.' }); + done(err, 'done'); + }); + } + ], function(err) { + if (err) return next(err); + res.redirect('/forgot'); + }); +};