I am trying to save password in MongoDB but have error:
Error: User validation failed: password: Path `password` is required.
Model:
const {Schema, model} = require('mongoose');
const UserSchema = new Schema({
email: {type: String, unique: true, required: true},
password: {type: String, required: true},
isActivated: {type: Boolean, default: false},
activationLink: {type: String},
})
module.exports = model('User', UserSchema)
create user:
const bcrypt = require('bcryptjs');
const UserModel = require('../models/user-model');
...
const hashPassword = await bcrypt.hash(password, 10);
console.log(`email => ${email} pass => ${hashPassword}`);
const user = await UserModel.create({email, hashPassword});
Log shows that password hash created:
email => lll#google.com pass => $2a$10$4IV2Q0ZncWHInfT89Fwl.eCxCgvykvY.uqlvq0GNSeDJ/6Q83T7nK
const user = await UserModel.create({email, hashPassword});
If you pass hashPassword variable, it will take as hashPassword field.
Change your code like this:
const hashPassword = await bcrypt.hash(password, 10);
const user = await UserModel.create({email, password: hashPassword});
Re-create your model using these lines of code
const mongoose = require('mongoose')
const bcrypt = require('bcryptjs')
const userSchema = mongoose.Schema(
{
email: {
type: String,
required: true,
lowercase: true,
trim: true
},
password: {
type: String,
required: false,
minlength: 8
},
activationLink: {
type: String,
trim: false
},
isActivated: {
type: Boolean,
default: false
}
},{
timestamps: true
}
)
userSchema.methods.isPasswordMatch = async function (password) {
const user = this
return bcrypt.compare(password, user.password)
}
userSchema.pre('save', async function (next) {
const user = this
if (user.isModified('password')) {
user.password = await bcrypt.hash(user.password, 8)
}
next()
})
const User = mongoose.model('user', userSchema)
module.exports = User
Related
I'm junior software developer which main task is develop a auth nodejs app. When I took the part of reset_password functionality, return me error message that I'm not able to solve.
This is my env file:
TOKEN_SECRET: T0K€N
RESET_PASSWORD_TOKEN: T0K€N
This is my user's model:
../models/user.js
const mongoose = require('mongoose');
const userSchema = mongoose.Schema({
name: {
type: String,
required: true,
min: 6,
max: 255
},
email: {
type: String,
required: true,
min: 6,
max: 1024
},
password: {
type: String,
required: true,
minlength: 6
},
subscribe: {
type: Boolean,
default: false
},
date: {
type: Date,
default: Date.now
},
role: {
type: String,
required: false,
minlength: 4
},
address: {
type: String,
required: false,
minlength: 4,
defaultValue: ""
},
nonce: {
type: String,
required: false,
minlength: 4,
defaultValue: ""
},
})
module.exports = mongoose.model('User', userSchema);
This is my token's model:
../models/token.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema({
token: {
type: String,
required: true,
min: 6
},
id_user:{
type: String,
required: true,
min: 1
}
})
module.exports = mongoose.model('expired_tokens', Schema);
And finally, my user's controller:
const Joi = require('#hapi/joi');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const nodemailer = require("nodemailer");
//models
const User = require('../models/user');
const expired_token = require('../models/expired_token');
//nodemailer
const sendMail = require('../nodemailer');
ResetPassword: async (req, res) => {
const user = await User.findOne({ email: req.body.email });
if (!user) {
return res.status(400).json({
data: "",
message: "User with this email doesn't exist",
status: "error"
})
}
const token = jwt.sign({ id: user._id, email: user.email }, process.env.RESET_PASSWORD_TOKEN );
const data = {
from: 'noreply#hello.com',
to: email,
subject: 'Recuperacion de contraseña',
template: "reset password",
context: {
url: 'http://localhosy:3005/auth/reset_password?token=' + token,
name: user.fullName.split('').split('')[0]
}
}
const link = `${process.env.BASE_URL}/reset_password/${user._id}/${token.token} `;
await sendEmail(user.email, "Password Reset", link);
},
//routes
router.route('/reset_password')
.post(verifyToken, controller.ResetPassword);
Nevertheless, when I tested in postman, return me the error message:
Probably, the error has to do with the enviroment variable in env. file. So, I'd be really grateful if someone could bring me his help or advice in order to solve this situation.
Thanks and have a nice day!
I'm trying to use joi module on mongoose schema but it doesn't work
everything works except joi validation
the module was installed and required.
schema:
const mongoose = require("mongoose");
const joi = require("joi");
const userSchima = new mongoose.Schema({
name: {
type: String,
required: [true, "use must have a name"],
unique: true,
trim: true,
},
email: {
type: String,
required: [true, "use must have an email"],
unique: true,
trim: true,
},
password: {
type: String,
required: [true, "use must have an password"],
},
});
const User = mongoose.model("User", userSchima);
// const validateUser = (User) => {
// const schema = {
// name: joi.string().min(2).max(15),
// email: joi.types.String().email().required(),
// password: joi.minOfUppercase(1).minOfNumeric(2).noWhiteSpaces().required(),
// };
// return joi.validate(User, schema);
// };
// module.exports = validateUser;
module.exports = User;
create async fun from the controller:
i didn't add the catch method because of to much code here
exports.creatUser = async (req, res) => {
try {
const newUser = await User.create(req.body);
res.status(200).json({
status: "success",
data: {
user: newUser,
},
});
}
thanks from help
I have 2 models in relation a User model and a Task model each user have inside an empty task array and I want a function that get the user by email and push a new task to the users task array I tried a lot but I don't made that function to work so I need some help here is my code.
User model:
const { Schema } = mongoose;
//connecting mongoose to mongoDB
mongoose.connect("mongodb+srv://tudor:tudor#cluster0.gbojb.mongodb.net/<dbname>?retryWrites=true&w=majority", { useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false });
const { Post } = require("./PostModel")
const userSchema = new Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
minlength: [5, 'The password should have more then 5 characters']
},
age: {
type: Number,
required: true,
},
description: {
type: String,
required: true,
maxlength: [300, 'Description should have less then 300 characters']
},
tasks: [{
type: Schema.Types.ObjectId,
ref: "task"
}]
})
const User = mongoose.model('User', userSchema);
exports.User = User
task model
const mongoose = require("mongoose")
const Schema = mongoose.Schema
let TaskSchema = new Schema({
content: String,
owner: {
type: Schema.Types.ObjectId,
ref: "User"
}
})
module.exports = mongoose.model("Task", TaskSchema)
And here I want to make the function :
const createNewTask = async (req, res, next) => {
const userEmail = req.params.id;
}
This is how your function will work:
const createNewTask = async (req, res, next) => {
const userEmail = req.params.id;
// find user first by email
const userData = await User.findOne({email: userEmail});
// add check here if user exist or not (not writing it for now)
// now create task by extract task payload (assuming you have detail in body)
const taskData = await Task.create({
content: req.body.content,
owner: userData._id,
});
// now push task id in user
await User.updateOne({
email: userEmail
}, {
$push: {tasks: taskData._id},
});
}
There can be some errors since didn't tested it but you get the idea how to do it.
The user model
```
const crypto = require('crypto');
const mongoose = require('mongoose');
const validator = require('validator');
const bcrypt = require('bcryptjs');
const UserSchema = new mongoose.Schema(
{
username: {
type: String,
unique: [true, 'Username already taken'],
required: [true, 'Please enter a usernam']
},
dob: String,
email: {
type: String,
required: [true, 'Please provide your email'],
unique: true,
lowercase: true,
validate: [validator.isEmail, 'Please provide with a mail']
},
profile_img: String, //url of the image |||Should think how we have store the image|||
password: {
type: String,
required: [true, 'Please provide with a password'],
minlength: 8,
select: false
},
passwordConfirm: {
type: String,
required: [true, 'Please confirm your password'],
validate: {
validator: function(el) {
return el === this.password;
},
message: "Password don't match"
}
},
passwordChangedAt: Date,
passwordResetToken: String,
passwordResetExpires: Date,
areaOfInterest: [], //array of String
friends: [
{
type: mongoose.Schema.ObjectId,
ref: 'User'
}
],
isBoarded: { type: Boolean, default: false },
createdAt: {
type: Date,
default: Date.now()
}
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
);
//virtual populate
UserSchema.virtual('posts', {
ref: 'Post',
foreignField: 'userId',
localField: '_id'
});
UserSchema.pre('save', async function(next) {
if (!this.isModified('password')) return next();
this.password = await bcrypt.hash(this.password, 12);
this.passwordConfirm = undefined;
next();
});
UserSchema.pre('save', function(next) {
if (!this.isModified('password') || this.isNew) return next();
this.passwordChangedAt = Date.now() - 1000;
next();
});
UserSchema.methods.correctPassword = async function(passwordToMatch, password) {
return await bcrypt.compare(passwordToMatch, password);
};
UserSchema.methods.changedPasswordAfter = function(JWTTimeStamp) {
if (this.passwordChangedAt) {
const changedTimeStamp = parseInt(
this.passwordChangedAt.getTime() / 1000,
10
);
return JWTTimeStamp < changedTimeStamp;
}
return false;
};
This is where the method is added using the methods property before the exporting the model
UserSchema.methods.createPasswordResetToken = function() {
const resetToken = crypto.randomBytes(32).toString('hex');
this.passwordResetToken = crypto
.createHash('sha256')
.update(resetToken)
.digest('hex');
// console.log({ resetToken }, this.passwordResetToken);
this.passwordResetExpires = Date.now() + 10 * 60 * 1000;
return resetToken;
};
const User = mongoose.model('User', UserSchema);
module.exports = User;
And method is called in this fuction
const { promisify } = require('util');
const crypto = require('crypto');
const jwt = require('jsonwebtoken');
const User = require('../models/userModel');
const catchAsync = require('../utils/catchAsync');
const AppError = require('../utils/appError');
const sendEmail = require('../utils/email');
exports.forgotPassword =async (req, res, next) => {
console.log(User.schema.methods);
const user = await User.findOne({ email: req.body.email });
console.log(user);
if (!user) {
return next(new AppError('No user with that email address', 404));
}
Here is where the error occurs where I have called the method with the error "user.createPassswordResetToken is not a function","stack":"TypeError: user.createPassswordResetToken is not a function\n at controllers/authController.js:117:27\n at processTicksAndRejections (internal/process/task_queues.js:93:5)"
In the above mentioned error this is the line no which it points to
const resetToken = user.createPassswordResetToken();
await user.save({ validateBeforeSave: false });
const resetURL = `${req.protocol}://${req.get(
'host'
)}/api/v1/users/resetPassword/${resetToken}`;
const message = `Forgot your Password? Submit your new password and confirm your password at ${resetURL}.\n If you didn't forgot your password, please ignore this email.`;
The console log of User.schema.methods is
{
correctPassword: [AsyncFunction (anonymous)],
changedPasswordAfter: [Function (anonymous)],
createPasswordResetToken: [Function (anonymous)]
}
the method in user schema is createPasswordResetToken, while in the function you called another non existing function createPassswordResetToken
use createPasswordResetToken rather than createPassswordResetToken
I've create a Mongoose model and I wrote some code to test if it works, I tried to save the model and then display all of the models but it doesn't log anything to the console and the model isn't saving.
My testing code:
let User = require('./models/user')(MAI);
let myUser = new User({
username: 'Admin',
email: 'admin#example.com',
password: '123456',
});
await myUser.save();
User.find((err, users) => {
if(err) console.log(err);
console.dir(users);
});
My model:
const mongoose = require('mongoose');
const UserSchema = mongoose.Schema({
user_id: Number,
username: String,
email: String,
password: String,
verified: { type: Boolean, default: false },
joindate: { type: Date, default: Date.now },
postcount: { type: Number, default: 0 },
});
module.exports = function(MAI) {
UserSchema.plugin(MAI.plugin, {
model: 'User',
field: 'user_id',
startAt: 1,
incrementBy: 1,
unique: true
});
return mongoose.model('User', UserSchema);
}
And if it's important, mongoose & mai initialization:
mongoose.Promise = require('bluebird');
let connection = mongoose.createConnection('mongodb://localhost:27017/forum');
MAI.initialize(connection);
Fixed it, the problem was I required mongoose in the model file when what I should've done was to pass the mongoose from my entry point.