EDIT: This question was asked earlier, but I didn't do a good job of asking it. I've rewritten the question. Thanks in advance for your help!
I'm in the process of writing a simple messaging server for a school project. Among its other functionalities, the server allows the user to update the information stored in their account. When the user does update their account, an authentication token is generated for them. Here's the schema that defines all of that. Note, header and body are parts of the user input:
UserSchema = new Schema({ _id: {type: ObjectId, select: false}, username: {type: String, required: true, index: {unique: true} }, password: {type: String, required: true, select: false}, email: {type: String}, token: {type: String, select: false} }, { autoIndex: false }); UserSchema.pre("save", function(next) { // Create a new token for the user var self = this; bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) { if (err) { next(err); } else { crypto.randomBytes(256, function(err, bytes) { if (err) { next(err); } else { bytes = bytes.toString("hex"); bcrypt.hash((new Date() + bytes), salt, function(err, tokenHash) { if (err) { next(err); } else { self.token = tokenHash; next(); } }); } }); } }); }); UserSchema.pre("save", function(next) { // Hash the password before saving var self = this; if (!self.isModified("password")) { next(); } else { bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) { if (err) { next(err); } else { bcrypt.hash(self.password, salt, function(err, passwordHash) { if (err) { next(err); } else { self.password = passwordHash; next(); } }); } }); } }); I'm running into an issue when updating a particular user. Because I want to use the Model middleware, the way I'm updating a user is by using Model#findOne() followed by Model#save(). Here's the code I have to do that:
// Make sure user provided all necessary information. if (!header.token) { return callback(new errors.MissingHeaderDataError("Missing 'token' parameter in the header.")); } else { // Update the user account based on what's in the envelope's body. User.findOne({"token": header.token}, "+token +password", function (err, user) { if (err) { return callback(err); } else { // Get a list of all parameters the user wants to change. var paramsToChange = Object.keys(body); // Now update the parameters paramsToChange.forEach(function(param) { user[param] = body[param]; }); console.log("Updated user:"); console.dir(user); user.save(function(err, user) { if (err) { return callback(err); } else { console.log("Returned user:"); console.dir(user); User.find({}, "+token +password", function(err, foundUser) { if (err) { throw err; } else { console.log(JSON.stringify(foundUser)); } }); callback(null, new SuccessEnvelope(user)); } }); } }); } When I run my tests and come to the last bit of code (after save() is returned), I get this output:
Updated user: { token: '$2a$10$5VWWqjJ52aGbS4xc6NDKjuGPv8brX7pRmwiKyYjP8VHoTKCtYZiTu', username: 'jim_bob', password: '$2a$10$ue08HUsunzzzcbZURzXF7uaH1dZxF3SwkwadC6D1JsIC9xAUhTbCC', email: '[email protected]', __v: 0 } Returned user: { token: '$2a$10$fRwED..7fFFhN46Vn.ZJW..xYql5t5P39LHddjFS4kl/pmhwfT.tO', username: 'jim_bob', password: '$2a$10$ue08HUsunzzzcbZURzXF7uaH1dZxF3SwkwadC6D1JsIC9xAUhTbCC', email: '[email protected]', __v: 0 } [{"token":"$2a$10$5VWWqjJ52aGbS4xc6NDKjuGPv8brX7pRmwiKyYjP8VHoTKCtYZiTu","username":"joe_bob","password":"$2a$10$ue08HUsunzzzcbZURzXF7uaH1dZ xF3SwkwadC6D1JsIC9xAUhTbCC","email":"[email protected]","__v":0}] As you can see, the document is not properly saved to the database, as the previous data is still there. My question is: why? Why is the user not being updated when calling save? I think I'm doing everything properly, but obviously I'm not. Any help with this would be great since I'm going mad!