#node.js #mongodb #mongoose #mongoose-schema
#node.js #mongodb #mongoose #mongoose-schema
Вопрос:
Я принимаю ввод пароля от пользователя и шифрую пароль с помощью криптографии, а затем сохраняю в базе данных. Это мой код, здесь я сохраняю зашифрованный пароль в свойстве 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);
}
});
};
Ответ №1:
прежде всего, в этой ситуации вы не должны использовать virtual
Виртуальные объекты — это свойства документа, которые вы можете получить и установить, но которые не сохраняются в MongoDB. Геттеры полезны для форматирования или объединения полей, в то время как сеттеры полезны для разбиения одного значения на несколько значений для хранения.
но в области virtual
, this
не удается получить доступ к методу, вы не можете получить доступ к методу, как ваш способ, это пример использования метода в mongoose
const Animal = mongoose.model('Animal', animalSchema);
const dog = new Animal({ type: 'dog' });
dog.findSimilarTypes((err, dogs) => {
console.log(dogs); // woof
});
вы можете проверить документирование метода:
если вы хотите просто получить доступ к securePassword
своему способу, вам может понравиться это и удалить метод mongoose complately, потому что это не то место, которое нужно использовать 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
Комментарии:
1. Я запускаю этот код, он работает нормально, и я могу сохранить зашифрованный пароль в этом свойстве.encry_password. Но проблема в том, что перед сохранением пароля в этом свойстве.encry_password в базе данных сохраняется нулевая информация, поэтому она выдает ошибку «требуется this.encry_password».
2. пожалуйста, полностью добавьте ваш файл схемы в вопрос
3. вы должны изменить свой способ и не использовать virtual, в
virtual
области видимости невозможно получить доступ к полям схемы сthis
помощью, используйтеpre save
,4. Я добавил весь свой файл схемы, теперь вы можете проверить
5. вы хотите создать пользователя с хэш-паролем? это правильно?
Ответ №2:
Похоже, что область действия функции securePassword определена внутри UserSchema, и вы пытаетесь вызвать ее в UserSchema.virtual.
Комментарии:
1. Можете ли вы помочь мне решить эту проблему?