首页 > 解决方案 > Mongoose Schema.method() 不起作用,并显示错误消息

问题描述

我正在从用户那里输入密码并使用密码加密密码,然后保存到数据库中。这是我的代码,这里我将加密的密码存储到来自 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);
        }
    });
};

标签: node.jsmongodbmongoosemongoose-schema

解决方案


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

虚拟

Virtuals 是您可以获取和设置但不会持久保存到 MongoDB 的文档属性。getter 可用于格式化或组合字段,而 setter 可用于将单个值分解为多个值以进行存储。

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

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

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

您可以检查方法文档

如果您只想以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,改变你的方式,不要使用 virtual 作为密码和使用pre save

在将有关用户的信息保存在数据库中之前,将完成此任务检查预文档

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


推荐阅读