mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
Fixes asynchronous cron bug that allows cron to run twice for a user within seconds. (#10142)
* Fixes asynchronous cron bug that allows cron to run twice for a user within seconds of eachother. fixes #8991 * Fixing tests. * Updating assignment to keep user and res.locals.user in sync.
This commit is contained in:
@@ -166,8 +166,11 @@ describe('cron middleware', () => {
|
|||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
cronMiddleware(req, res, (err) => {
|
cronMiddleware(req, res, (err) => {
|
||||||
if (err) return reject(err);
|
if (err) return reject(err);
|
||||||
expect(user.stats.hp).to.be.lessThan(hpBefore);
|
User.findOne({_id: user._id}, function (secondErr, updatedUser) {
|
||||||
resolve();
|
if (secondErr) return reject(secondErr);
|
||||||
|
expect(updatedUser.stats.hp).to.be.lessThan(hpBefore);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -217,8 +220,11 @@ describe('cron middleware', () => {
|
|||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
cronMiddleware(req, res, (err) => {
|
cronMiddleware(req, res, (err) => {
|
||||||
if (err) return reject(err);
|
if (err) return reject(err);
|
||||||
expect(user.stats.hp).to.be.lessThan(hpBefore);
|
User.findOne({_id: user._id}, function (secondErr, updatedUser) {
|
||||||
resolve();
|
if (secondErr) return reject(secondErr);
|
||||||
|
expect(updatedUser.stats.hp).to.be.lessThan(hpBefore);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ async function checkForActiveCron (user, now) {
|
|||||||
}, {
|
}, {
|
||||||
$set: {
|
$set: {
|
||||||
_cronSignature,
|
_cronSignature,
|
||||||
lastCron: now, // setting lastCron now so we don't risk re-running parts of cron if it fails
|
|
||||||
'auth.timestamps.loggedin': now,
|
'auth.timestamps.loggedin': now,
|
||||||
},
|
},
|
||||||
}).exec();
|
}).exec();
|
||||||
@@ -35,6 +34,14 @@ async function checkForActiveCron (user, now) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateLastCron (user, now) {
|
||||||
|
await User.update({
|
||||||
|
_id: user._id,
|
||||||
|
}, {
|
||||||
|
lastCron: now, // setting lastCron now so we don't risk re-running parts of cron if it fails
|
||||||
|
}).exec();
|
||||||
|
}
|
||||||
|
|
||||||
async function unlockUser (user) {
|
async function unlockUser (user) {
|
||||||
await User.update({
|
await User.update({
|
||||||
_id: user._id,
|
_id: user._id,
|
||||||
@@ -51,9 +58,12 @@ async function cronAsync (req, res) {
|
|||||||
let now = new Date();
|
let now = new Date();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await checkForActiveCron(user, now);
|
||||||
|
|
||||||
|
user = res.locals.user = await User.findOne({_id: user._id}).exec();
|
||||||
let {daysMissed, timezoneOffsetFromUserPrefs} = user.daysUserHasMissed(now, req);
|
let {daysMissed, timezoneOffsetFromUserPrefs} = user.daysUserHasMissed(now, req);
|
||||||
|
|
||||||
await checkForActiveCron(user, now);
|
await updateLastCron(user, now);
|
||||||
|
|
||||||
if (daysMissed <= 0) {
|
if (daysMissed <= 0) {
|
||||||
if (user.isModified()) await user.save();
|
if (user.isModified()) await user.save();
|
||||||
|
|||||||
Reference in New Issue
Block a user