How to check confirm password with zod - node.js

How do I check for confirm password with zod?. I want to validate for confirm password with Zod. I want Zod to compare my password with comparePassword
export const registerUSerSchema = z.object({
firstName: z.string(),
lastName: z.string(),
userName: z.string(),
email: z.string().email(),
phone: z.string().transform(data => Number(data)),
password: z.string().min(4),
confirmPassword: z.string().min(4),
avatar: z.string().optional(),
isVerified: z.boolean().optional()
})

You can achieve this by tacking on a superRefine
export const registerUserSchema = z.object({
firstName: z.string(),
lastName: z.string(),
userName: z.string(),
email: z.string().email(),
phone: z.string().transform(data => Number(data)),
password: z.string().min(4),
confirmPassword: z.string().min(4),
avatar: z.string().optional(),
isVerified: z.boolean().optional()
}).superRefine(({ confirmPassword, password }, ctx) => {
if (confirmPassword !== password) {
ctx.addIssue({
code: "custom",
message: "The passwords did not match"
});
}
});
If the passwords fail to parse for the base reason (not at least 4 characters) then that error will come through, but if the whole base object succeeds to parse, then the super refine check will happen.

I have like this:
const validationSchema = z
.object({
name: string().min(1, { message: "Name is required" }), // pass custom message
email: string().email(),
website: string().optional(),
country: string(),
password: string(),
confirm: string(),
})
.refine((data) => data.password === data.confirm, {
message: "Passwords don't match",
path: ["confirm"],
});
I am using React Hook Form.
Here are some docs, I copy and pasted for you, so you can see how it works: https://docs.google.com/document/d/1jqTth88I-D0-qzq34B4sUGbp8wGmExS7kpc78QA_4sk/edit?usp=sharing

Related

mongoose put does not check for required field

I am making nodejs API and I have a user model. Some fields are required. When trigger post it will tell me that some fields required so no save will be done, but when I do it with put it will replace it even if validation is wrong, or even if there is a required field and is missing, but duplicates run good.
this is the model of user
const mongoose = require('mongoose');
const validator = require('validator');
const userSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
firstName: {
type: String,
required: [true, 'the firstName is missing'],
validate: [(val) => validator.isAlpha(val, ['fr-FR']), 'not valid first name'],
},
lastName: {
type: String,
required: [true, 'the lastName is missing'],
validate: [(val) => validator.isAlpha(val, ['fr-FR']), 'not valid last name'],
},
phoneNumber: {
type: String,
required: [true, 'the phoneNumber is missing'],
unique: [true, 'phoneNumber already in use'],
validate: [(val) => validator.isMobilePhone(val,['ar-DZ']), 'not valid phone number'],
},
email : {
type: String,
required: [true, 'the email is missing'],
unique: [true, 'email already in use'],
validate: [validator.isEmail, 'not valid email'],
},
role: {
type : String,
"enum" : ['teacher', 'student'],
required : [true, 'the user `s role is missing'],
}
});
module.exports = mongoose.model('User', userSchema);
this is where I handle put
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const User = require('../../../../models/user');
router.put('/', (req, res) => {
//get the new user object
const userId = req.body.userId;
User.replaceOne({
_id: userId
},
{
_id: userId,
firstName: req.body.firstName,
lastName: req.body.lastName,
phoneNumber: req.body.phoneNumber,
email: req.body.email,
role: req.body.role
})
.exec()
.then(response => {
res.status(200).json(response);
})
.catch(err => console.log(err));
});
module.exports = router;
so I tried to test those, by postman, I wanted from mongoose to do that automatically, I thought about splitting it and redirect it to delete then post, but i will need to do the checking first, or just do the checking manually, and because am using api, I don't want to use the patch method so I don't track the user for what changes he did in the front end.
You can, instead of replaceOne() use updateOne() or findOneAndUpdate() with turned on validators (as they are of by default), like so:
User.updateOne({_id: userId},
{
_id: userId,
firstName: req.body.firstName,
lastName: req.body.lastName,
phoneNumber: req.body.phoneNumber,
email: req.body.email,
role: req.body.role
},
{runValidators: true})
.then(response => {
res.status(200).json(response);
})
.catch(err => console.log(err));
Or you can call the validate() on the new instance of the model and if it is valid continue with update logic, e.g.
let user = new User({_id: userId,
firstName: req.body.firstName,
lastName: req.body.lastName,
phoneNumber: req.body.phoneNumber,
email: req.body.email,
role: req.body.role});
user.validate()
.then(() => {
// update logic
})
.catch((err) => {
// handle error
})
Look for more information on Mongoose validation with update.

MongoError code 66 immutable field in nodeJS

I was trying to do an update operation. Now I'm getting an immutable error I knew the cause it was updating the key. I wonder because I'm not passing the _id from the API still I can see the _id if I console. I want to remove the _id from my object in order to fix this error. Code below
router.put('/:id', (req, res) => {
//var findid= req.params.id;
if (!ObjectId.isValid(req.params.id))
return res.status(400).send(`No record with given id : ${req.params.id}`);
var alum = new Alumni({
fname: req.body.fname,
lname: req.body.lname,
contact: req.body.contact,
gender: req.body.gender,
dob: req.body.dob,
message: req.body.message,
city: req.body.city,
pincode: req.body.pincode,
state: req.body.state,
district: req.body.district,
password: req.body.password,
email: req.body.email
});
//delete alum['_id'];
Alumni.findByIdAndUpdate(req.params.id, { $set: alum }, { new: true }, (err, doc) => {
if (!err) { res.send(doc); }
else {
console.log(alum);
console.log('Error in Alumni Update :' + JSON.stringify(err, undefined, 2)); }
});
});
How can I resolve this error?
Whenever JSON object is assigned using mongoose model like new Alumni(), by default it assigns _id field which is immutable so you don't need to use model with update object. Simply assign it as given below
var alum = {
fname: req.body.fname,
lname: req.body.lname,
contact: req.body.contact,
gender: req.body.gender,
dob: req.body.dob,
message: req.body.message,
city: req.body.city,
pincode: req.body.pincode,
state: req.body.state,
district: req.body.district,
password: req.body.password,
email: req.body.email
};

I have been trying to solve the duplicate key problem in nodeJS with Mongoose, but nothing works

I'm trying to build a user model, but I want to make sure that username and email are unique. When I created the first user everything was ok, but when I try to create the second user with the same information, I got the some error that I can handle in when I will save, but the duplicate key wasn't there to handle it.
This is my schema file code:
const UserSchema = new Schema({
// this username with SchemaType of string
username: {
type: String,
lowercase: true,
required: [true, "username is required"],
unique: true,
trim: true,
minlength: [4, "try to user longer name"],
maxlength: [60, "your name is way too long"],
},
// virtual name
name: {
// name have two properties
// first is first and refer to first-name
// second is last and refer to last-name
first: {
type: String,
lowercase: true,
trim: true,
minlength: 4,
maxlength: 20
},
last: {
type: String,
lowercase: true,
trim: true,
minlength: 4,
maxlength: 20
}
},
password: {
type: String,
required: [true, "password is required"]
},
email: {
type: String,
required: [true, "email is required"],
unique: true
},
active: {
type: Boolean,
default: true
},
admin: {
type: Boolean,
default: false
},
meta: {
update: {
type: Date,
default: Date.now()
},
timestamp: {
type: Date,
default: Date.now()
}
}
});
UserSchema.virtual("fullname").get(function () {
// return the concatenation of first and last
return this.name.first + " " + this.name.last;
});
// Create User Model
const User = mongoose.model("User", UserSchema);
module.exports = User;
And this is my router code where I tried to handle it:
router.post("/register", (request, response) => {
const user = {
username: request.body.username,
email: request.body.email,
password: request.body.password
};
if (!user.email && !user.username && !user.password) {
return response.json({
"message": "please fill the whole information"
});
}
// put user info in model
const newUser = new User({
username: user.username,
email: user.email,
password: user.password
})
newUser.validate((err) => {
console.log(err);
});
// save User in model
newUser.save()
// return response with info
return response.status(201).json(user);
})
I think the explanation here is quite a simple one. You are specifying the unique attribute in your schema for multiple fields, so mongo will not allow you to create multiple entries with the same information. This is quite obvious.
Also, I noticed a bit of irregularity in your code. The save method you are calling returns a promise, which means the event loop will not block your code and the response will be returned immediately. For this, you either need to handle your response inside the then block or use async await throughout your code.
I would suggest the following changes:
router.post("/register", (request, response) => {
const user = {
username: request.body.username,
email: request.body.email,
password: request.body.password
};
if (!user.email && !user.username && !user.password) {
return response.json({
"message": "please fill the whole information"
});
}
// put user info in model
const newUser = new User({
username: user.username,
email: user.email,
password: user.password
})
newUser.validate((err) => {
if(err) {
response.status(403).json({ message: 'Your custom error message' });
}
newUser.save().then(res => {
return response.status(201).json(user);
}).catch(e => {
return response.status(500).json({ message: 'Your custom error message' });
})
});
})

Nodejs saving to mongoDB

I want to save data to database but i dont know how to do it in this case.
userModel.js
const userSchema = new mongoose.Schema({
email: {
type: String,
unique: true
},
password: String,
passwordResetToken: String,
passwordResetExpires: Date,
profile: {
firstname: String,
lastname: String,
gender: String,
status: String,
location: String,
website: String,
picture: String
}
});
Signup.js
const user = new User({
firstname: req.body.firstname,
lastname: req.body.lastname,
location: req.body.location,
status: 0,
email: req.body.email,
password: req.body.password
});
Problem is that those things in profile wont save and i dont know how to edit that signup.js to make it work. Something like profile.firstname: req.body.firstname does not work.
const user = new User({
profile: {
firstname: req.body.firstname,
lastname: req.body.lastname,
location: req.body.location,
status: 0,
},
email: req.body.email,
password: req.body.password
});
From schema (userModel.js), we need update with profile structure
You need to save like this in signUp.js
const user = new User({
profile :{
firstname: req.body.firstname,
lastname: req.body.lastname,
location: req.body.location,
status: 0
},
email: req.body.email,
password: req.body.password
});
As firstname, lastname, location and status are part of the profile object.

Node POST req returns same values regardless of input

I'm making a POST request like this:
router.post('/register2', (req, res) => {
const newUser = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password
});
newUser.save()
.then(res.json(newUser));
})
But, in Postman, no matter what I enter for my name/email/password values, it just returns the first set of values I ever tried. The id and date update each time, but name, email, and password ignore the input and give me the same things every time.
Here's the "User" that newUser refers to:
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model('users', UserSchema);

Resources