vue-express-mongo-boilerplate
Version:
Express NodeJS application server boilerplate with Mongo and VueJS
230 lines (186 loc) • 5.73 kB
JavaScript
;
let config = require("../config");
let logger = require("../core/logger");
let crypto = require("crypto");
let async = require("async");
let passport = require("passport");
let express = require("express");
let mailer = require("../libs/mailer");
let User = require("../models/user");
let Response = require("../core/response");
/**
* Generate JSON or HTML response to client,
* If browser accept JSON and not HTML, we send
* JSON response. Else we redirect to an URL
* which defined in `redirect` parameter.
*
* If req.flash contains errors, we send back error messages too.
*
* @param {Object} req request object
* @param {Object} res response object
* @param {String} redirect redirect site URL.
* @param {Object} err Error object.
*/
function respond(req, res, redirect, err) {
if (req.accepts("json") && !req.accepts("html")) {
let flash = req.flash();
if (flash && flash.error && flash.error.length > 0) {
let errMessage = flash.error[0].msg;
Response.json(res, null, err || Response.REQUEST_FAILED, errMessage);
}
else {
let successData = "OK";
if (flash && flash.info && flash.info.length > 0)
successData = flash.info[0].msg;
Response.json(res, successData);
}
}
else if (redirect) {
// Redirect to the original url
if (req.session.returnTo) {
redirect = req.session.returnTo;
delete req.session.returnTo;
}
res.redirect(redirect);
}
}
module.exports = function(app, db) {
let authRouter = express.Router();
authRouter.post("/local", function(req, res, next) {
req.assert("username", req.t("UsernameCannotBeEmpty")).notEmpty();
let errors = req.validationErrors();
if (errors) {
req.flash("error", errors);
return respond(req, res, "/login", Response.BAD_REQUEST);
}
if (req.body.password) {
// Login with password
passport.authenticate("local", function(err, user, info) {
if (!user) {
req.flash("error", { msg: info.message });
return respond(req, res, "/login");
}
req.login(user, function(err) {
if (err) {
req.flash("error", { msg: err });
return respond(req, res, "/login");
}
// Success authentication
// Update user's record with login time
req.user.lastLogin = Date.now();
req.user.save(function() {
// Remove sensitive data before login
req.user.password = undefined;
req.user.salt = undefined;
respond(req, res, "/");
});
});
})(req, res, next);
} else {
// Passwordless login
async.waterfall([
function generateToken(done) {
crypto.randomBytes(25, function(err, buf) {
done(err, err ? null : buf.toString("hex"));
});
},
function getUser(token, done) {
let username = req.body.username;
User.findOne({
$or: [
{ "username": username},
{ "email": username}
]
}, function(err, user) {
if (!user) {
req.flash("error", { msg: req.t("UsernameIsNotAssociated", { username: username}) });
return done("Invalid username or email: " + username);
}
// Check that the user is not disabled or deleted
if (user.status !== 1) {
req.flash("error", { msg: req.t("UserDisabledOrDeleted")});
return done(`User '${username} is disabled or deleted!`);
}
user.passwordLessToken = token;
//user.passwordLessTokenExpires = Date.now() + 3600000; // expire in 1 hour
user.save(function(err) {
done(err, token, user);
});
});
},
function sendResetEmailToUser(token, user, done) {
let subject = req.t("mailSubjectLogin", config);
res.render("mail/passwordLessLogin", {
name: user.fullName,
loginLink: "http://" + req.headers.host + "/passwordless/" + token
}, function(err, html) {
if (err)
return done(err);
mailer.send(user.email, subject, html, function(err, info) {
if (err)
req.flash("error", { msg: req.t("UnableToSendEmail", user) });
else
req.flash("info", { msg: req.t("emailSentWithMagicLink", user) });
done(err);
});
});
}
], function(err, user) {
if (err) {
logger.error(err);
}
respond(req, res, "back");
});
}
});
/**
* Google authentication routes
*
* Available scopes: https://developers.google.com/+/web/api/rest/oauth#authorization-scopes
*/
authRouter.get("/google", passport.authenticate("google", {
scope: "profile email"
/*scope: [
'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/plus.profile.emails.read'
]*/
}));
authRouter.get("/google/callback", passport.authenticate("google", {
failureRedirect: "/login"
}), function(req, res) {
res.redirect("/");
});
/**
* Facebook authentication routes
*/
authRouter.get("/facebook", passport.authenticate("facebook", {
scope: ["email", "user_location"]
}));
authRouter.get("/facebook/callback", passport.authenticate("facebook", {
failureRedirect: "/login"
}), function(req, res) {
res.redirect("/");
});
/**
* Twitter authentication routes
*/
authRouter.get("/twitter", passport.authenticate("twitter"));
authRouter.get("/twitter/callback", passport.authenticate("twitter", {
failureRedirect: "/login"
}), function(req, res) {
res.redirect("/");
});
/**
* Github authentication routes
*/
authRouter.get("/github", passport.authenticate("github", {
scope: "user:email"
}));
authRouter.get("/github/callback", passport.authenticate("github", {
failureRedirect: "/login"
}), function(req, res) {
res.redirect("/");
});
// Add router to app
app.use("/auth", authRouter);
};