diff --git a/src/controllers/auth.js b/src/controllers/auth.js
index b6a4d17f18..7ebf4bf7f2 100644
--- a/src/controllers/auth.js
+++ b/src/controllers/auth.js
@@ -41,10 +41,9 @@ api.auth = function(req, res, next) {
};
api.authWithSession = function(req, res, next) { //[todo] there is probably a more elegant way of doing this...
- var uid = req.session.userId;
if (!(req.session && req.session.userId))
return res.json(401, NO_SESSION_FOUND);
- User.findOne({_id: uid}, function(err, user) {
+ User.findOne({_id: req.session.userId}, function(err, user) {
if (err) return next(err);
if (_.isEmpty(user)) return res.json(401, NO_USER_FOUND);
res.locals.user = user;
@@ -62,33 +61,25 @@ api.authWithUrl = function(req, res, next) {
}
api.registerUser = function(req, res, next) {
- var confirmPassword, e, email, password, username, _ref;
- _ref = req.body, email = _ref.email, username = _ref.username, password = _ref.password, confirmPassword = _ref.confirmPassword;
- if (!(username && password && email)) {
- return res.json(401, {err: ":username, :email, :password, :confirmPassword required"});
- }
- if (password !== confirmPassword) {
- return res.json(401, {err: ":password and :confirmPassword don't match"});
- }
- if (!validator.isEmail(email)) {
- return res.json(401, {err: ":email invalid"});
- }
+ var confirmPassword = req.body.confirmPassword,
+ email = req.body.email,
+ password = req.body.password,
+ username = req.body.username;
+ if (!(username && password && email)) return res.json(401, {err: ":username, :email, :password, :confirmPassword required"});
+ if (password !== confirmPassword) return res.json(401, {err: ":password and :confirmPassword don't match"});
+ if (!validator.isEmail(email)) return res.json(401, {err: ":email invalid"});
async.waterfall([
function(cb) {
User.findOne({'auth.local.email': email}, cb);
},
function(found, cb) {
- if (found) {
- return cb("Email already taken");
- }
+ if (found) return cb("Email already taken");
User.findOne({'auth.local.username': username}, cb);
}, function(found, cb) {
var newUser, salt, user;
- if (found) {
- return cb("Username already taken");
- }
+ if (found) return cb("Username already taken");
salt = utils.makeSalt();
- var newUser = {
+ newUser = {
auth: {
local: {
username: username,
@@ -138,10 +129,9 @@ api.registerUser = function(req, res, next) {
ga.event('register', 'Local').send()
}
], function(err, saved) {
- if (err) {
- return res.json(401, {err: err});
- }
+ if (err) return res.json(401, {err: err});
res.json(200, saved);
+ email = password = username = null;
});
};
@@ -167,6 +157,7 @@ api.loginLocal = function(req, res, next) {
if (err) return next(err);
if (!user) return res.json(401,{err:"Username or password incorrect. Click 'Forgot Password' for help with either. (Note: usernames are case-sensitive)"});
res.json({id: user._id,token: user.apiToken});
+ password = null;
});
});
};
@@ -177,10 +168,8 @@ api.loginLocal = function(req, res, next) {
api.loginFacebook = function(req, res, next) {
- var email, facebook_id, name, _ref;
- _ref = req.body, facebook_id = _ref.facebook_id, email = _ref.email, name = _ref.name;
- if (!facebook_id)
- return res.json(401, {err: 'No facebook id provided'});
+ var facebook_id = req.body.facebook_id;
+ if (!facebook_id) return res.json(401, {err: 'No facebook id provided'});
User.findOne({'auth.facebook.id': facebook_id}, function(err, user) {
if (err) {
return res.json(401, {err: err});
@@ -215,31 +204,31 @@ api.resetPassword = function(req, res, next){
html: "Password for " + user.auth.local.username + " has been reset to " + newPassword + ". Log in at " + nconf.get('BASE_URL')
});
user.save();
- return res.send('New password sent to '+ email);
+ res.send('New password sent to '+ email);
+ email = salt = newPassword = hashed_password = null;
});
};
api.changeUsername = function(req, res, next) {
var user = res.locals.user,
- password = req.body.password
+ password = req.body.password,
newUsername = req.body.newUsername;
User.findOne({'auth.local.username': newUsername}, function(err, result) {
if (err) next(err);
+ if(result) return res.json(401, {err: "Username already taken"});
- if(result)
- return res.json(401, {err: "Username already taken"});
-
- var salt = user.auth.local.salt,
- hashed_password = utils.encryptPassword(password, salt);
+ var salt = user.auth.local.salt;
+ var hashed_password = utils.encryptPassword(password, salt);
if (hashed_password !== user.auth.local.hashed_password)
return res.json(401, {err:"Incorrect password"});
user.auth.local.username = newUsername;
user.save(function(err, saved){
- if (err) next(err);
- res.send(200);
+ if (err) next(err);
+ res.send(200);
+ user = password = newUsername = null;
})
});
}
diff --git a/src/controllers/challenges.js b/src/controllers/challenges.js
index ba692a0d1e..b5fe4d6982 100644
--- a/src/controllers/challenges.js
+++ b/src/controllers/challenges.js
@@ -38,9 +38,9 @@ api.list = function(req, res, next) {
})
.select('name leader description group memberCount prize official')
.select({members:{$elemMatch:{$in:[user._id]}}})
+ .sort('-official -timestamp')
.populate('group', '_id name')
.populate('leader', 'profile.name')
- .sort('-official -timestamp')
.exec(cb);
}
], function(err, challenges){
@@ -49,6 +49,7 @@ api.list = function(req, res, next) {
c._isMember = c.members.length > 0;
})
res.json(challenges);
+ user = null;
});
}
@@ -77,14 +78,13 @@ api.csv = function(req, res, next) {
function(_challenge,cb) {
challenge = _challenge;
if (!challenge) return cb('Challenge ' + cid + ' not found');
- User.aggregate([
- {$match:{'_id':{ '$in': challenge.members}}}, //yes, we want members
- {$project:{'profile.name':1,tasks:{$setUnion:["$habits","$dailys","$todos","$rewards"]}}},
- {$unwind:"$tasks"},
- {$match:{"tasks.challenge.id":cid}},
- {$sort:{'tasks.type':1,'tasks.id':1}},
- {$group:{_id:"$_id", "tasks":{$push:"$tasks"},"name":{$first:"$profile.name"}}}
-
+ User.aggregate([
+ {$match:{'_id':{ '$in': challenge.members}}}, //yes, we want members
+ {$project:{'profile.name':1,tasks:{$setUnion:["$habits","$dailys","$todos","$rewards"]}}},
+ {$unwind:"$tasks"},
+ {$match:{"tasks.challenge.id":cid}},
+ {$sort:{'tasks.type':1,'tasks.id':1}},
+ {$group:{_id:"$_id", "tasks":{$push:"$tasks"},"name":{$first:"$profile.name"}}}
], cb);
}
],function(err,users){
@@ -107,6 +107,7 @@ api.csv = function(req, res, next) {
});
res.header('Content-disposition', 'attachment; filename='+cid+'.csv');
res.csv(output);
+ challenge = cid = null;
})
}
@@ -137,8 +138,9 @@ api.getMember = function(req, res, next) {
.project(proj)
.exec(function(err, member){
if (err) return next(err);
- if (!member) return res.json(404, {err: 'Member '+uid+' for challenge '+cid+' not found'});
+ if (!member) return res.json(404, {err: 'Member '+uid+' for challenge '+cid+' not found'});
res.json(member[0]);
+ uid = cid = null;
});
}
@@ -181,7 +183,7 @@ api.create = function(req, res, next){
// User pays for all of prize
user.balance -= prizeCost;
}
- cb(null)
+ cb(null);
});
}
@@ -206,6 +208,7 @@ api.create = function(req, res, next){
async.waterfall(waterfall, function(err){
if (err) return next(err);
res.json(chal);
+ user = group = chal = null;
});
}
@@ -229,8 +232,6 @@ api.update = function(req, res, next){
Challenge.findByIdAndUpdate(cid, {$set:attrs}, cb);
},
function(saved, cb) {
- // after saving, we're done as far as the client's concerned. We kick of syncing (heavy task) in the background
- cb(null, saved);
// Compare whether any changes have been made to tasks. If so, we'll want to sync those changes to subscribers
if (before.isOutdated(req.body)) {
@@ -243,10 +244,13 @@ api.update = function(req, res, next){
})
}
+ // after saving, we're done as far as the client's concerned. We kick off syncing (heavy task) in the background
+ cb(null, saved);
}
], function(err, saved){
if(err) next(err);
res.json(saved);
+ cid = user = before = null;
})
}
@@ -284,6 +288,7 @@ function closeChal(cid, broken, cb) {
})
})
async.parallel(parallel, cb2);
+ removed = null;
}
], cb);
}
@@ -306,6 +311,7 @@ api['delete'] = function(req, res, next){
], function(err){
if (err) return next(err);
res.send(200);
+ user = cid = null;
});
}
@@ -340,6 +346,7 @@ api.selectWinner = function(req, res, next) {
], function(err){
if (err) return next(err);
res.send(200);
+ user = cid = chal = null;
})
}
@@ -369,6 +376,7 @@ api.join = function(req, res, next){
if(err) return next(err);
chal._isMember = true;
res.json(chal);
+ user = cid = null;
});
}
@@ -401,6 +409,7 @@ api.leave = function(req, res, next){
if(err) return next(err);
if (chal) chal._isMember = false;
res.json(chal);
+ user = cid = keep = null;
});
}
@@ -417,5 +426,6 @@ api.unlink = function(req, res, next) {
user.unlink({cid:cid, keep:req.query.keep, tid:tid}, function(err, saved){
if (err) return next(err);
res.send(200);
+ user = tid = cid = null;
});
}
diff --git a/src/controllers/coupon.js b/src/controllers/coupon.js
index 233be59078..b8450d34f3 100644
--- a/src/controllers/coupon.js
+++ b/src/controllers/coupon.js
@@ -5,8 +5,7 @@ var csv = require('express-csv');
var async = require('async');
api.ensureAdmin = function(req, res, next) {
- var user = res.locals.user;
- if (!user.contributor.sudo) return res.json(401, {err:"You don't have admin access"});
+ if (!res.locals.user.contributor.sudo) return res.json(401, {err:"You don't have admin access"});
next();
}
@@ -34,4 +33,4 @@ api.enterCode = function(req,res,next) {
if (err) return res.json(400,{err:err});
res.json(user);
});
-}
\ No newline at end of file
+}
diff --git a/src/controllers/dataexport.js b/src/controllers/dataexport.js
index 6e5f6703b2..48a08b1d38 100644
--- a/src/controllers/dataexport.js
+++ b/src/controllers/dataexport.js
@@ -39,8 +39,7 @@ var userdata = function(user) {
}
dataexport.leanuser = function(req, res, next) {
- var user = res.locals.user;
- User.findOne({_id: user._id,}).lean().exec(function(err, user) {
+ User.findOne({_id: res.locals.user._id}).lean().exec(function(err, user) {
if (err) return res.json(500, {err: err});
if (_.isEmpty(user)) return res.json(401, NO_USER_FOUND);
res.locals.user = user;
@@ -56,7 +55,7 @@ dataexport.userdata = {
json: function(req, res) {
var user = userdata(res.locals.user);
return res.jsonstring(user);
- },
+ }
}
/*
diff --git a/src/controllers/groups.js b/src/controllers/groups.js
index 02638f5432..cd7c768fad 100644
--- a/src/controllers/groups.js
+++ b/src/controllers/groups.js
@@ -117,6 +117,8 @@ api.list = function(req, res, next) {
return m.concat(_.isArray(v) ? v : [v]);
}, [])
res.json(arr);
+
+ user = groupFields = sort = type = null;
})
};
@@ -139,6 +141,7 @@ api.get = function(req, res, next) {
if (err) return next(err);
if (!group && gid!=='party') return res.json(404,{err: "Group not found or you don't have access."});
res.json(group);
+ gid = null;
});
};
@@ -162,6 +165,7 @@ api.create = function(req, res, next) {
],function(err,saved){
if (err) return next(err);
res.json(saved);
+ group = user = null;
});
}else{
@@ -180,6 +184,7 @@ api.create = function(req, res, next) {
if (err == 'Already in a party, try refreshing.') return res.json(400,{err:err});
if (err) return next(err);
return res.json(populated);
+ group = user = null;
})
}
}
@@ -236,6 +241,7 @@ api.postChat = function(req, res, next) {
group.save(function(err, saved){
if (err) return next(err);
return chatUpdated ? res.json({chat: group.chat}) : res.json({message: saved.chat[0]});
+ group = chatUpdated = null;
});
}
@@ -254,7 +260,8 @@ api.deleteChatMessage = function(req, res, next){
Group.update({_id:group._id}, {$pull:{chat:{id: req.params.messageId}}}, function(err){
if(err) return next(err);
- return chatUpdated ? res.json({chat: group.chat}) : res.send(204);
+ chatUpdated ? res.json({chat: group.chat}) : res.send(204);
+ group = chatUpdated = null;
});
}
@@ -324,6 +331,7 @@ api.join = function(req, res, next) {
// Return the group? Or not?
res.json(results[1]);
+ group = null;
});
}
@@ -400,13 +408,13 @@ api.leave = function(req, res, next) {
],function(err){
if (err) return next(err);
return res.send(204);
+ user = group = keep = null;
})
}
api.invite = function(req, res, next) {
var group = res.locals.group;
var uuid = req.query.uuid;
- var user = res.locals.user;
User.findById(uuid, function(err,invite){
if (err) return next(err);
@@ -454,6 +462,7 @@ api.invite = function(req, res, next) {
// Have to return whole group and its members for angular to show the invited user
res.json(results[2]);
+ group = uuid = null;
});
}
});
@@ -463,7 +472,7 @@ api.removeMember = function(req, res, next){
var group = res.locals.group;
var uuid = req.query.uuid;
var user = res.locals.user;
-
+
if(group.leader !== user._id){
return res.json(401, {err: "Only group leader can remove a member!"});
}
@@ -479,7 +488,7 @@ api.removeMember = function(req, res, next){
update['$inc'] = {memberCount: -1};
Group.update({_id:group._id},update, function(err, saved){
if (err) return next(err);
-
+
// Sending an empty 204 because Group.update doesn't return the group
// see http://mongoosejs.com/docs/api.html#model_Model.update
return res.send(204);
@@ -506,11 +515,13 @@ api.removeMember = function(req, res, next){
// Sending an empty 204 because Group.update doesn't return the group
// see http://mongoosejs.com/docs/api.html#model_Model.update
return res.send(204);
+ group = uuid = null;
});
});
}else{
return res.json(400, {err: "User not found among group's members!"});
+ group = uuid = null;
}
}
@@ -581,9 +592,10 @@ questStart = function(req, res, next) {
var lastIndex = results.length -1;
var groupClone = clone(group);
-
+
groupClone.members = results[lastIndex].members;
+ group = null;
return res.json(groupClone);
});
}
@@ -650,6 +662,7 @@ api.questCancel = function(req, res, next){
], function(err){
if (err) return next(err);
res.json(group);
+ group = null;
})
}
@@ -688,6 +701,6 @@ api.questAbort = function(req, res, next){
groupClone.members = results[2].members;
res.json(groupClone);
+ group = null;
})
}
-
diff --git a/src/controllers/payments.js b/src/controllers/payments.js
index f8ce5950a9..d117d02ca5 100644
--- a/src/controllers/payments.js
+++ b/src/controllers/payments.js
@@ -14,6 +14,7 @@ var request = require('request');
var moment = require('moment');
var api = module.exports;
var isProduction = nconf.get("NODE_ENV") === "production";
+var stripe = require("stripe")(nconf.get('STRIPE_API_KEY'));
var PaypalRecurring = require('paypal-recurring');
var paypalRecurring = new PaypalRecurring({
@@ -51,7 +52,7 @@ function getMailingInfo(user) {
}
function emailUser(user, emailType) {
- mailingInfo = getMailingInfo(user);
+ var mailingInfo = getMailingInfo(user);
if(mailingInfo.email){
request({
url: nconf.get('EMAIL_SERVER_URL') + '/job',
@@ -131,8 +132,6 @@ if (nconf.get('NODE_ENV')==='testing') {
Setup Stripe response when posting payment
*/
api.stripeCheckout = function(req, res, next) {
- var api_key = nconf.get('STRIPE_API_KEY');
- var stripe = require("stripe")(api_key);
var token = req.body.id;
var user = res.locals.user;
@@ -164,11 +163,11 @@ api.stripeCheckout = function(req, res, next) {
], function(err, saved){
if (err) return res.send(500, err.toString()); // don't json this, let toString() handle errors
res.send(200);
+ user = token = null;
});
};
api.stripeSubscribeCancel = function(req, res, next) {
- var stripe = require("stripe")(nconf.get('STRIPE_API_KEY'));
var user = res.locals.user;
if (!user.purchased.plan.customerId)
return res.json(401, {err: "User does not have a plan subscription"});
@@ -184,11 +183,11 @@ api.stripeSubscribeCancel = function(req, res, next) {
], function(err, saved){
if (err) return res.send(500, err.toString()); // don't json this, let toString() handle errors
res.redirect('/');
+ user = null;
});
};
api.stripeSubscribeEdit = function(req, res, next) {
- var stripe = require("stripe")(nconf.get('STRIPE_API_KEY'));
var token = req.body.id;
var user = res.locals.user;
var user_id = user.purchased.plan.customerId;
@@ -210,14 +209,14 @@ api.stripeSubscribeEdit = function(req, res, next) {
], function(err, saved){
if (err) return res.send(500, err.toString()); // don't json this, let toString() handle errors
res.send(200);
+ token = user = user_id = sub_id;
});
};
api.paypalSubscribe = function(req,res,next) {
- var uuid = res.locals.user._id;
// Authenticate a future subscription of ~5 USD
paypalRecurring.authenticate({
- RETURNURL: nconf.get('BASE_URL') + '/paypal/subscribe/success?uuid=' + uuid,
+ RETURNURL: nconf.get('BASE_URL') + '/paypal/subscribe/success?uuid=' + res.locals.user._id,
CANCELURL: nconf.get("BASE_URL"),
PAYMENTREQUEST_0_AMT: 5,
L_BILLINGAGREEMENTDESCRIPTION0: "HabitRPG Subscription"
@@ -265,12 +264,12 @@ api.paypalSubscribeCancel = function(req, res, next) {
], function(err, saved){
if (err) return next(err);
res.redirect('/');
+ user = null;
});
};
api.paypalCheckout = function(req, res, next) {
- var uuid = res.locals.user._id;
- var opts = {RETURNURL:nconf.get('BASE_URL') + '/paypal/checkout/success?uuid=' + uuid};
+ var opts = {RETURNURL:nconf.get('BASE_URL') + '/paypal/checkout/success?uuid=' + res.locals.user._id};
paypalCheckout.pay(+new Date(), 5, 'HabitRPG Gems', 'USD', opts, function(err, url) {
if (err) return next(err);
res.redirect(url);
@@ -292,6 +291,7 @@ api.paypalCheckoutSuccess = function(req,res,next) {
user.save(function(){
if (err) return next(err);
res.redirect('/');
+ uuid = null;
});
});
});
diff --git a/src/controllers/user.js b/src/controllers/user.js
index 3fa1cc2528..fe610e4f9a 100644
--- a/src/controllers/user.js
+++ b/src/controllers/user.js
@@ -68,6 +68,8 @@ api.score = function(req, res, next) {
user = res.locals.user,
task;
+ var clearMemory = function(){user = task = id = direction = null;}
+
// Send error responses for improper API call
if (!id) return res.json(400, {err: ':id required'});
if (direction !== 'up' && direction !== 'down') {
@@ -104,22 +106,28 @@ api.score = function(req, res, next) {
_tmp: user._tmp
}, saved.toJSON().stats));
- // If it's a challenge task, sync the score. Do it in the background, we've already sent down a response
- // and the user doesn't care what happens back there
- if (!task.challenge || !task.challenge.id || task.challenge.broken) return;
- if (task.type == 'reward') return; // we don't want to update the reward GP cost
+ if (
+ (!task.challenge || !task.challenge.id || task.challenge.broken) // If it's a challenge task, sync the score. Do it in the background, we've already sent down a response and the user doesn't care what happens back there
+ || (task.type == 'reward') // we don't want to update the reward GP cost
+ ) return clearMemory();
Challenge.findById(task.challenge.id, 'habits dailys todos rewards', function(err, chal){
if (err) return next(err);
if (!chal) {
task.challenge.broken = 'CHALLENGE_DELETED';
- return user.save();
+ user.save();
+ return clearMemory();
}
var t = chal.tasks[task.id];
- if (!t) return chal.syncToUser(user); // this task was removed from the challenge, notify user
+ // this task was removed from the challenge, notify user
+ if (!t) {
+ chal.syncToUser(user);
+ return clearMemory();
+ }
t.value += delta;
if (t.type == 'habit' || t.type == 'daily')
t.history.push({value: t.value, date: +new Date});
chal.save();
+ clearMemory();
});
});
};
@@ -164,7 +172,6 @@ api.getTask = function(req, res, next) {
api.getBuyList = function (req, res, next) {
var list = shared.updateStore(res.locals.user);
-
return res.json(200, list);
};
@@ -231,6 +238,7 @@ api.update = function(req, res, next) {
if (!_.isEmpty(errors)) return res.json(401, {err: errors});
if (err) return next(err);
res.json(200, user);
+ user = errors = null;
});
};
@@ -262,8 +270,9 @@ api.cron = function(req, res, next) {
User.findById(user._id, cb);
}
], function(err, saved) {
- user = res.locals.user = saved;
+ res.locals.user = saved;
next(err,saved);
+ user = progress = quest = null;
});
};
@@ -314,11 +323,12 @@ api.addTenGems = function(req, res, next) {
------------------------------------------------------------------------
*/
api.cast = function(req, res, next) {
- var user = res.locals.user;
- var targetType = req.query.targetType;
- var targetId = req.query.targetId;
- var klass = shared.content.spells.special[req.params.spell] ? 'special' : user.stats.class
- var spell = shared.content.spells[klass][req.params.spell];
+ var user = res.locals.user,
+ targetType = req.query.targetType,
+ targetId = req.query.targetId,
+ klass = shared.content.spells.special[req.params.spell] ? 'special' : user.stats.class,
+ spell = shared.content.spells[klass][req.params.spell];
+
if (!spell) return res.json(404, {err: 'Spell "' + req.params.spell + '" not found.'});
if (spell.mana > user.stats.mp) return res.json(400, {err: 'Not enough mana to cast spell'});
@@ -327,6 +337,7 @@ api.cast = function(req, res, next) {
var saved = _.size(arguments == 3) ? arguments[2] : arguments[1];
if (err) return next(err);
res.json(saved);
+ user = targetType = targetId = klass = spell = null;
}
switch (targetType) {
@@ -370,6 +381,8 @@ api.cast = function(req, res, next) {
})
}
+ series.push(function(cb2){g = group = series = found = null;cb2();})
+
async.series(series, cb);
},
function(whatever, cb){
diff --git a/src/models/coupon.js b/src/models/coupon.js
index 692cb91be9..fb99f6f4c0 100644
--- a/src/models/coupon.js
+++ b/src/models/coupon.js
@@ -49,6 +49,7 @@ CouponSchema.statics.apply = function(user, code, next){
], function(err){
if (err) return next(err);
next(null,_user);
+ _coupon = _user = null;
})
}
diff --git a/src/models/group.js b/src/models/group.js
index 51a6044b7f..2f8f6674b9 100644
--- a/src/models/group.js
+++ b/src/models/group.js
@@ -281,6 +281,7 @@ GroupSchema.statics.tavernBoss = function(user,progress) {
],function(err,res){
if (err === true) return; // no current quest
if (err) return logging.error(err);
+ dmg = rage = null;
})
}