UNPKG

glintcms-starter-glintcms

Version:

This is a WebSite implementation with GlintCMS. It shows how you can use GlintCMS.

427 lines (368 loc) 11.5 kB
var debug = require('debug')('page-auth:controller'); var async = require('async'); var crypto = require('crypto'); var nodemailer = require('nodemailer'); var passport = require('passport'); var jade = require('jade'); var User = require('./model'); var secrets = require('./secrets'); var view = require('./view'); exports = module.exports = function authController(o) { /** * Expose User gravatar * * @type {User.gravatar} */ exports.gravatar = User.gravatar; /** * GET /login * Login page. */ exports.getLogin = function(req, res, next) { if (req.user) return res.redirect('/'); view(o).login .load(res.locals, function(err, result) { if (err) next(err); res.send(result.page); }); }; /** * POST /login * Sign in using email and password. */ exports.postLogin = function(req, res, next) { req.assert('email', req.__('Email is not valid')).isEmail(); req.assert('password', req.__('Password cannot be blank')).notEmpty(); var errors = req.validationErrors(); if (errors) { req.flash('errors', errors); return res.redirect('/login'); } passport.authenticate('local', function(err, user, info) { debug('login', err, user, info); if (err) return next(err); if (!user) { req.flash('errors', {msg: info.message}); return res.redirect('/login'); } req.logIn(user, function(err) { if (err) return next(err); req.flash('success', {msg: 'Success! You are logged in.'}); res.redirect(req.session.returnTo || '/'); }); })(req, res, next); }; /** * GET /logout * Log out. */ exports.logout = function(req, res) { req.logout(); res.redirect('/'); }; /** * GET /signup * Signup page. */ exports.getSignup = function(req, res, next) { if (req.user) return res.redirect('/'); view(o).signup .load(res.locals, function(err, result) { if (err) next(err); res.send(result.page); }); }; /** * GET /signin * Signin page. (Login + Signup) */ exports.getSignin = function(req, res, next) { if (req.user) return res.redirect('/'); view(o).signin .load(res.locals, function(err, result) { if (err) next(err); res.send(result.page); }); }; /** * POST /signup * Create a new local account. */ exports.postSignup = function(req, res, next) { req.assert('email', 'Email is not valid').isEmail(); req.assert('password', 'Password must be at least 4 characters long').len(4); req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password); var errors = req.validationErrors(); if (errors) { req.flash('errors', errors); return res.redirect('/signup'); } var user = new User({ email: req.body.email, password: req.body.password }); User.findOne({email: req.body.email}, function(err, existingUser) { if (existingUser) { req.flash('errors', {msg: 'Account with that email address already exists.'}); return res.redirect('/signup'); } user.save(function(err) { if (err) return next(err); req.logIn(user, function(err) { if (err) return next(err); res.redirect('/'); }); }); }); }; /** * GET /account * Profile page. */ exports.getAccount = function(req, res, next) { debug('getAccount', res.locals); view(o).account .load(res.locals, function(err, result) { if (err) next(err); res.send(result.page); }); }; /** * POST /account/profile * Update profile information. */ exports.postUpdateProfile = function(req, res, next) { User.findById(req.user.id, function(err, user) { if (err) return next(err); user.email(req.body.email || ''); user.profileName(req.body.name || ''); user.profileGender(req.body.gender || ''); user.profileLocation(req.body.location || ''); user.profileWebsite(req.body.website || ''); user.save(function(err) { if (err) return next(err); req.flash('success', {msg: 'Profile information updated.'}); res.redirect('/account'); }); }); }; /** * POST /account/password * Update current password. */ exports.postUpdatePassword = function(req, res, next) { req.assert('password', 'Password must be at least 4 characters long').len(4); req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password); var errors = req.validationErrors(); if (errors) { req.flash('errors', errors); return res.redirect('/account'); } User.findById(req.user.id, function(err, user) { if (err) return next(err); user.changePassword(req.body.password); user.save(function(err) { if (err) return next(err); req.flash('success', {msg: 'Password has been changed.'}); res.redirect('/account'); }); }); }; /** * POST /account/delete * Delete user account. */ exports.postDeleteAccount = function(req, res, next) { User.findById(req.user.id, function(err, user) { if (err) return next(err); user.remove(function(err, result) { if (err) return next(err); req.logout(); req.flash('info', {msg: 'Your account has been deleted.'}); res.redirect('/'); }); }); }; /** * GET /account/unlink/:provider * Unlink OAuth provider. */ exports.getOauthUnlink = function(req, res, next) { var provider = req.params.provider; User.findById(req.user.id, function(err, user) { if (err) return next(err); if (typeof user[provider] === 'function') { user[provider](undefined); } function remainigTokens() { return user.tokens.filter(function(token) { return token.kind !== provider; }); } user.tokens(remainigTokens()); user.save(function(err) { if (err) return next(err); req.flash('info', {msg: provider + ' account has been unlinked.'}); res.redirect('/account'); }); }); }; /** * GET /reset/:token * Reset Password page. */ exports.getReset = function(req, res, next) { if (req.isAuthenticated()) { return res.redirect('/'); } User.findOne({ $and: [ {resetPasswordToken: req.params.token}, {resetPasswordExpires: {$gt: Date.now()}} ] }, function(err, user) { if (!user) { req.flash('errors', {msg: 'Password reset token is invalid or has expired.'}); return res.redirect('/forgot'); } view(o).reset .load(res.locals, function(err, result) { if (err) next(err); res.send(result.page); }); }); }; /** * 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({ $and: [ {resetPasswordToken: req.params.token}, {resetPasswordExpires: {$gt: Date.now()}} ] }, 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 transporter = nodemailer.createTransport({ 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' }; transporter.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, next) { if (req.isAuthenticated()) { return res.redirect('/'); } view(o).forgot .load(res.locals, function(err, result) { if (err) next(err); res.send(result.page); }); }; /** * POST /forgot * Create a random token, then the send user an email with a reset link. */ 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 transporter = nodemailer.createTransport({ 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' }; transporter.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'); }); }; return exports; }