summaryrefslogtreecommitdiff
path: root/server/lib/auth/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/auth/index.js')
-rw-r--r--server/lib/auth/index.js331
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