passport-local-mongoose icon indicating copy to clipboard operation
passport-local-mongoose copied to clipboard

save() concurrency issue when using options.limitAttempts

Open anoirclere opened this issue 10 years ago • 1 comments

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 {
           …
        }

anoirclere avatar Oct 07 '14 14:10 anoirclere

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.

mvoorberg avatar Oct 18 '17 20:10 mvoorberg