mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-15 21:57:22 +01:00
Always use .exec() for .find*() and .update() (#8361)
* add exec where missing in /models * ix taskManager query * fix top-level controllers * fix api-v3 controllers
This commit is contained in:
@@ -525,7 +525,7 @@ api.resetPassword = {
|
||||
let newPassword = passwordUtils.makeSalt(); // use a salt as the new password too (they'll change it later)
|
||||
let hashedPassword = passwordUtils.encrypt(newPassword, salt);
|
||||
|
||||
let user = await User.findOne({ 'auth.local.email': email });
|
||||
let user = await User.findOne({ 'auth.local.email': email }).exec();
|
||||
|
||||
if (user) {
|
||||
user.auth.local.salt = salt;
|
||||
@@ -578,7 +578,10 @@ api.updateEmail = {
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
let emailAlreadyInUse = await User.findOne({'auth.local.email': req.body.newEmail}).select({_id: 1}).lean().exec();
|
||||
let emailAlreadyInUse = await User.findOne({
|
||||
'auth.local.email': req.body.newEmail,
|
||||
}).select({_id: 1}).lean().exec();
|
||||
|
||||
if (emailAlreadyInUse) throw new NotAuthorized(res.t('cannotFulfillReq'));
|
||||
|
||||
let candidatePassword = passwordUtils.encrypt(req.body.password, user.auth.local.salt);
|
||||
|
||||
@@ -138,7 +138,7 @@ api.joinChallenge = {
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
let challenge = await Challenge.findOne({ _id: req.params.challengeId });
|
||||
let challenge = await Challenge.findOne({ _id: req.params.challengeId }).exec();
|
||||
if (!challenge) throw new NotFound(res.t('challengeNotFound'));
|
||||
if (challenge.isMember(user)) throw new NotAuthorized(res.t('userAlreadyInChallenge'));
|
||||
|
||||
@@ -187,7 +187,7 @@ api.leaveChallenge = {
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
let challenge = await Challenge.findOne({ _id: req.params.challengeId });
|
||||
let challenge = await Challenge.findOne({ _id: req.params.challengeId }).exec();
|
||||
if (!challenge) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
let group = await Group.getGroup({user, groupId: challenge.group, fields: '_id type privacy'});
|
||||
@@ -282,9 +282,13 @@ api.getGroupChallenges = {
|
||||
let resChals = challenges.map(challenge => challenge.toJSON());
|
||||
// Instead of populate we make a find call manually because of https://github.com/Automattic/mongoose/issues/3833
|
||||
await Bluebird.all(resChals.map((chal, index) => {
|
||||
return User.findById(chal.leader).select(nameFields).exec().then(populatedLeader => {
|
||||
resChals[index].leader = populatedLeader ? populatedLeader.toJSON({minimize: true}) : null;
|
||||
});
|
||||
return User
|
||||
.findById(chal.leader)
|
||||
.select(nameFields)
|
||||
.exec()
|
||||
.then(populatedLeader => {
|
||||
resChals[index].leader = populatedLeader ? populatedLeader.toJSON({minimize: true}) : null;
|
||||
});
|
||||
}));
|
||||
|
||||
res.respond(200, resChals);
|
||||
@@ -315,10 +319,10 @@ api.getChallenge = {
|
||||
let user = res.locals.user;
|
||||
let challengeId = req.params.challengeId;
|
||||
|
||||
let challenge = await Challenge.findById(challengeId)
|
||||
// Don't populate the group as we'll fetch it manually later
|
||||
// .populate('leader', nameFields)
|
||||
.exec();
|
||||
// Don't populate the group as we'll fetch it manually later
|
||||
// .populate('leader', nameFields)
|
||||
let challenge = await Challenge.findById(challengeId).exec();
|
||||
|
||||
if (!challenge) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
// Fetching basic group data
|
||||
@@ -374,8 +378,12 @@ api.exportChallengeCsv = {
|
||||
.lean() // so we don't involve mongoose
|
||||
.exec(),
|
||||
|
||||
Tasks.Task.find({'challenge.id': challengeId, userId: {$exists: true}})
|
||||
.sort({userId: 1, text: 1}).select('userId type text value notes').lean().exec(),
|
||||
Tasks.Task.find({
|
||||
'challenge.id': challengeId,
|
||||
userId: {$exists: true},
|
||||
}).sort({userId: 1, text: 1})
|
||||
.select('userId type text value notes')
|
||||
.lean().exec(),
|
||||
]);
|
||||
|
||||
let resArray = members.map(member => [member._id, member.profile.name]);
|
||||
|
||||
@@ -31,7 +31,7 @@ async function getAuthorEmailFromMessage (message) {
|
||||
return 'system';
|
||||
}
|
||||
|
||||
let author = await User.findOne({_id: authorId}, {auth: 1});
|
||||
let author = await User.findOne({_id: authorId}, {auth: 1}).exec();
|
||||
|
||||
if (author) {
|
||||
return getUserInfo(author, ['email']).email;
|
||||
@@ -182,7 +182,7 @@ api.likeChat = {
|
||||
await Group.update(
|
||||
{_id: group._id, 'chat.id': message.id},
|
||||
update
|
||||
);
|
||||
).exec();
|
||||
res.respond(200, message); // TODO what if the message is flagged and shouldn't be returned?
|
||||
},
|
||||
};
|
||||
@@ -257,7 +257,7 @@ api.flagChat = {
|
||||
await Group.update(
|
||||
{_id: group._id, 'chat.id': message.id},
|
||||
update
|
||||
);
|
||||
).exec();
|
||||
|
||||
let reporterEmailContent = getUserInfo(user, ['email']).email;
|
||||
let authorEmail = await getAuthorEmailFromMessage(message);
|
||||
@@ -344,7 +344,7 @@ api.clearChatFlags = {
|
||||
await Group.update(
|
||||
{_id: group._id, 'chat.id': message.id},
|
||||
{$set: {'chat.$.flagCount': message.flagCount}}
|
||||
);
|
||||
).exec();
|
||||
|
||||
let adminEmailContent = getUserInfo(user, ['email']).email;
|
||||
let authorEmail = getAuthorEmailFromMessage(message);
|
||||
@@ -454,7 +454,7 @@ api.deleteChat = {
|
||||
await Group.update(
|
||||
{_id: group._id},
|
||||
{$pull: {chat: {id: chatId}}}
|
||||
);
|
||||
).exec();
|
||||
|
||||
if (chatUpdated) {
|
||||
let chatRes = Group.toJSONCleanChat(group, user).chat;
|
||||
|
||||
@@ -308,7 +308,8 @@ api.updateGroup = {
|
||||
let response = Group.toJSONCleanChat(savedGroup, user);
|
||||
// If the leader changed fetch new data, otherwise use authenticated user
|
||||
if (response.leader !== user._id) {
|
||||
response.leader = (await User.findById(response.leader).select(nameFields).exec()).toJSON({minimize: true});
|
||||
let rawLeader = await User.findById(response.leader).select(nameFields).exec();
|
||||
response.leader = rawLeader.toJSON({minimize: true});
|
||||
} else {
|
||||
response.leader = {
|
||||
_id: user._id,
|
||||
@@ -423,10 +424,16 @@ api.joinGroup = {
|
||||
|
||||
if (group.type === 'party' && inviter) {
|
||||
if (group.memberCount > 1) {
|
||||
promises.push(User.update({$or: [{'party._id': group._id}, {_id: user._id}], 'achievements.partyUp': {$ne: true}}, {$set: {'achievements.partyUp': true}}, {multi: true}).exec());
|
||||
promises.push(User.update({
|
||||
$or: [{'party._id': group._id}, {_id: user._id}],
|
||||
'achievements.partyUp': {$ne: true},
|
||||
}, {$set: {'achievements.partyUp': true}}, {multi: true}).exec());
|
||||
}
|
||||
if (group.memberCount > 3) {
|
||||
promises.push(User.update({$or: [{'party._id': group._id}, {_id: user._id}], 'achievements.partyOn': {$ne: true}}, {$set: {'achievements.partyOn': true}}, {multi: true}).exec());
|
||||
promises.push(User.update({
|
||||
$or: [{'party._id': group._id}, {_id: user._id}],
|
||||
'achievements.partyOn': {$ne: true},
|
||||
}, {$set: {'achievements.partyOn': true}}, {multi: true}).exec());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,8 @@ api.inviteToQuest = {
|
||||
let members = await User.find({
|
||||
'party._id': group._id,
|
||||
_id: {$ne: user._id},
|
||||
}).select('auth.facebook auth.local preferences.emailNotifications profile.name pushDevices')
|
||||
})
|
||||
.select('auth.facebook auth.local preferences.emailNotifications profile.name pushDevices')
|
||||
.exec();
|
||||
|
||||
group.markModified('quest');
|
||||
@@ -376,7 +377,7 @@ api.cancelQuest = {
|
||||
{'party._id': groupId},
|
||||
{$set: {'party.quest': Group.cleanQuestProgress()}},
|
||||
{multi: true}
|
||||
),
|
||||
).exec(),
|
||||
]);
|
||||
|
||||
res.respond(200, savedGroup.quest);
|
||||
|
||||
@@ -157,9 +157,17 @@ api.getChallengeTasks = {
|
||||
let user = res.locals.user;
|
||||
let challengeId = req.params.challengeId;
|
||||
|
||||
let challenge = await Challenge.findOne({_id: challengeId}).select('group leader tasksOrder').exec();
|
||||
let challenge = await Challenge.findOne({
|
||||
_id: challengeId,
|
||||
}).select('group leader tasksOrder').exec();
|
||||
if (!challenge) throw new NotFound(res.t('challengeNotFound'));
|
||||
let group = await Group.getGroup({user, groupId: challenge.group, fields: '_id type privacy', optionalMembership: true});
|
||||
|
||||
let group = await Group.getGroup({
|
||||
user,
|
||||
groupId: challenge.group,
|
||||
fields: '_id type privacy',
|
||||
optionalMembership: true,
|
||||
});
|
||||
if (!group || !challenge.canView(user, group)) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
let tasks = await getTasks(req, res, {user, challenge});
|
||||
@@ -339,7 +347,8 @@ api.scoreTask = {
|
||||
task.group.approval.requestedDate = new Date();
|
||||
|
||||
let group = await Group.getGroup({user, groupId: task.group.id, fields: requiredGroupFields});
|
||||
let groupLeader = await User.findById(group.leader); // Use this method so we can get access to notifications
|
||||
let groupLeader = await User.findById(group.leader).exec(); // Use this method so we can get access to notifications
|
||||
|
||||
groupLeader.addNotification('GROUP_TASK_APPROVAL', {
|
||||
message: res.t('userHasRequestedTaskApproval', {
|
||||
user: user.profile.name,
|
||||
|
||||
@@ -104,7 +104,7 @@ api.assignTask = {
|
||||
|
||||
let user = res.locals.user;
|
||||
let assignedUserId = req.params.assignedUserId;
|
||||
let assignedUser = await User.findById(assignedUserId);
|
||||
let assignedUser = await User.findById(assignedUserId).exec();
|
||||
|
||||
let taskId = req.params.taskId;
|
||||
let task = await Tasks.Task.findByIdOrAlias(taskId, user._id);
|
||||
@@ -162,7 +162,7 @@ api.unassignTask = {
|
||||
|
||||
let user = res.locals.user;
|
||||
let assignedUserId = req.params.assignedUserId;
|
||||
let assignedUser = await User.findById(assignedUserId);
|
||||
let assignedUser = await User.findById(assignedUserId).exec();
|
||||
|
||||
let taskId = req.params.taskId;
|
||||
let task = await Tasks.Task.findByIdOrAlias(taskId, user._id);
|
||||
@@ -211,13 +211,13 @@ api.approveTask = {
|
||||
|
||||
let user = res.locals.user;
|
||||
let assignedUserId = req.params.userId;
|
||||
let assignedUser = await User.findById(assignedUserId);
|
||||
let assignedUser = await User.findById(assignedUserId).exec();
|
||||
|
||||
let taskId = req.params.taskId;
|
||||
let task = await Tasks.Task.findOne({
|
||||
'group.taskId': taskId,
|
||||
userId: assignedUserId,
|
||||
});
|
||||
}).exec();
|
||||
|
||||
if (!task) {
|
||||
throw new NotFound(res.t('taskNotFound'));
|
||||
|
||||
@@ -39,15 +39,16 @@ api.unsubscribe = {
|
||||
let userUpdated = await User.update(
|
||||
{_id: data._id},
|
||||
{ $set: {'preferences.emailNotifications.unsubscribeFromAll': true}}
|
||||
);
|
||||
).exec();
|
||||
|
||||
if (userUpdated.nModified !== 1) throw new NotFound(res.t('userNotFound'));
|
||||
|
||||
res.send(`<h1>${res.t('unsubscribedSuccessfully')}</h1> ${res.t('unsubscribedTextUsers')}`);
|
||||
} else {
|
||||
let unsubscribedEmail = await EmailUnsubscription.findOne({email: data.email.toLowerCase()});
|
||||
let okResponse = `<h1>${res.t('unsubscribedSuccessfully')}</h1> ${res.t('unsubscribedTextOthers')}`;
|
||||
let unsubscribedEmail = await EmailUnsubscription.findOne({email: data.email.toLowerCase()}).exec();
|
||||
if (!unsubscribedEmail) await EmailUnsubscription.create({email: data.email.toLowerCase()});
|
||||
|
||||
let okResponse = `<h1>${res.t('unsubscribedSuccessfully')}</h1> ${res.t('unsubscribedTextOthers')}`;
|
||||
res.send(okResponse);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -144,7 +144,7 @@ api.checkout = {
|
||||
|
||||
if (gift) {
|
||||
if (gift.type === 'subscription') method = 'createSubscription';
|
||||
gift.member = await User.findById(gift ? gift.uuid : undefined);
|
||||
gift.member = await User.findById(gift ? gift.uuid : undefined).exec();
|
||||
data.gift = gift;
|
||||
data.paymentMethod = 'Amazon Payments (Gift)';
|
||||
}
|
||||
@@ -184,7 +184,7 @@ api.subscribe = {
|
||||
|
||||
if (sub.discount) { // apply discount
|
||||
if (!coupon) throw new BadRequest(res.t('couponCodeRequired'));
|
||||
let result = await Coupon.findOne({_id: cc.validate(coupon), event: sub.key});
|
||||
let result = await Coupon.findOne({_id: cc.validate(coupon), event: sub.key}).exec();
|
||||
if (!result) throw new NotAuthorized(res.t('invalidCoupon'));
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ api.checkoutSuccess = {
|
||||
delete req.session.gift;
|
||||
|
||||
if (gift) {
|
||||
gift.member = await User.findById(gift.uuid);
|
||||
gift.member = await User.findById(gift.uuid).exec();
|
||||
if (gift.type === 'subscription') {
|
||||
method = 'createSubscription';
|
||||
}
|
||||
@@ -168,7 +168,7 @@ api.subscribe = {
|
||||
|
||||
if (sub.discount) {
|
||||
if (!req.query.coupon) throw new BadRequest(res.t('couponCodeRequired'));
|
||||
let coupon = await Coupon.findOne({_id: cc.validate(req.query.coupon), event: sub.key});
|
||||
let coupon = await Coupon.findOne({_id: cc.validate(req.query.coupon), event: sub.key}).exec();
|
||||
if (!coupon) throw new NotAuthorized(res.t('invalidCoupon'));
|
||||
}
|
||||
|
||||
@@ -295,14 +295,18 @@ api.ipn = {
|
||||
await ipnVerifyAsync(req.body);
|
||||
|
||||
if (req.body.txn_type === 'recurring_payment_profile_cancel' || req.body.txn_type === 'subscr_cancel') {
|
||||
let user = await User.findOne({ 'purchased.plan.customerId': req.body.recurring_payment_id });
|
||||
let user = await User.findOne({ 'purchased.plan.customerId': req.body.recurring_payment_id }).exec();
|
||||
if (user) {
|
||||
await payments.cancelSubscription({ user, paymentMethod: 'Paypal' });
|
||||
return;
|
||||
}
|
||||
|
||||
let groupFields = basicGroupFields.concat(' purchased');
|
||||
let group = await Group.findOne({ 'purchased.plan.customerId': req.body.recurring_payment_id }).select(groupFields).exec();
|
||||
let group = await Group
|
||||
.findOne({ 'purchased.plan.customerId': req.body.recurring_payment_id })
|
||||
.select(groupFields)
|
||||
.exec();
|
||||
|
||||
if (group) {
|
||||
await payments.cancelSubscription({ groupId: group._id, paymentMethod: 'Paypal' });
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ api.checkout = {
|
||||
if (sub) {
|
||||
if (sub.discount) {
|
||||
if (!req.query.coupon) throw new BadRequest(res.t('couponCodeRequired'));
|
||||
coupon = await Coupon.findOne({_id: cc.validate(req.query.coupon), event: sub.key});
|
||||
coupon = await Coupon.findOne({_id: cc.validate(req.query.coupon), event: sub.key}).exec();
|
||||
if (!coupon) throw new BadRequest(res.t('invalidCoupon'));
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ api.checkout = {
|
||||
};
|
||||
|
||||
if (gift) {
|
||||
let member = await User.findById(gift.uuid);
|
||||
let member = await User.findById(gift.uuid).exec();
|
||||
gift.member = member;
|
||||
if (gift.type === 'subscription') method = 'createSubscription';
|
||||
data.paymentMethod = 'Stripe (Gift)';
|
||||
|
||||
@@ -107,6 +107,8 @@ export async function getTasks (req, res, options = {}) {
|
||||
} = options;
|
||||
|
||||
let query = {userId: user._id};
|
||||
let limit;
|
||||
let sort;
|
||||
let owner = group || challenge || user;
|
||||
|
||||
if (challenge) {
|
||||
@@ -122,18 +124,21 @@ export async function getTasks (req, res, options = {}) {
|
||||
query.completed = false; // Exclude completed todos
|
||||
query.type = 'todo';
|
||||
} else if (type === 'completedTodos' || type === '_allCompletedTodos') { // _allCompletedTodos is currently in BETA and is likely to be removed in future
|
||||
let limit = 30;
|
||||
limit = 30;
|
||||
|
||||
if (type === '_allCompletedTodos') {
|
||||
limit = 0; // no limit
|
||||
}
|
||||
query = Tasks.Task.find({
|
||||
|
||||
query = {
|
||||
userId: user._id,
|
||||
type: 'todo',
|
||||
completed: true,
|
||||
}).limit(limit).sort({
|
||||
};
|
||||
|
||||
sort = {
|
||||
dateCompleted: -1,
|
||||
});
|
||||
};
|
||||
} else {
|
||||
query.type = type.slice(0, -1); // removing the final "s"
|
||||
}
|
||||
@@ -144,7 +149,11 @@ export async function getTasks (req, res, options = {}) {
|
||||
];
|
||||
}
|
||||
|
||||
let tasks = await Tasks.Task.find(query).exec();
|
||||
let mQuery = Tasks.Task.find(query);
|
||||
if (limit) mQuery.limit(limit);
|
||||
if (sort) mQuery.sort(sort);
|
||||
|
||||
let tasks = await mQuery.exec();
|
||||
|
||||
// Order tasks based on tasksOrder
|
||||
if (type && type !== 'completedTodos' && type !== '_allCompletedTodos') {
|
||||
|
||||
@@ -461,7 +461,7 @@ schema.methods.startQuest = async function startQuest (user) {
|
||||
let partyId = this._id;
|
||||
let questMembers = this.quest.members;
|
||||
await Bluebird.map(Object.keys(this.quest.members), async (memberId) => {
|
||||
let member = await User.findOne({_id: memberId, 'party._id': partyId}).select('_id').lean();
|
||||
let member = await User.findOne({_id: memberId, 'party._id': partyId}).select('_id').lean().exec();
|
||||
|
||||
if (!member) {
|
||||
delete questMembers[memberId];
|
||||
@@ -553,7 +553,7 @@ schema.methods.sendGroupChatReceivedWebhooks = function sendGroupChatReceivedWeb
|
||||
query.guilds = this._id;
|
||||
}
|
||||
|
||||
User.find(query).select({webhooks: 1}).lean().then((users) => {
|
||||
User.find(query).select({webhooks: 1}).lean().exec().then((users) => {
|
||||
users.forEach((user) => {
|
||||
let { webhooks } = user;
|
||||
groupChatReceivedWebhook.send(webhooks, {
|
||||
@@ -797,7 +797,7 @@ schema.statics.processQuestProgress = async function processQuestProgress (user,
|
||||
});
|
||||
};
|
||||
|
||||
// to set a boss: `db.groups.update({_id:TAVERN_ID},{$set:{quest:{key:'dilatory',active:true,progress:{hp:1000,rage:1500}}}})`
|
||||
// to set a boss: `db.groups.update({_id:TAVERN_ID},{$set:{quest:{key:'dilatory',active:true,progress:{hp:1000,rage:1500}}}}).exec()`
|
||||
// we export an empty object that is then populated with the query-returned data
|
||||
export let tavernQuest = {};
|
||||
let tavernQ = {_id: TAVERN_ID, 'quest.key': {$ne: null}};
|
||||
@@ -891,7 +891,7 @@ schema.methods.leave = async function leaveGroup (user, keep = 'keep-all') {
|
||||
let challenges = await Challenge.find({
|
||||
_id: {$in: user.challenges},
|
||||
group: group._id,
|
||||
});
|
||||
}).exec();
|
||||
|
||||
let challengesToRemoveUserFrom = challenges.map(chal => {
|
||||
return chal.unlinkTasks(user, keep);
|
||||
@@ -903,7 +903,7 @@ schema.methods.leave = async function leaveGroup (user, keep = 'keep-all') {
|
||||
'group.id': group._id,
|
||||
userId: {$exists: false},
|
||||
'group.assignedUsers': user._id,
|
||||
});
|
||||
}).exec();
|
||||
let assignedTasksToRemoveUserFrom = assignedTasks.map(task => {
|
||||
return this.unlinkTask(task, user, keep);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user