4

编辑:这个问题之前被问过,但我没有很好地提出这个问题。我已经重写了这个问题。在此先感谢您的帮助!

我正在为一个学校项目编写一个简单的消息服务器。在其其他功能中,服务器允许用户更新存储在其帐户中的信息。当用户确实更新他们的帐户时,会为他们生成一个身份验证令牌。这是定义所有这些的架构。注意headerbody是用户输入的一部分:

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();
          }
        });
      }
    });
  }
});

更新特定用户时遇到问题。因为我想使用模型中间件,所以我更新用户的方式是使用Model#findOne()后跟Model#save(). 这是我必须这样做的代码:

// 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));
        }
      });
    }
  });
}

当我运行测试并到达最后一段代码(save()返回之后)时,我得到以下输出:

Updated user:
{ token: '$2a$10$5VWWqjJ52aGbS4xc6NDKjuGPv8brX7pRmwiKyYjP8VHoTKCtYZiTu',
  username: 'jim_bob',
  password: '$2a$10$ue08HUsunzzzcbZURzXF7uaH1dZxF3SwkwadC6D1JsIC9xAUhTbCC',
  email: 'joe_bob@email.com',
  __v: 0 }
Returned user:
{ token: '$2a$10$fRwED..7fFFhN46Vn.ZJW..xYql5t5P39LHddjFS4kl/pmhwfT.tO',
  username: 'jim_bob',
  password: '$2a$10$ue08HUsunzzzcbZURzXF7uaH1dZxF3SwkwadC6D1JsIC9xAUhTbCC',
  email: 'joe_bob@email.com',
  __v: 0 }
[{"token":"$2a$10$5VWWqjJ52aGbS4xc6NDKjuGPv8brX7pRmwiKyYjP8VHoTKCtYZiTu","username":"joe_bob","password":"$2a$10$ue08HUsunzzzcbZURzXF7uaH1dZ
xF3SwkwadC6D1JsIC9xAUhTbCC","email":"joe_bob@email.com","__v":0}]

如您所见,文档没有正确保存到数据库中,因为之前的数据仍然存在。我的问题是:为什么?为什么调用保存时没有更新用户?我认为我做的一切都正确,但显然我不是。任何帮助都会很棒,因为我要疯了!

4

1 回答 1

3

显然,为了将文档保存到数据库,它需要一个_id. 有点傻,Mongoose 在找不到文档时不会给出错误。唉...

我更新了代码以反映更改:

 // 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}, "+_id +token +password", function (err, user) {
      if (err) {
        return callback(err);
      } else {
        console.log("Found user:");
        console.dir(user);
        // 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, numberTouched) {
          if (err) {
            return callback(err);
          } else {
            console.log("Returned user:");
            console.dir(user);
            console.log(numberTouched);
            User.find({}, "+token +password", function(err, foundUser) {
              if (err) {
                throw err;
              } else {
                console.dir(foundUser);
              }
            });
            callback(null, new SuccessEnvelope(user));
          }
        });
      }
    });
  }
于 2013-10-09T18:02:37.570 回答