Mongoose Schema.method() 不工作,并显示一条错误消息

Mongoose Schema.method() is not working, and showing an error message

我正在获取用户输入的密码并使用 crypto 加密密码,然后保存到数据库中。这是我的代码,在这里我将加密的密码存储到来自 userSchema 的 encry_password 属性 中。但是,这给我的错误是“this.securePassword”不是一个函数。

const mongoose = require("mongoose");
const crypto = require("crypto");
const { v1: uuidv1 } = require("uuid");

const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    maxlength: 32,
    trim: true,
  },
  lastname: {
    type: String,
    maxlength: 32,
    trim: true,
  },
  email: {
    type: String,
    trim: true,
    required: true,
    unique: true,
  },
  usrinfo: {
    type: String,
    trim: true,
  },
  encry_password: {
    type: String,
    required: true
  },
  salt: String,
  role: {
    type: Number,
    default: 0,
  },
  purchases: {
    type: Array,
    default: [],
  },
}, { timestamps: true });


userSchema.virtual("password")
  .set((password) => {
    this._password = password;
    this.salt = uuidv1();
    this.encry_password = securePassword(password, uuidv1());
    console.log(this.encry_password);
  })
  .get(() => {
    return this._password;
  });

// const authenticate = function (plainPassword, encry_password) {
//   return securePassword(plainPassword) === encry_password;
//   };

const securePassword = function (plainPassword, salt) {
  if (!plainPassword) return "";
  try {
    return crypto.createHmac("sha256", salt).update(plainPassword).digest("hex");
  } catch (error) {
    return "";
  }
};


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

用户注册路径

exports.signup = (req, res) => {
    console.log(req.body);
    const user = new User(req.body);
    user.save((err, user) => {
        if (err) {
            console.log(err);
            res.status(400).json({
                err: "Note able to save the user in database"
            });
        } else {
            res.json(user);
        }
    });
};

似乎 securePassword 函数的作用域是在 userSchema 中定义的,而您正试图在 userSchema.virtual 中调用它。

首先,在这种情况下你不应该使用virtual

Virtuals

Virtuals are document properties that you can get and set but that do not get persisted to MongoDB. The getters are useful for formatting or combining fields, while setters are useful for de-composing a single value into multiple values for storage.

但是在virtual的范围内,this不能访问方法,像你这样的方式不能访问方法,这是mongoose中方法使用的一个例子

  const Animal = mongoose.model('Animal', animalSchema);
  const dog = new Animal({ type: 'dog' });

  dog.findSimilarTypes((err, dogs) => {
    console.log(dogs); // woof
  });

你可以查看 method documantation:

如果你只想以你的方式访问 securePassword 你可以喜欢这个并完全删除方法 mongoose 因为这不是使用 method:

的地方
UserSchema.virtual("password")
  .set((password) => {
    this._password = password;
    this.salt = uuidv1();
    console.log("This is running");
    this.encry_password = securePassword(password, this.salt);
    console.log(encry_password);
  })
  .get(() => {
    return this._password;
  });

const authenticate = function (plainPassword, encry_password) {
  return securePassword(plainPassword) === encry_password;
};

const securePassword = function (plainPassword, salt) {
  if (!plainPassword) return "";
  try {
    return crypto
      .createHmac("sha256", salt)
      .update(plainPassword)
      .digest("hex");
  } catch (error) {
    return "";
  }
};

如果你想创建authenticate service,改变你的方式,不要使用虚拟密码,使用pre save

在将有关用户的信息保存到数据库之前,将完成此任务 检查 pre documentation

userSchema.pre("save", async function (next) {
  try {
    this.password = securePassword (plainPassword, salt);
  } catch (error) {
    console.log(error);
  }
});

创建散列密码后,像这样保存信息:

const userSchema = new mongoose.Schema({
    .
    .
    .
    password: { //convert encry_password to password
      type: String,
    }
    .
    .
    .
  }, { timestamps: true });
  //every time want to user save this method called
  userSchema.pre('save', function (next) {
    this.salt = uuidv1()
    this.password = securePassword(this.password, this.salt)
    next()
 })
 //for have a clean  routes, you can create a static methods
 userSchema.statics.Create = async (data) => {
    let model = new User(data); 
    let resUser = await model.save(); //save your user
    return resUser;
  };

  const securePassword = function (plainPassword, salt) {
    if (!plainPassword) return "";
    try {
      return crypto.createHmac("sha256", salt).update(plainPassword).digest("hex");
    } catch (error) {
      return "";
    }
  };
  
  let User  = mongoose.model("User", userSchema)
  module.exports = {User};

像这样更改控制器:

let {User} = require("./path of user schema")
exports.signup = async (req, res) => {
  try {
    console.log(req.body);
    const user = await User.create(req.body); //create a user
    res.json(user);
  } catch (error) {
    console.log(err);
    res.status(400).json({
      err: "Note able to save the user in database",
    });
  }
};

注意 : 在 req.body 中,密码字段的名称应为 password