passport-local-mongoose
passport-local-mongoose copied to clipboard
save() concurrency issue when using options.limitAttempts
Hello, While using your plugin and implementing a "delete my account" feature, I can ran into a Mongoose error "VersionError: No matching document found".
When a user wants to delete his account, my app opens a modal and asks for his password. If the password is matching (using passport-local-mongoose 'authenticate'), then I set "status: 'deleted'" on the User document and save it. I'm using options.limitAttempts, so passport-local-mongoose performs a first save beforehand to update lastLoginField and attemptsField, but does not use a callback. Therefore, If "my" second save comes too quickly after "yours", I get this mongoose version conflict.
Could you nest the callback of authenticate inside the call to self.save() ?
~line 105:
if (hash === self.get(options.hashField)) {
if (options.limitAttempts){
self.set(options.lastLoginField, Date.now());
self.set(options.attemptsField, 0);
self.save();
}
return cb(null, self);
} else {
…
}
=>
if (hash === self.get(options.hashField)) {
if (options.limitAttempts){
self.set(options.lastLoginField, Date.now());
self.set(options.attemptsField, 0);
self.save(cb);
} else {
return cb(null, self);
}
} else {
…
}
Ran into this same issue while trying to update the user record on successful login - the two saves overlap each other and I was getting duplicate entries (with the same ObjectId) in a subdocument. The code needs to reflect the async nature of .save() and only hit the callback when it returns.