diff options
| author | Jules Laplace <jules@okfoc.us> | 2014-07-02 16:22:51 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2014-07-02 16:22:51 -0400 |
| commit | 221a14315b09946db2485036bbf4a80295dc4889 (patch) | |
| tree | a0c96d11dac2aed77cc453e2fcb9841fcae4d19e /server/lib/auth/index.js | |
| parent | bde9f3e47d66a1c8a334763146671320ac0359f9 (diff) | |
password reset / username dupe stuff from PH
Diffstat (limited to 'server/lib/auth/index.js')
| -rw-r--r-- | server/lib/auth/index.js | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/server/lib/auth/index.js b/server/lib/auth/index.js new file mode 100644 index 0000000..99af9b5 --- /dev/null +++ b/server/lib/auth/index.js @@ -0,0 +1,331 @@ +/* jshint node: true */ + +var passport = require('passport'), + FacebookStrategy = require('passport-facebook').Strategy, + TwitterStrategy = require('passport-twitter').Strategy, + LocalStrategy = require('passport-local').Strategy, + passportSocketIo = require("passport.socketio"), + cookieParser = require('express').cookieParser, + crypto = require('crypto'), + express = require('express'), + _ = require('lodash'), + mongoose = require('mongoose'), + util = require('../util'), + config = require('../../../config.json'), + User = require('../schemas/User'); + +var auth = { + views: require('./views'), + mail: require('./mail'), + + init: function () { + passport.serializeUser(auth.serializeUser); + passport.deserializeUser(auth.deserializeUser); + + passport.use(new LocalStrategy(auth.verifyLocalUser)) + + passport.use(new TwitterStrategy({ + consumerKey: process.env.VVALLS_TWITTER_KEY || 'brI5VqBak5yrhCcxU56lj5L3v', + consumerSecret: process.env.VVALLS_TWITTER_SECRET || 'ThzaEVWUgkmfzqOs3qcrdonGzgDBjDHTVzPkfY0wFJxjUH6JWZ', + callbackURL: 'http://' + config.host + '/auth/twitter/callback' + }, auth.insertTwitterUser)); + + /* + passport.use(new FacebookStrategy({ + clientID: process.env.VVALLS_FACEBOOK_KEY || '719828821410310', + clientSecret: process.env.VVALLS_FACEBOOK_SECRET || 'f9aba78e08f37f621eadb88b1409d48c', + callbackURL: 'http://' + config.host + '/auth/facebook/callback', + enableProof: false, + }, auth.insertFacebookUser)); + */ + auth.mail.init() + }, + + initSockets: function (io, SessionStore) { + io.set('authorization', passportSocketIo.authorize({ + cookieParser: express.cookieParser, + passport: passport, + key: 'vvalls.sid', // the name of the cookie where express/connect stores its session_id + secret: 'flibbertigibbet', // the session_secret to parse the cookie + store: SessionStore, // we NEED to use a sessionstore. no memorystore please + success: auth.socketSuccess, + fail: auth.socketFail, + })); + }, + + socketSuccess: function (data, accept) { + // console.error('successful connection to socket.io'); + accept(null, true); + }, + + socketFail: function (data, message, error, accept){ + if (error) { + throw new Error(message); + } + // console.log(data) + console.error('failed connection to socket.io:', message); + + // We use this callback to log all of our failed connections. + accept(null, false); + }, + + // technically these return the login middleware + login: function (strategy) { + return passport.authenticate(strategy); + }, + + loggedIn: function (strategy) { + return function (req, res, next) { + console.log("attempting to use", strategy) + + passport.authenticate(strategy, function(err, user, info){ + if (err) { + return next(err); + } + if (! user) { + req.session.userData = info + return res.redirect('/auth/usernameTaken'); + } + if (! user.created_ip) { + user.created_ip = util.ip2num( req.ip ) + } + user.last_ip = util.ip2num( req.ip ) + user.save(function(err, data){ if (err) console.err('error setting ip for user') }) + + req.logIn(user, function(err) { + if (err) { return next(err); } + var returnTo = req.session.returnTo + delete req.session.returnTo + return res.redirect( returnTo || "/profile" ); + }); + })(req, res, next); + } + }, + + loggedInLocal: function (req, res, next) { + passport.authenticate("local", function(err, user, info){ + if (err) { + return res.json({ error: err }); + } + if (! user) { + return info ? res.json(info) : res.redirect("/login"); + } + + user.last_ip = util.ip2num( req.ip ) + user.save(function(err, data){ if (err) console.err('error setting ip for user') }) + + req.logIn(user, function(err) { + if (err) { return next(err); } + var returnTo = req.session.returnTo + delete req.session.returnTo + return res.json({ status: "OK", returnTo: returnTo || "/profile" }) + }); + })(req, res, next); + }, + + logout: function (req, res) { + req.logout(); + res.redirect('/'); + }, + + serializeUser: function (user, done) { + done(null, user._id); + }, + + deserializeUser: function (id, done) { + try { + var _id = mongoose.Types.ObjectId(id) + User.findOne({ _id: _id }, "_id displayName username photo isStaff", function (err, user) { + done(err, user); + }); + } + catch (e) { + User.findOne({ twitter_id: id }, "_id displayName username photo isStaff", function (err, user) { + done(err, user); + }); + } + }, + + signup: function (req, res){ + var username = util.trim(req.body.username) + var password = req.body.password + var email = util.trim(req.body.email) + + var shasum = crypto.createHash('sha1') + shasum.update(password) + password = shasum.digest('hex'); + + User.findByUsername(username, function (err, user) { + if (user) { + res.json({ error: { errors: { username: { message: "Username has been taken" } } } }) + return + } + + User.findByEmail(email, function (err, user) { + if (user) { + res.json({ error: { errors: { username: { message: "Email has already been used" } } } }) + return + } + var data = { + username: username, + displayName: username, + password: password, + email: email, + created_ip: util.ip2num( req.ip ), + last_ip: util.ip2num( req.ip ), + created_at: new Date () + } + new User(data).save(function(err, user){ + if (err || ! data) { return res.json({ error: err }) } + req.login(user, function(){ + auth.mail.welcome(user, function(){ + res.json({ status: "OK", payload: user }) + }) + }) + }) + }) + }) + }, + + verifyLocalUser: function (username, password, done) { + User.findByUsername(username, function(err, user){ + if (err) { return done(err); } + if (! user) { + return done(null, false, { error: { errors: { username: { message: 'No such username.' } }}}) + } + if (! user.validPassword(password)) { + return done(null, false, { error: { errors: { password: { message: 'Incorrect password.' } }}}) + } + return done(null, user); + }); + }, + + insertTwitterUser: function (accessToken, refreshToken, profile, done) { + process.nextTick(function () { + var userData = { + twitter_id: profile.id, + username: profile.username, + displayName: profile.displayName, + photo: profile.photos[0].value, + twitterName: profile.username, + }; + User.findOne({twitter_id: profile.id}, function(err, data){ + if (! err && data) { + return done(err, data); + } + User.findByUsername(profile.username, function(err, data){ + if (data) { + return done(null, false, userData) + } + new User(userData).save(function(err, data){ + if (err) { + console.error(err) + } + return done(err, data) + }) + }) + }); + + }); + }, + + insertFacebookUser: function (accessToken, refreshToken, profile, done) { + process.nextTick(function () { + var userData = { + facebook_id: profile.id, + username: profile.username || profile.displayName.toLowerCase().replace(/ /g,'-'), + displayName: profile.displayName, + photo: "http://graph.facebook.com/" + profile.id + "/picture?type=large", + facebookUrl: profile.username ? "https://facebook.com/" + profile.username : "" + }; + + User.findOne({twitter_id: profile.id}, function(err, data){ + if (! err && data) { + return done(err, data); + } + User.findByUsername(profile.username, function(err, data){ + if (data) { + return done(null, false, userData) + } + new User(userData).save(function(err, data){ + if (err) { + console.error(err) + } + return done(err, data) + }) + }) + }); + + }); + }, + + usernameFixed: function (req, res) { + + var userData = req.session.userData + if (! userData) { + return res.redirect("/") + } + if (req.isAuthenticated()) { + delete req.session.userData + return res.redirect("/") + } + + var username = util.sanitize(req.body.username) + + User.findByUsername(username, function(err, doc){ + if (err || doc) { + res.json({ error: { errors: { username: { message: "Username has been taken" } } } }) + return + } + userData.username = username + + new User(userData).save(function(err, user){ + req.logIn(user, function(err) { + if (err) { return res.json(err); } + var returnTo = req.session.returnTo + delete req.session.returnTo + return res.json({ status: "OK", returnTo: returnTo || "/profile" }) + }); + }) + }) + }, + + forgotPassword: function (req, res) { + User.findByEmail(req.body.email, function(err, user){ + if (err || ! user) { + res.json({ error: { errors: { email: { message: "That email address was not found." } } } }) + return + } + User.resetPasswordNonce(user, function(err){ + auth.mail.forgotPassword(user, function(){ + res.json({ success: 'OK' }) + }) + }) + }) + }, + + resetPassword: function (req, res) { + var password = req.body.password + + var shasum = crypto.createHash('sha1') + shasum.update(password) + password = shasum.digest('hex'); + + User.findOne({ passwordNonce: req.body.nonce }, function (err, user){ + if (err || ! user) { + res.json({ error: { errors: { email: { message: "That reset token has already been used." } } } }) + return + } + user.password = password + user.passwordNonce = "" + user.save(function(){ + req.login(user, function(){ + res.json({ status: "OK", payload: user }) + }) + }) + }) + }, + +} + +module.exports = auth |
