Azoulay Jason
Azoulay Jason

Reputation: 2989

Route using wrong validator in Mongoose

I'm using Postman to test the routes and this route returns the err message after user.save((err)=>{}) saying that the password is too long. It uses a passwordValidator I created but I obviously didn't call it for this route neither in Schema.

What am I doing wrong?

The user schema in mongoose:

    const userSchema=new Schema({
    email: { type: String, required: true, unique: true, lowercase: true, validate: emailValidators},
    username: { type: String, required: true, unique: true, lowercase: true, validate: usernameValidators},
    bio: { type:String,default:null,validate:bioValidators},
    location: {type:String, default:null},
    gender: {type:String,default:null,validate:genderValidators},
    birthday: { type:String,default:null},
    password: { type: String, required: true,validate: passwordValidators}
});

The route:

router.put('/editProfile',(req,res)=>{
        if(!req.body.bio){
            res.json({success:false,message:"No bio provided"});
        }
        else{
            if(!req.body.location){
                res.json({success:false,message:"No location provided"});
            }
            else{
                if(!req.body.gender){
                    res.json({success:false,message:"No gender provided"});
                }
                else{
                    if (!req.body.birthday) {
                        res.json({success:false,message:"No birthday provided"});
                    }
                    else{
                        User.findOne({_id:req.decoded.userId},(err,user)=>{
                            if(err){
                                res.json({success:false,message:"Something went wrong: "+err});
                            }
                            else{
                                if(!user){
                                    res.json({success:false,message:"User not found"});
                                }
                                else{
                                    user.bio=req.body.bio;
                                    user.location=req.body.location;
                                    user.gender=req.body.gender;
                                    user.birthday=req.body.birthday;
                                    user.save((err)=>{
                                        if(err){
                                            res.json({success:false,message:'Something went wrong: '+ err}); //returns this
                                        }
                                        else{
                                            res.json({success:true,message:"Account updated !"});
                                        }
                                    }); 
                                }
                            }
                        });
                    }
                }
            }
        }
    });

EDIT

Here's the password validator array

const passwordValidators = [
    {
        validator: passwordLengthChecker,
        message: 'Password must be at least 5 characters but no more than 40'
    },
    {
        validator:validPassword,
        message: 'Must have at least one uppercase, lowercase, special character, and number'
    }
];

and the checkers

let passwordLengthChecker = (password)=>{
    if (!password) {
        return false;
    }
    else{
        if(password.length<5 || password.length>40){
            return false;
        }
        else{
            return true;
        }
    }
};

let validPassword = (password)=>{
    if (!password) {
        return false;
    }
    else{
        const regExp = new RegExp(/^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[\d])(?=.*?[\W]).{8,35}$/);
        return regExp.test(password);
    }
};

As you can see it's using the passwordLengthChecker though it shouldn't

EDIT N°2

I just realized i have this middleware just below the schema

userSchema.pre('save', function(next){
    if(!this.isModified('password'))
    return next();

    bcrypt.hash(this.password, null, null, (err,hash)=>{
        if(err) return next(err);
        this.password=hash;
        next();
    });
});

does it mean this function is gonna run everytime I use save() ?

Upvotes: 1

Views: 86

Answers (2)

user8377060
user8377060

Reputation:

Down here is the problem, you providing bio , location, gender, birthday but not password. When you do not declare a password its length will be equal to 0. That's why you get error back. Length can be from 5 to 40.

else{
                                    user.password=req.body.password;
                                    //I added user.password here, this is what you should do
                                    user.bio=req.body.bio;
                                    user.location=req.body.location;
                                    user.gender=req.body.gender;
                                    user.birthday=req.body.birthday;
                                    user.save((err)=>{
                                        if(err){
                                            res.json({success:false,message:'Something went wrong: '+ err}); //returns this
                                        }
                                        else{
                                            res.json({success:true,message:"Account updated !"});
                                        }
                                    }); 
                                }

UPDATE HERE

If you are only going to update bio,location,gender and birthday then using save() function is wrong. You need to use findOneAndUpdate() function.

User.findOneAndUpdate({_id:req.decoded.userId}, { $rename : {gender: 'male' , bio : 'somethingElse'}}, {new: true}, function(err, user){
if(err) throw err;
else{
console.log("done : " + user.gender);
}
});

Also please see findOneAndUpdate and its operators to be used

Upvotes: 1

Azoulay Jason
Azoulay Jason

Reputation: 2989

So i think the bcrypt function compromised the Mongoose save() function, i found an other solution for now in Mongoose doc.

User.findByIdAndUpdate(req.decoded.userId,{$set:{bio:req.body.bio, location:req.body.location, gender:req.body.gender, birthday:req.body.birthday}},{new:true},function(err,user){
                            if(err){
                                res.json({success:false,message:"Something went wrong: "+err});
                            }
                            else{
                                if(!user){
                                    res.json({success:false,message:"User not found"});
                                }
                                else{
                                    res.json({success:true,user:user});
                                }
                            }
                        });

Upvotes: 0

Related Questions