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.
答案 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