I'm working on a project where I'm creating the login and registration functions of the website. Registration is working but in the login section, the given password and the password stored in the database is not getting compared and a error is coming user.isValidPassword is not a function
. Although the function is declared in the user.model.js file but still the function is not working.
user.controller.js -
import userModel from '../models/user.model.js';
import * as userService from '../services/user.service.js'
import { validationResult } from 'express-validator';
export const createUserController = async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
try {
const user = await userService.createUser(req.body);
const token = await userModel.generateJWT;
res.status(201).send(user);
} catch (error) {
res.status(400).send(error.message)
}
}
export const loginUserController = async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
try {
const { email, password } = req.body;
const user = await userModel.findOne({ email }).select('+password');
if (!user) {
return res.status(401).json({
errors: "Invalid credentials"
})
}
const isMatch = await user.isValidPassword(password);
if (!isMatch) {
return res.status(401).json({
errors: "Invalid password"
})
}
const token = user.generateJWT();
res.status(200).json({user,token});
}
catch (error) {
res.status(400).send(error.message)
}
}
user.model.js -
import mongoose, { Types } from 'mongoose';
import bcrypt from "bcrypt";
import jwt from "jsonwebtoken"
const userSchema = new mongoose.Schema({
email:{
type: String,
required: true,
unique: true,
trim: true,
lowercase: true,
minLength: [6, "Email must be atleast 6 characters long."],
maxLength: [50, "Email can't be more than 50 characters long."]
},
password:{
type: String,
select: false,
}
})
userSchema.statics.hasPassword = async function (password) {
if (!password) {
throw new Error("Password is required");
}
return await bcrypt.hash(password, 10);
};
userSchema.method.isValidPassword = async (password) => {
return await bcrypt.compare(password, this.password)
}
userSchema.methods.generateJWT = function () {
return jwt.sign({email: this.email}, process.env.JWT_SECRET);
}
const User = mongoose.model('user', userSchema);
export default User;
When I'm sending a post request with
{
"email": "[email protected]",
"password": "thisistestpassword"
}
as raw in body at http://localhost:3000/users/login
I'm getting user.isValidPassword is not a function
Schema method is not implemented correctly: you need to use either Schema.methods
or Schema.method()
, and you shouldn't use arrow functions for declaring methods, because they wont' have access to the mongoose document (this
) (see: Instance methods).
So, change your method like this:
userSchema.methods.isValidPassword = async function (password) {
return await bcrypt.compare(password, this.password)
}