Virtual field not setting field in mongoose model

时间:2018-03-23 00:26:53

标签: node.js express mongoose-schema

I am new to nodeJS and mongoose. I am trying to make a user model that does not save a password as plain text. In other backend frameworks you can accomplish this with an ORM by utilizing a virtual field. I looked up the docs for Mongoose and found that this can be accomplished. Following the dics I created the following Mongoose model. Mind you this is not the final implementation and is for merely testing my understanding of how Mongoose handle virtual fields.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const userSchema = new Schema({
  name: {type: String, required: true},
  email: {type: String, required: true},
  passwordHash: {type: String, required: true}
});

userSchema.virtual("password")
  .get(() => this._password)
  .set(val => {
    this._password = val;
    console.log("setting: ", val);
    this.passwordHash = "test";
  })


module.exports = mongoose.model("Users", userSchema);

I also have the following test for this model

it("should not save passwords as plain test", done => {
    const user = new User({name: "john", email: "john@example.com",     password: "password1234"});
    console.log(user);
    user.validate(({errors}) => {
      expect(errors).to.not.exist
    });
    done();
  }); 

The test fails because I have an error. The error states that the passwordHash field is missing. I know I have that field as required, but I assign the value "test" to this.passwordHash in the set function just like the docs say to do. This is where I get stuck. Any guidance is much appreciated.

1 个答案:

答案 0 :(得分:1)

我认为问题出在this函数

中的userSchema.virtual("password")上下文中
userSchema.virtual("password")
  .get(() => this._password) // this points to global object
  .set(val => {
    this._password = val; // this points to global object
    console.log("setting: ", val);
    this.passwordHash = "test";
  });

当您无法使用箭头功能时,这是一个例外情况。

userSchema.virtual("password")
  .get(function() {
      return this._password;
  })
  .set(function(val) {
    this._password = val;
    console.log("setting: ", val);
    this.passwordHash = "test";
  });

让我知道它现在正常运作。

我的一般建议:对于散列/检查密码,使用Schema.pre('save')挂钩。例如:

// before save user
userSchema.pre('save', function(next) {
  if (this.isModified('password')) { //only if password is modified then hash
    return bcrypt.hash(this.password, 8, (err, hash) => {
      if (err) {
        return next(err);
      }
      this.password = hash; //save hash in UserSchema.password in database
      next();
    });
  }
  next();
});

Schema.pre是中间件的一部分。有关mongoose的中间件的更多信息:http://mongoosejs.com/docs/middleware.html