I am trying to save a user to MongoDB as follows, but I am getting the error bcrypt Error: data and hash arguments required. I have checked the same error question asked by other Dev on StackOverflow but it doesn't help. I have attached the codes of the model file and router file.
User Model file
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const uSchema = new mongoose.Schema({
fullName: {
type: String,
required: true,
min: 4,
max: 30
},
email: {
type: String,
required: true,
trim: true,
unique: true,
index: true
},
hash_password: {
type: String,
required: true,
min: 6,
max: 12
},
role: {
type: String,
enum: ['user', 'admin', 'moderator'],
default: 'admin'
}
}, { timestamps: true });
uSchema.virtual('password')
.set(function (password) {
this.hash_password = bcrypt.hashSync(password, 10);
});
uSchema.methods = {
authenticate: function (password) {
return bcrypt.compareSync(password, this.hash_password);
}
}
module.exports = mongoose.model('User', uSchema);
User Router file
const express = require('express');
const router = express.Router();
const User = require('../models/user.model');
router.post('/login', (req, res) => {
});
router.post('/signin', (req, res) => {
User.findOne({ email: req.body.email })
.exec((error, user) => {
if (user) return res.status(400).json({
message: 'User already exists.'
});
const {
fullName,
email,
password
} = req.body;
const _user = new User({
fullName,
email,
password
});
_user.save((error, data) => {
if (error) {
return res.status(400).json({
message: 'Something went wrong'
});
} if (data) {
return res.status(201).json({
user: data
})
}
})
});
});
module.exports = router;
You can do it in the router file instead.
const bcrypt = require("bcrypt")
// ...
router.post('/signin', (req, res) => { // Change this to signup
User.findOne({ email: req.body.email })
.exec((error, user) => {
if (user) return res.status(400).json({
message: 'User already exists.'
});
const {
fullName,
email,
password
} = req.body;
const hashedPassword = bcrypt.hashSync(password, 10);
const _user = new User({
fullName,
email,
hashedPassword
});
_user.save((error, data) => {
if (error) {
return res.status(400).json({
message: 'Something went wrong'
});
} if (data) {
return res.status(201).json({
user: data
})
}
})
});
});
module.exports = router;
and delete the password virtual from the model.
Related
This is My User Model
const mongoose = require('mongoose')
const bcrypt = require('bcrypt');
const userSchema = mongoose.Schema({
contact: {
type: Number,
required: true,
},
email: {
type: String,
required: true,
unique: true
},
score: {
type: Number,
default:0,
},
password: {
type: String,
required: true,
},
role: {
type: String
},
blocked: {
type: Boolean, default: false
}
}, { timestamp: true }
)
userSchema.statics.hashPassword = function hashPassword(password){
return bcrypt.hashSync(password,10);
}
userSchema.methods.isValid = function(hashedpassword){
return bcrypt.compareSync(hashedpassword, this.password);
}
module.exports = mongoose.model('user',userSchema)
This is my Controller
const User = require('../models/user')
const Otp = require('../models/otp')
const jwt = require('jsonwebtoken')
const sendMail = require('../mail/mail')
const bcrypt = require('bcryptjs')
exports.getCheck = (req, res, next) => {
res.json({ msg: "All ok" })
}
exports.registerStudent = async (req, res) => {
// const x = await check(req,res,req.body.email);
const user = new User({
contact: req.body.phone,
email: req.body.email,
role: "student",
password: User.hashPassword(req.body.p1),
});
User.find({ email: req.body.email }, (err, users) => {
if (err) {
console.log("err in finding email ");
res.json({ msg: "some baler error!" });
}
if (users.length != 0) {
console.log("already user with this email");
res.json({ msg: "already user exist with this email!" });
}
else {
user.save((error, registeredUser) => {
if (error) {
console.log(error);
res.json({ msg: "some error!" });
}
else {
let payload = { subject: registeredUser._id }
let token = jwt.sign(payload, 'secretkey')
res.status(200).json({ token: token })
}
})
}
})
}
PLeasee HELP me out i'm getting confused
IGNORE
I ran into the same problem. 1. I saved my ATLAS_URI ID to a file called .env 2. My .env file was in the wrong directory, that's how the problem cause 3. Solution: I used "ls -a" command to make sure my .env file is in the same location as my server
IGNORE
PLeasee HELP me out i'm getting confused
I am building a user signup and login api and admin signup and login using express and currently I am testing in the postman, but somehow postman keeps return "error": "firstName is not defined" even though I posted firstname etc. here is my code, can anyone help me to explain it what is wrong? I saw so many videos using all different kinds of method, like generateAuthtakoken in the user.model or joi password library, it is just so overwhelming, can you help me to point to a direction as to how to use express to create ?
this is my user.model file:
const mongoose = require("mongoose");
const bcrypt = require("bcrypt");
const validator = require("validator");
const userSchema = new mongoose.Schema(
{
firstName: {
type: String,
required: true,
trim: true,
},
lastName: {
type: String,
required: true,
trim: true,
},
email: {
type: String,
required: true,
trim: true,
unique: true,
},
password: {
type: String,
required: true,
},
role: {
type: String,
enum: ["user", "admin"],
default: "user",
},
contactNumber: { type: String },
profilePicture: { type: String },
},
{ timestamps: true }
);
//static signup method
userSchema.statics.signup = async function (email, password) {
//validation
if (!firstName || !lastName || !email || !password) {
throw Error("All fields must be filled");
}
if (!validator.isEmail(email)) {
throw Error("Email is not valid");
}
if (!validator.isStrongPassword(password)) {
throw Error("Password is not strong enough");
}
const exists = await this.findOne({ email });
if (exists) {
throw Error("Email already in use");
}
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(password, salt);
const user = await this.create({ email, password: bcrypt.hash });
return user;
};
//static login method
userSchema.statics.login = async function (email, password) {
if (!firstName || !lastName || !email || !password) {
throw Error("All fields must be filled");
}
const user = await this.findOne({ email });
if (!user) {
throw Error("Incorrect Email");
}
const match = await bcrypt.compare(password, user.password);
if (!match) {
throw Error("Incorrect password");
}
return user;
};
module.exports = mongoose.model("User", userSchema);
this is my controller file:
const User = require("../models/user");
const jwt = require("jsonwebtoken");
const createToken = (_id) => {
jwt.sign({ _id }, process.env.JWT_SECRET, { expiresIn: "3d" });
};
//login user
const loginUser = async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.login(email, password);
// create token
const token = createToken(user._id);
res.status(200).json({ email, token });
} catch (error) {
res.status(400).json({ error: error.message });
}
res.json({ msg: "login user" });
};
//signup user
const signupUser = async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.signup(email, password);
// create token
const token = createToken(user._id);
res.status(200).json({ email, token });
} catch (error) {
res.status(400).json({ error: error.message });
}
res.json({ msg: "login user" });
};
module.exports = { signupUser, loginUser };
and my router file:
const express = require("express");
const router = express.Router();
const { signupUser, loginUser } = require("../controller/auth");
//login route
router.post("/login", loginUser);
//signup route
router.post("/signup", signupUser);
module.exports = router;
where exactly do you get this error. Please provide full details to regenerate this error.
But as i could guess
In your static login method you do not need firstName and LastName.
In your signup user method you should be passing those missing required db fields as in your model.
I'm trying to be able to delete a user if they choose to delete their account. I'm not sure how it's properly done. Here's the code for the delete function. I've looked at other StackOverflow solutions but I haven't been able to grasp the concept just yet. can anyone help?
const { validationResult } = require('express-validator')
const User = require('../modelSchema/User')
const mongo = require('mongodb')
const signUp = (req, res) => {
const errors = validationResult(req)
if(!errors.isEmpty()) return res.status(400).json({ errors: errors.array()})
//new instance of user
const user = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password })
//save the user
user.save()
.then(data => {
res.json(data)
res.send('User added successfully!')
console.log(data)
})
.catch(err => {
res.status(400).json(err)
})
}
const deleteUser = (req, res) => {
let id = req.params.id;
User.get().createCollection('user', function ( col) {
col.deleteOne({_id: new mongo.ObjectId(id)});
});
res.json({ success: id })
res.send('User Deleted Successfully!')
.catch(err => {
res.status(400).json(err)
})
}
module.exports = { signUp, deleteUser }
here are the routes that I'm using
const express = require('express');
const { check } = require('express-validator')
const { signUp, deleteUser } = require('../controllers/users');
const router = express.Router();
router.post('/signup', [
check('name', 'Please Enter your Name').not().isEmpty(),
check('email', 'Please Enter your Email').isEmail(),
check('password', 'Please Enter your Password').isLength({ minLength: 6})
], signUp)
router.delete('/delete/:id', deleteUser)
module.exports = router;
and here's my schema
const mongoose = require('mongoose');
let userSchema = new mongoose.Schema({
name: { type: 'string', required: true},
email: { type: 'string', required: true},
password: { type: 'string', required: true},
date: { type: Date, default: Date.now}
})
module.exports = mongoose.model('user', userSchema)
Update your delete function as below
const deleteUser = async (req, res) => {
const { id } = req.params;
const user = await User.findByIdAndDelete(id);
if (!user) {
return res.status(400).json("User not found");
}
res.status(200).json("User deleted successfully");
};
findByIdAndDelete takes an ObjectId of a user to be deleted. If the user exist, it'll delete the user and return user document, else return null;
Matching User while logging in
const LocalStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// Load User Model
const User = require('../models/User');
module.exports = function(passport) {
passport.use(
new LocalStrategy({ username: 'username' }, (username,
password, done) => {
// Match User
User.findOne({ username: username })
.then(user => {
if (!user) {
return done(null, false, { message: 'username is
not registered' });
}
// Match Password
bcrypt.compare(password, user.hashedPassword, (err,
isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message:
'Password incorrect' });
}
});
})
.catch(err => console.error(err))
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
}
Validation pass while registering user
User.findOne({ username: username })
.then(async user => {
if (user) {
//User exists
errors.push({ msg: "username has already taken" });
res.render('register', {
errors,
username,
password
});
} else {
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password,
salt);
const newUser = new User({
username: username,
password: hashedPassword,
});
newUser.save()
.then(user => {
// res.status(201).json(user);
req.flash('success_msg', 'You are now
registered')
res.redirect('/users/login');
})
.catch(err => console.log(err));
}
})
.catch(err => {
console.log(err);
})
}
../models/User
// Importing modules
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new mongoose.Schema({
username: {
type: String,
lowercase: true,
unique: true,
// required: [true, "can't be blank"],
match: [/^[a-zA-Z0-9]+$/, 'is invalid'],
index: true
},
password: {
type: String,
required: true
},
Date: {
type: Date,
default: Date.now
}
}, { timestamps: true });
// export userschema
module.exports = mongoose.model('User', UserSchema);
why is it showing the error "Error: Illegal arguments: string, undefined". The same error was throwing when saving the password as hash in DB and now the same error throwing while comparing the hashed password. I checked the documentation, the format is the same but I think there is a syntactical error.
In the definition of the User data type, only the fields username and password exist. There is no field hashedPassword. However, you're trying to access this field in the line saying bcrypt.compare(password, user.hashedPassword ....
You're stroring the hased password in the password field here:
const newUser = new User({
username: username,
password: hashedPassword,
});
So later, you also need to read it from the password field:
bcrypt.compare(password, user.password ...
*I can create new account and also i can login but when i am going to logout that time i will logout but if i am try to login with same email and password but i cannot able to login it is showing me jsonwebtoken error -> {"name":"JsonWebTokenError","message":"jwt must be provided"} *
register.js
This is my register.js file code
app.get("/register", (req, res) => {
// res.send('Hello Arunesh')
res.render("register");
});
app.post("/register", async (req, res) => {
try {
const password = req.body.password;
const cPassword = req.body.cPassword;
if (password === cPassword) {
const registerData = new Register({
firstName: req.body.firstName,
lastName: req.body.lastName,
phone: req.body.phone,
gender: req.body.gender,
email: req.body.email,
age: req.body.age,
password: req.body.password,
confirmPassword: req.body.cPassword,
});
const token = await registerData.generateAuthToken();
console.log('Register Token : ',token);
res.cookie('jwt', token,{
httpOnly:true
})
const register = await registerData.save();
console.log(register);
res.status(201).render("index");
} else {
res.send("Password are not match");
}
} catch (e) {
res.status(400).send(e);
}
});
login.js
app.get("/login", (req, res) => {
res.render("login");
});
app.post("/login", auth,async (req, res) => {
try {
const email = req.body.email;
const password = req.body.password;
const userEmail = await Register.findOne({ email: email });
const isMatch = await bcrypt.compare(password, userEmail.password);
const token = await userEmail.generateAuthToken();
res.cookie('jwt', token,{
expires:new Date(Date.now()+30000000),
httpOnly:true
})
console.log('Login Token : ',token);
console.log(isMatch);
if (isMatch) {
res.status(201).render("index");
} else {
res.send("Invalid password or email");
}
} catch (e) {
res.status(400).send(e);
}
});
Logout.js
app.get('/logout', auth,async (req, res)=>{
try{
// console.log(req.user);
// Logout for single user
req.user.tokens = req.user.tokens.filter((authToken)=>{
return authToken.token != req.token;
})
// logout from all device
// req.user.tokens = [];
res.clearCookie("jwt");
await req.user.save();
res.render('login');
}catch(e){
console.log(e);
}
})
auth.js
const jwt = require('jsonwebtoken');
const Register = require('../models/registers');
const auth = async (req, res, next)=>{
try{
const token = req.cookies.jwt;
const verifyUser = jwt.verify(token, process.env.SECRET_KEY);
const user = await Register.findOne({_id:verifyUser._id, 'tokens.token':token})
req.token = token;
req.user = user;
next()
}catch(e){
res.send(e)
}
}
module.exports = auth;
**
generateAuthToken
**
registerSchema.methods.generateAuthToken = async function () {
try {
const token = jwt.sign({ _id: this._id.toString() },process.env.SECRET_KEY);
this.tokens = this.tokens.concat({token:token})
await this.save();
return token;
} catch (e) {
console.log(e);
}
};
**
Schema
**
const mongoose = require("mongoose");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const registerSchema = new mongoose.Schema({
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
phone: {
type: Number,
required: true,
unique: true,
},
gender: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
age: {
type: Number,
required: true,
},
password: {
type: String,
required: true,
},
confirmPassword: {
type: String,
required: true,
},
tokens: [
{
token: {
type: String,
required: true,
},
},
],
});
/********************************************
* Generate Token
********************************************/
registerSchema.methods.generateAuthToken = async function () {
try {
const token = jwt.sign({ _id: this._id.toString() },process.env.SECRET_KEY);
this.tokens = this.tokens.concat({token:token})
await this.save();
return token;
} catch (e) {
console.log(e);
}
};
/********************************************
* Password Hash
********************************************/
registerSchema.pre("save", async function (next) {
if (this.isModified("password")) {
this.password = await bcrypt.hash(this.password, 10);
this.confirmPassword = await bcrypt.hash(this.password, 10);
}
next();
});
const Register = new mongoose.model("Register", registerSchema);
module.exports = Register;
you use auth middleware in /login route, this error happens when the coming token is null or empty ,remove auth middleware from the route like this, I hope the problem is solved with my answer
app.post("/login" , async (req, res) => {...