From cb3ebccbbfce492933510992b4e2394e3e57c731 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 18 Nov 2014 15:50:37 -0800 Subject: [PATCH] feat(invite-friends): obfuscated invite --- public/js/controllers/groupsCtrl.js | 32 ++++++++++++------------- src/controllers/user.js | 27 ++++++++++++++------- src/middleware.js | 8 +++---- src/utils.js | 17 ++++++++++++- views/shared/modals/invite-friends.jade | 8 +++---- 5 files changed, 59 insertions(+), 33 deletions(-) diff --git a/public/js/controllers/groupsCtrl.js b/public/js/controllers/groupsCtrl.js index 1d4456d09e..3322087c58 100644 --- a/public/js/controllers/groupsCtrl.js +++ b/public/js/controllers/groupsCtrl.js @@ -73,22 +73,22 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', ' }); } - var serializeQs = function(obj, prefix){ - var str = []; - for(var p in obj) { - if (obj.hasOwnProperty(p)) { - var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p]; - str.push(typeof v == "object" ? - serializeQs(v, k) : - encodeURIComponent(k) + "=" + encodeURIComponent(v)); - } - } - return str.join("&"); - } - - $scope.inviteLink = function(obj){ - return window.env.BASE_URL + '?' + serializeQs({partyInvite: obj}); - } + //var serializeQs = function(obj, prefix){ + // var str = []; + // for(var p in obj) { + // if (obj.hasOwnProperty(p)) { + // var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p]; + // str.push(typeof v == "object" ? + // serializeQs(v, k) : + // encodeURIComponent(k) + "=" + encodeURIComponent(v)); + // } + // } + // return str.join("&"); + //} + // + //$scope.inviteLink = function(obj){ + // return window.env.BASE_URL + '?' + serializeQs({partyInvite: obj}); + //} $scope.emails = [{name:"",email:""},{name:"",email:""}]; $scope.inviter = User.user.profile.name; $scope.inviteEmails = function(inviter, emails){ diff --git a/src/controllers/user.js b/src/controllers/user.js index 6580971b7a..5b732dabdc 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -411,7 +411,7 @@ api.cast = function(req, res, next) { api.inviteFriends = function(req, res, next) { Group.findOne({type:'party', members:{'$in': [res.locals.user._id]}}).select('_id name').exec(function(err,party){ if (err) return next(err); - var link = nconf.get('BASE_URL') + '?' + qs.stringify({partyInvite:{id:party._id, inviter:res.locals.user._id, name:party.name}}); + var link = nconf.get('BASE_URL')+'?partyInvite='+ utils.encrypt(JSON.stringify({id:party._id, inviter:res.locals.user._id, name:party.name})); _.each(req.body.emails, function(invite){ if (invite.email) { var variables = [ @@ -426,17 +426,28 @@ api.inviteFriends = function(req, res, next) { res.send(200); }) } + api.sessionPartyInvite = function(req,res,next){ - if (req.session.partyInvite) { - var inv = res.locals.user.invitations; - if (!(inv.party && inv.party.id)) { + if (!req.session.partyInvite) return next(); + var inv = res.locals.user.invitations; + if (inv.party && inv.party.id) return next(); // already invited to a party + async.waterfall([ + function(cb){ + Group.findOne({_id:req.session.partyInvite.id, type:'party', members:{$in:[req.session.partyInvite.inviter]}}) + .select('invites members').exec(cb); + }, + function(group, cb){ + if (!group) return cb("Inviter not in party"); inv.party = req.session.partyInvite; - Group.update({_id:req.session.partyInvite.id},{$addToSet:{invites:res.locals.user._id}}); delete req.session.partyInvite; - return res.locals.user.save(next); + if (!~group.invites.indexOf(res.locals.user._id)) + group.invites.push(res.locals.user._id); //$addToSt + group.save(cb); + }, + function(saved, cb){ + res.locals.user.save(cb); } - } - next(); + ], next); } /** diff --git a/src/middleware.js b/src/middleware.js index d7a6902ead..ba5ed01f07 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -12,7 +12,7 @@ var shared = require('habitrpg-shared'); var request = require('request'); var os = require('os'); var moment = require('moment'); -var qs = require('qs'); +var utils = require('./utils'); module.exports.apiThrottle = function(app) { if (nconf.get('NODE_ENV') !== 'production') return; @@ -200,9 +200,9 @@ module.exports.locals = function(req, res, next) { }; // Put query-string party invitations into session to be handled later - var partyInvite = qs.parse(req.query.partyInvite); - if (partyInvite && partyInvite.id) - req.session.partyInvite = partyInvite; + try{ + req.session.partyInvite = JSON.parse(utils.decrypt(req.query.partyInvite)) + } catch(e){} next(); } diff --git a/src/utils.js b/src/utils.js index 0789038b5e..ba8dd47f95 100644 --- a/src/utils.js +++ b/src/utils.js @@ -90,4 +90,19 @@ module.exports.setupConfig = function(){ require('newrelic'); module.exports.ga = require('universal-analytics')(nconf.get('GA_ID')); -}; \ No newline at end of file +}; + +var algorithm = 'aes-256-ctr'; +module.exports.encrypt = function(text){ + var cipher = crypto.createCipher(algorithm,nconf.get('SESSION_SECRET')) + var crypted = cipher.update(text,'utf8','hex') + crypted += cipher.final('hex'); + return crypted; +} + +module.exports.decrypt = function(text){ + var decipher = crypto.createDecipher(algorithm,nconf.get('SESSION_SECRET')) + var dec = decipher.update(text,'hex','utf8') + dec += decipher.final('utf8'); + return dec; +} \ No newline at end of file diff --git a/views/shared/modals/invite-friends.jade b/views/shared/modals/invite-friends.jade index 47c8becda4..02e4ce0c8d 100644 --- a/views/shared/modals/invite-friends.jade +++ b/views/shared/modals/invite-friends.jade @@ -38,10 +38,10 @@ script(type='text/ng-template', id='modals/invite-friends.html') input.form-control(type='text', ng-model='inviter') .col-sm-4 button.btn.btn-primary(type='submit') Invite New User(s) - - hr - p.alert.alert-info Or share this link (copy/paste): - input.form-control(type='text', ng-value='inviteLink({id: party._id, inviter: user._id, name: party.name})') + //- + hr + p.alert.alert-info Or share this link (copy/paste): + input.form-control(type='text', ng-value='inviteLink({id: party._id, inviter: user._id, name: party.name})') .modal-footer button.btn.btn-default(ng-click='$close()') Close