From 8e5714cab410b63d3dc00781d2457c4603e3931e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 2 May 2013 11:11:10 -0400 Subject: [PATCH] skeleton for twitter integration via passport --- config.default.js | 4 ++++ package.json | 1 + public/templates/footer.tpl | 1 + src/user.js | 40 ++++++++++++++++++++++++++++++++++--- src/webserver.js | 38 ++++++++++++++++++----------------- 5 files changed, 63 insertions(+), 21 deletions(-) diff --git a/config.default.js b/config.default.js index ed2c5eacc2..8c5a546c50 100644 --- a/config.default.js +++ b/config.default.js @@ -13,6 +13,10 @@ var config = { options: { } + }, + "twitter": { + "key": '', + "secret": '' } } diff --git a/package.json b/package.json index 67cc1abef8..cb853c9be6 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "crypto": "0.0.3", "passport": "0.1.16", "passport-local": "0.1.6", + "passport-twitter": "0.1.4", "less-middleware": "0.1.11" }, "devDependencies": {}, diff --git a/public/templates/footer.tpl b/public/templates/footer.tpl index dd3de05b00..08fb9d2fb7 100644 --- a/public/templates/footer.tpl +++ b/public/templates/footer.tpl @@ -45,6 +45,7 @@ }); socket.emit('api:user.get', { fields: ['username', 'picture'] }); socket.on('api:user.get', function(data) { + console.log(data); if (data.uid > 0) { var gravatar = document.createElement('img'), name = document.createElement('span') diff --git a/src/user.js b/src/user.js index c0161db737..1d3ae16402 100644 --- a/src/user.js +++ b/src/user.js @@ -32,6 +32,7 @@ var config = require('../config.js'), if (returnData.picture !== undefined) { var md5sum = crypto.createHash('md5'); + if (!returnData.email) returnData.email = ''; md5sum.update(returnData.email.toLowerCase()); returnData.picture = 'http://www.gravatar.com/avatar/' + md5sum.digest('hex') + '?s=24'; if (removeEmail) delete returnData.email; @@ -123,6 +124,31 @@ var config = require('../config.js'), } } + User.loginViaTwitter = function(twid, handle, callback) { + User.get_uid_by_twitter_id(twid, function(uid) { + if (uid !== null) { + // Existing User + callback(null, { + uid: uid + }); + } else { + // New User + User.create(handle, null, null, function(err, uid) { + if (err !== null) { + callback(err); + } else { + // Save twitter-specific information to the user + RDB.set('uid:' + uid + ':twid', twid); + RDB.set('twid:' + twid + ':uid', uid); + callback(null, { + uid: uid + }); + } + }); + } + }) + } + User.logout = function(sessionID, callback) { User.get_uid_by_session(sessionID, function(uid) { if (uid) { @@ -142,9 +168,11 @@ var config = require('../config.js'), RDB.incr('global:next_user_id', function(uid) { RDB.set('username:' + username + ':uid', uid); RDB.set('uid:' + uid + ':username', username); - RDB.set('uid:' + uid + ':password', password); - RDB.set('uid:' + uid + ':email', email); - RDB.set('email:' + email, uid); + if (password) RDB.set('uid:' + uid + ':password', password); + if (email) { + RDB.set('uid:' + uid + ':email', email); + RDB.set('email:' + email, uid); + } RDB.incr('user:count', function(count) { io.sockets.emit('user.count', {count: count}); @@ -190,6 +218,12 @@ var config = require('../config.js'), RDB.get('sess:' + session + ':uid', callback); }; + User.get_uid_by_twitter_id = function(twid, callback) { + RDB.get('twid:' + twid + ':uid', function(uid) { + callback(uid); + }); + } + User.session_ping = function(sessionID, uid) { // Start, replace, or extend a session RDB.get('sess:' + sessionID, function(session) { diff --git a/src/webserver.js b/src/webserver.js index 32869b2bc1..586c462a9c 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -7,7 +7,8 @@ var express = require('express'), redis = require('redis'), redisServer = redis.createClient(config.redis.port, config.redis.host, config.redis.options), passport = require('passport'), - passportLocal = require('passport-local').Strategy; + passportLocal = require('passport-local').Strategy, + passportTwitter = require('passport-twitter').Strategy; passport.use(new passportLocal(function(user, password, next) { global.modules.user.loginViaLocal(user, password, function(login) { @@ -16,6 +17,17 @@ passport.use(new passportLocal(function(user, password, next) { }); })); +passport.use(new passportTwitter({ + consumerKey: config.twitter.key, + consumerSecret: config.twitter.secret, + callbackURL: config.url + "auth/twitter/callback" +}, function(token, tokenSecret, profile, done) { + global.modules.user.loginViaTwitter(profile.id, profile.username, function(err, user) { + if (err) { return done(err); } + done(null, user); + }); +})); + passport.serializeUser(function(user, done) { done(null, user.uid); }); @@ -62,23 +74,6 @@ passport.deserializeUser(function(uid, done) { global.modules.user.session_ping(req.sessionID, req.user.uid); } - // if (req.session.uid === undefined) { - // console.log('info: [Auth] First load, retrieving uid...'); - - // global.modules.user.get_uid_by_session(req.sessionID, function(uid) { - // if (uid !== null) { - // req.session.uid = uid; - // console.log('info: [Auth] uid ' + req.session.uid + ' found. Welcome back.'); - // } else { - // req.session.uid = 0; - // console.log('info: [Auth] No login session found.'); - // } - // }); - // } else { - // // console.log('SESSION: ' + req.sessionID); - // // console.log('info: [Auth] Ping from uid ' + req.session.uid); - // } - // (Re-)register the session as active global.modules.user.active.register(req.sessionID); @@ -152,6 +147,13 @@ passport.deserializeUser(function(uid, done) { }); }); + app.get('/auth/twitter', passport.authenticate('twitter')); + + app.get('/auth/twitter/callback', passport.authenticate('twitter', { + successRedirect: '/', + failureRedirect: '/login' + })); + app.get('/reset/:code', function(req, res) { res.send(templates['header'] + templates['reset_code'].parse({ reset_code: req.params.code }) + templates['footer']); });