/* 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