I created a user authentication system where user needs to verify first with otp after then user can login but the problem is while updating user verified status password is also updating automatically. I can’t figure out the problem why is this happening. I sharing my code anyone help me with this
Here is my verify and login controller
`
const verifyUser = expressAsyncHandler(async (req, res) => {
let minutes = 10;
let now = new Date().getTime();
let otpTime;
let otpFromDatabase;
const { otp } = req.body;
const user = await User.findById(req.user._id);
if (!user) {
res.status(404);
throw new Error("User not found");
}
otpTime = new Date(user.otpTime).getTime();
otpFromDatabase = user.otp;
console.log("Time-Diff", now - otpTime > minutes * 60 * 1000);
console.log("Time-Diff 2", now - otpTime);
if (now - otpTime > minutes * 60 * 1000) {
user.isOtpExpired = true;
const otpExpiredUpdateUser = await user.save();
res.json({
otpTime: otpExpiredUpdateUser.otpTime,
otpFromDatabase: otpExpiredUpdateUser.otp,
otpExpired:otpExpiredUpdateUser.isOtpExpired,
});
} else {
if (otpFromDatabase !== otp) {
res.status(400);
throw new Error("Please enter a valid OTP");
} else {
user.isVerified = true;
const verifiedUser = await user.save();
res.json({
_id: verifiedUser._id,
name: verifiedUser.name,
email: verifiedUser.email,
token: generateToken(verifiedUser._id),
});
}
}});
const loginUser = expressAsyncHandler(async (req, res) => {
const { email, password } = req.body;
let verifiedUser;
let matchUserPassword;
const user = await User.findOne({ email });
if (user) {
verifiedUser = user.isVerified;
matchUserPassword = await user.matchPassword(password);
console.log(verifiedUser);
console.log(matchUserPassword);
}
if (user && (await user.matchPassword(password))) {
if (verifiedUser) {
res.json({
_id: user._id,
name: user.name,
email: user.email,
token: generateToken(user._id),
});
} else {
res.status(400);
throw new Error("Please verify the email!");
}
} else {
res.status(401);
throw new Error("Invalid email or password");
}});
I am also sharing the my schema
const mongoose = require("mongoose");
const bcrypt = require("bcryptjs");
const userSchema = mongoose.Schema(
{
name: {
type: String,
required: true,
},
email: {
type: String,
unique: true,
required: true,
},
password: {
type: String,
required: true,
},
mobile_number: {
type: Number,
required: true,
},
otp: {
type: Number,
required: true,
},
isOtpExpired: {
type: Boolean,
default: false,
required: true,
},
otpTime: {
type: Date,
default: new Date().getTime().toString(),
},
isVerified: {
type: Boolean,
default: false,
},
isAdmin: {
type: Boolean,
default: false,
required: true,
},
},
{
timestamps: {
createdAt: "created_at",
updatedAt: "modified_at",
},
}
);
userSchema.methods.matchPassword =
async function (enteredPassword) {
return await bcrypt.compare(
enteredPassword,
this.password
);
};
userSchema.pre("save", async function (next) {
if (!this.isModified) {
next();
}
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(
this.password,
salt
);
});
const User = mongoose.model("User", userSchema);
module.exports = User;
I want only the fields should be updated that I mentioned in my code not other just like password
2
Answers
If you want to update only specific fields in your code, I think you can use Mongoose’s select method when querying the user from the database like this:
This will ensure that only the fields isVerified, otpTime, otp, and isOtpExpired are returned from the database, and any other fields in the User schema will be ignored.
Similarly, when saving the user after updating isVerified, try use the select method to update only the isVerified field, like this:
This will update only the isVerified field in the database and ignore any other changes made to the User schema.
Hope this helps!
To update only specific fields in Mongoose, you can use the updateOne method with the $set operator. Here’s an example:
In this example, we only update the isVerified field of the user document. We create an update object that includes only the field we want to update, using the $set operator. We then use the updateOne method to update the document, passing in the _id of the user we want to update, the update object, and some options. The new option tells Mongoose to return the updated document. Finally, we return the updated fields in the response.
You can modify this example to update any other fields you need to update. Just make sure to use the $set operator to only update the specific fields you need.