У меня проблемы с NodeJS (ExpressJS), MongoDB, Joi Validation Module и Bcrypt.
У меня есть пользовательский API-маршрутизатор и пользовательская модель. Моя модель пользователя такова:
const userSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
minlength: [3, 'Adınızın Karakter Sayısı Uygun Değildir. Minimum 3, Maksimum 50 Adet Karakterden Oluşabilir.'],
maxlength: [50, 'Adınızın Karakter Sayısı Uygun Değildir. Minimum 3, Maksimum 50 Adet Karakterden Oluşabilir.'],
validate: {
validator: function(v) {
return /^[A-Za-zıİüÜğĞşŞçÇöÖ ]+$/.test(v);
},
message: 'Uygun Formatta İsim Giriniz. (Geçerli Karakterler: a-z, A-Z, boşluk karakteri.)'
},
match: [/^[A-Za-zıİüÜğĞşŞçÇöÖ ]+$/, 'Uygun Formatta İsim Giriniz. (Geçerli Karakterler: a-z, A-Z, boşluk karakteri.)']
},
lastname: {
type: String,
trim: true,
minlength: [3, 'Soyadınızın Karakter Sayısı Uygun Değildir. Minimum 3, Maksimum 50 Adet Karakterden Oluşabilir.'],
maxlength: [50, 'Adınızın Karakter Sayısı Uygun Değildir. Minimum 3, Maksimum 50 Adet Karakterden Oluşabilir.'],
validate: {
validator: function(v) {
return /^[A-Za-zıİüÜğĞşŞçÇöÖ ]+$/.test(v);
},
message: 'Uygun Formatta Soyisim Giriniz. (Geçerli Karakterler: a-z, A-Z, boşluk karakteri.)'
},
match: [/^[A-Za-zıİüÜğĞşŞçÇöÖ ]+$/, 'Uygun Formatta Soyisim Giriniz. (Geçerli Karakterler: a-z, A-Z, boşluk karakteri.)']
},
username: {
type: String,
trim: true,
index: true,
unique: true,
minlength: [3, 'Kullanıcı Adınızın Karakter Sayısı Uygun Değildir. Minimum 3, Maksimum 30 Adet Karakterden Oluşabilir.'],
maxlength: [20, 'Kullanıcı Adınızın Karakter Sayısı Uygun Değildir. Minimum 3, Maksimum 30 Adet Karakterden Oluşabilir.'],
validate: {
validator: function(v) {
let re = /^\w+$/;
return re.test(v);
},
message: 'Uygun Formatta Kullanıcı Adı Giriniz. (Geçerli Karakterler: a-z, A-Z, _.)'
},
match: [/^\w+$/, 'Uygun Formatta Kullanıcı Adı Giriniz. (Geçerli Karakterler: a-z, A-Z, _.)']
},
email: {
type: String,
trim: true,
index: true,
unique: true,
validate: {
validator: function(v) {
let re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
return re.test(v);
},
message: 'Uygun Formatta E-Posta Adresi Giriniz.'
},
match: [/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/, 'Uygun Formatta E-Posta Adresi Giriniz.']
},
password: {
type: String,
trim: true,
required: [true, 'Şifrenizi Girmeniz Gerekmektedir.'],
minlength: 5,
maxlength: 1024
},
elo: {
type: Number,
min: 0,
required: false,
default: 0
},
rank: {
type: Number,
min: -1,
required: false,
default: 0
},
registerDate: {
type: Date,
default: Date.now
},
isAdmin: {
type: Boolean,
required: true,
default: false
}
});
И это схема проверки Joi:
const Schema = {
name: Joi.string().min(3).max(50).regex(/^[A-Za-zıİüÜğĞşŞçÇöÖ ]+$/),
lastname: Joi.string().min(3).max(50).regex(/^[A-Za-zıİüÜğĞşŞçÇöÖ ]+$/),
username: Joi.string().required().min(3).max(25).regex(/^\w+$/),
email: Joi.string().required().min(3).email(),
password: Joi.string().required().min(5).max(255),
elo: Joi.number().default(0).min(0),
rank: Joi.number().default(0).min(-1),
isAdmin: Joi.boolean().default(false)
};
Это образец пользователя:
_id:5b47aae43cf7710e7047c033
elo:0
rank:0
isAdmin:true
name:"Furkan"
lastname:"Taştan"
username:"praaven"
email:"[email protected]"
password:"$2b$10$4xKTxmQnV5mnGrCccpQsY.A8j5ACCdmCHIihDdW0NXmcOcRCcwwPq"
registerDate:2018-07-12 22:24:20.778
__v:0
Я не понимаю, как обновить маршрутизатор API.
router.put('/:id', auth, async (req, res) => {
try {
const errorId = validateUserId(req.params.id);
if (errorId.error) return res.status(400).send({'Hata': errorId.error.details[0].message});
const { error } = validateUser(req.body);
if (error) return res.status(400).send({'Hata': error.details[0].message});
const salt = await bcyript.genSalt(10);
const user = await User.findByIdAndUpdate(req.params.id, {
name: req.body.name,
lastname: req.body.lastname,
username: req.body.username,
email: req.body.email,
password: await bcyript.hash(req.body.password, salt),
elo: req.body.elo,
rank: req.body.rank,
isAdmin: req.body.isAdmin
}, { new: true, runValidators: true, context: 'query' });
if (!user) return res.status(404).send({'Hata': 'Belirtilen ID\'ye Sahip Kullanıcı Bulunamadı.'});
res.status(200).send(_.pick(user, ['_id', 'name', 'lastname', 'username', 'email', 'elo', 'rank', 'registerDate', 'isAdmin']));
} catch(e) {
res.status(400).send({ 'Hata': e.message.replace(/(Validation failed|email|username|phone|team)/gi, v => arrayMap[v]) });
}
});
Проблема в том, зачем мне нужен пароль каждого пользователя обновления? Мне не нужен пароль пользователя, я хочу использовать его по желанию. Я думаю, мой Update Router
ошибочен, я новичок в кодировании API RESTful на NodeJS, вы можете мне помочь с этим?
Спасибо, хорошего дня!
@B_CooperA Да, то же самое. Я только что удалил .required()
по паролю Joi Schema. После этого я сделал условие if для моего метода PUT, потому что if (пароль, определенный в полезной нагрузке) обновлял данные пользователя с паролем, иначе обновлял данные пользователя без пароля. И я решил эту проблему на данный момент. Это хорошо или есть подход лучше? Спасибо...
Я отправил ответ. Надеюсь, я правильно понял вашу проблему :)
Вы уже проверяете поле пароля на уровне Schema
здесь:
password: {
type: String,
trim: true,
required: [true, 'Şifrenizi Girmeniz Gerekmektedir.'],
minlength: 5,
maxlength: 1024
},
поэтому нет необходимости повторно проверять его с помощью required()
внутри схемы JOI
.
Поскольку вы используете Mongoose
, вы можете использовать функции pre
внутри вашего userSchema
. Как это:
/**
* Hash password with blowfish algorithm (bcrypt) before saving it in to the database
*/
userSchema.pre('save', function(next) {
var user = this;
// only hash the password if it has been modified
if (!user.isModified('password'))
return next();
// password will be hashed only if it has changed
user.password = bcrypt.hash(user.password, bcrypt.genSalt(10));
next();
});
Это действительно из-за required()
, который вы добавили в свою схему JOI.
В качестве решения у вас есть несколько способов сделать это. Возможно, вы захотите предоставить другой API, чтобы специально разобраться с нюансами паролей и имени пользователя. Таким образом, вы в конечном итоге создаете две отдельные схемы JOI для работы с разными ситуациями - с изменением пароля, когда это действительно необходимо, и при обновлении деталей (я не уверен, что перемещение паролей вперед и назад при обновлении деталей - это приятное занятие. идея).
Дополнение: даже с учетом этого, я заметил, что вы на самом деле не выполняете здесь никаких преобразований (кроме пароля) над данными при передаче их из тела запроса в модель базы данных - и я не уверен, почему вы хотите проверить эти данные дважды для этого случая (помните, что вы также включили переключатель runValidators
во время обновления).
Да, мне действительно не нужно использовать JOI, да?
@ n3pixowe Вы можете использовать либо проверку JOI, либо проверку схемы Mongoose во время обновления. Не нужно делать это дважды с одними и теми же данными в одно и то же мгновение, да.
Ммм .. Значит, вы хотите обновить пароль, только если он был изменен?