diff --git a/app.js b/app.js index 96b367830c..a6391208cd 100644 --- a/app.js +++ b/app.js @@ -15,13 +15,6 @@ global.configuration = {}; global.modules = modules; -process.on('uncaughtException', function(err) { - // handle the error safely - console.log("error message "+err); - global.socket.emit('event:consolelog',{type:'uncaughtException',stack:err.stack,error:err.toString()}); -}); - - (function(config) { config['ROOT_DIRECTORY'] = __dirname; diff --git a/config.default.js b/config.default.js index 8c5a546c50..0e20f9672b 100644 --- a/config.default.js +++ b/config.default.js @@ -17,6 +17,10 @@ var config = { "twitter": { "key": '', "secret": '' + }, + "google": { + "id": '', + "secret": '' } } diff --git a/package.json b/package.json index cb853c9be6..072503960a 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "passport": "0.1.16", "passport-local": "0.1.6", "passport-twitter": "0.1.4", + "passport-google-oauth": "0.1.5", "less-middleware": "0.1.11" }, "devDependencies": {}, diff --git a/public/css/style.less b/public/css/style.less index d8920f5604..4852b00ab4 100644 --- a/public/css/style.less +++ b/public/css/style.less @@ -22,6 +22,15 @@ body { background: #fdfdfd; } + +.none { + display: none; +} + +.block { + display: block; +} + @media (min-width: 979px) { body { padding-top: 60px; @@ -200,6 +209,7 @@ footer.footer { border: 1px solid #999; margin-right: 8px; margin-top: -2px; + float: left; } span { @@ -219,14 +229,33 @@ footer.footer { padding: 0; li { - .inline-block; + vertical-align: top; + background: transparent; + .none; .pointer; - } -} -.none { - display: none !important; -} -.block { - display: block !important; + &.google { + width: 202px; + height: 32px; + background-image: url('../images/google_login.png'); + + &:hover { + background-position-x: -265px; + } + + &:active { + background-position-x: -535px; + } + } + + &.twitter { + width: 158px; + height: 28px; + background-image: url('../images/twitter_login.png'); + } + + &.active { + .inline-block; + } + } } diff --git a/public/images/google_login.png b/public/images/google_login.png new file mode 100644 index 0000000000..55abc2bc78 Binary files /dev/null and b/public/images/google_login.png differ diff --git a/public/templates/login.tpl b/public/templates/login.tpl index 304b8bd180..6f5bf0a752 100644 --- a/public/templates/login.tpl +++ b/public/templates/login.tpl @@ -15,7 +15,18 @@

Alternative Logins

- \ No newline at end of file + + + \ No newline at end of file diff --git a/src/posts.js b/src/posts.js index 9e46407864..35fdaa30a1 100644 --- a/src/posts.js +++ b/src/posts.js @@ -60,7 +60,7 @@ var RDB = require('./redis.js'), } - Posts.reply = function(tid, uid, content) { + Posts.reply = function(socket, tid, uid, content) { Posts.create(uid, content, function(pid) { RDB.rpush('tid:' + tid + ':posts', pid); diff --git a/src/topics.js b/src/topics.js index 15cadbb806..ba8da84519 100644 --- a/src/topics.js +++ b/src/topics.js @@ -93,8 +93,8 @@ var RDB = require('./redis.js'), }); } - - Topics.post = function(uid, title, content, category) { + Topics.post = function(socket, uid, title, content, category) { + if (uid === 0) { socket.emit('event:alert', { title: 'Thank you for posting', @@ -144,7 +144,6 @@ var RDB = require('./redis.js'), // User Details - move this out later RDB.lpush('uid:' + uid + ':topics', tid); - socket.emit('event:alert', { title: 'Thank you for posting', message: 'You have successfully posted. Click here to view your post.', diff --git a/src/user.js b/src/user.js index 1d3ae16402..ddcc07372a 100644 --- a/src/user.js +++ b/src/user.js @@ -7,7 +7,7 @@ var config = require('../config.js'), (function(User) { - User.get = function(uid, fields) { + User.get = function(socket, uid, fields) { if (uid > 0) { var keys = [], returnData = { @@ -48,7 +48,7 @@ var config = require('../config.js'), } } - User.login = function(user) { + User.login = function(socket, user) { if (user.username == null || user.password == null) { return socket.emit('user.login', {'status': 0, 'message': 'Missing fields'}); } @@ -146,7 +146,32 @@ var config = require('../config.js'), } }); } - }) + }); + } + + User.loginViaGoogle = function(gplusid, handle, email, callback) { + User.get_uid_by_google_id(gplusid, function(uid) { + if (uid !== null) { + // Existing User + callback(null, { + uid: uid + }); + } else { + // New User + User.create(handle, null, email, function(err, uid) { + if (err !== null) { + callback(err); + } else { + // Save twitter-specific information to the user + RDB.set('uid:' + uid + ':gplusid', gplusid); + RDB.set('gplusid:' + gplusid + ':uid', uid); + callback(null, { + uid: uid + }); + } + }); + } + }); } User.logout = function(sessionID, callback) { @@ -160,7 +185,7 @@ var config = require('../config.js'), } User.create = function(username, password, email, callback) { - User.exists(username, function(exists) { + User.exists(null, username, function(exists) { if (exists) { return callback('user-exists', 0); } @@ -187,7 +212,7 @@ var config = require('../config.js'), }; - User.exists = function(username, callback) { + User.exists = function(socket, username, callback) { User.get_uid_by_username(username, function(exists) { exists = !!exists; @@ -195,12 +220,14 @@ var config = require('../config.js'), else socket.emit('user.exists', {exists: exists}); }); }; - User.count = function() { + + User.count = function(socket) { RDB.get('user:count', function(count) { socket.emit('user.count', {count: (count === null) ? 0 : count}); }); }; - User.latest = function() { + + User.latest = function(socket) { RDB.lrange('user:users', 0, 0, function(username) { socket.emit('user.latest', {username: username}); }); @@ -224,6 +251,12 @@ var config = require('../config.js'), }); } + User.get_uid_by_google_id = function(gplusid, callback) { + RDB.get('gplusid:' + gplusid + ':uid', function(uid) { + callback(uid); + }); + } + User.session_ping = function(sessionID, uid) { // Start, replace, or extend a session RDB.get('sess:' + sessionID, function(session) { @@ -233,7 +266,7 @@ var config = require('../config.js'), } User.reset = { - validate: function(code, callback) { + validate: function(socket, code, callback) { if (typeof callback !== 'function') callback = undefined; RDB.get('reset:' + code + ':uid', function(uid) { @@ -256,7 +289,7 @@ var config = require('../config.js'), } }); }, - send: function(email) { + send: function(socket, email) { User.get_uid_by_email(email, function(uid) { if (uid !== null) { // Generate a new reset code @@ -305,7 +338,7 @@ var config = require('../config.js'), } }); }, - commit: function(code, password) { + commit: function(socket, code, password) { this.validate(code, function(validated) { if (validated) { RDB.get('reset:' + code + ':uid', function(uid) { @@ -321,7 +354,7 @@ var config = require('../config.js'), } User.email = { - exists: function(email, callback) { + exists: function(socket, email, callback) { User.get_uid_by_email(email, function(exists) { exists = !!exists; if (typeof callback !== 'function') socket.emit('user.email.exists', { exists: exists }); @@ -331,7 +364,7 @@ var config = require('../config.js'), } User.active = { - get_record : function() { + get_record : function(socket) { RDB.mget(['global:active_user_record', 'global:active_user_record_date'], function(data) { socket.emit('api:user.active.get_record', {record: data[0], timestamp: data[1]}); }); diff --git a/src/webserver.js b/src/webserver.js index cb9e26ac31..0b611681e8 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -9,6 +9,7 @@ var express = require('express'), passport = require('passport'), passportLocal = require('passport-local').Strategy, passportTwitter = require('passport-twitter').Strategy, + passportGoogle = require('passport-google-oauth').OAuth2Strategy, login_strategies = []; passport.use(new passportLocal(function(user, password, next) { @@ -22,7 +23,7 @@ if (config.twitter && config.twitter.key && config.twitter.key.length > 0 && con passport.use(new passportTwitter({ consumerKey: config.twitter.key, consumerSecret: config.twitter.secret, - callbackURL: config.url + "auth/twitter/callback" + 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); } @@ -33,6 +34,21 @@ if (config.twitter && config.twitter.key && config.twitter.key.length > 0 && con login_strategies.push('twitter'); } +if (config.google.id.length > 0 && config.google.secret.length > 0) { + passport.use(new passportGoogle({ + clientID: config.google.id, + clientSecret: config.google.secret, + callbackURL: config.url + 'auth/google/callback' + }, function(accessToken, refreshToken, profile, done) { + global.modules.user.loginViaGoogle(profile.id, profile.displayName, profile.emails[0].value, function(err, user) { + if (err) { return done(err); } + done(null, user); + }); + })) + + login_strategies.push('google'); +} + passport.serializeUser(function(user, done) { done(null, user.uid); }); @@ -140,12 +156,11 @@ passport.deserializeUser(function(uid, done) { 'alternate_logins:display': 'block' } for (var i=0, ii=num_strategies; i