Condition if/else don't work like expected in nodejs - javascript

I'm creating a simple api witch verify if the username and/or password are in the DB and if they are correct.
When I post correct data, it works. When I post a wrong password, it also works. But when I post a wrong username, my condition don't jump to the else. If the username is wrong, it means it is not in the DB. But here, it is like if it was in the DB, but he is not, so I get an error : " TypeError: Cannot read properties of undefined (reading 'Username') "
Here the code
app.post('/login', function(req, res) {
(async () => {
const bcrypt = require('bcrypt')
try {
username = req.query.username
password = req.query.password
let salt = await bcrypt.genSalt(10)
let hash = await bcrypt.hash(password, salt)
db_conn.getConnection( (err, conn) => {
if(err) throw err;
conn.query("SELECT * FROM mod803_appusers WHERE Username=? ", [username], (err, rows) => {
//Problem here : when I put a wrong password, it's ok, this condition works because there is a password, and if bcrypt.compare is true, it sends response, but if it's false, it sends 'Wrong password'.
//But if the Username is Wrong, it means there is no username in the DB. So here, I want this condition jump to the else : 'Incorrect username' but it doesn't.
if(rows[0]['Username'] && rows[0]['Password']) {
bcrypt.compare(password, rows[0]['Password'], function(err, result) {
if(result){
res.send({"table": rows});
} else {
res.send("Wrong password");
}});
} else {
res.send('Incorrect username');
}
})
})
} catch (error) {
console.log(error.message)
}
})()
})
Thanks

Related

Implementation of bcrypt/async gives query-result of undefined

The mysql query always returns undefined and I don't know whats wrongs. It used to work before I added the async await to the functions but that used to return an error in the terminal because bcrypt is an async function. Could someone help me with this? Here is my code
app.post('/login', async function(req, res) {
let username = req.body.username;
let password = req.body.password;
if (username && password) {
connection.query('SELECT username, password, email FROM accounts WHERE username = ?', [username], async function(err, result, fields) {
if (result.length > 0) {
try {
if(await bcrypt.compare(password, result.password)) {
req.session.loggedin = true;
req.session.username = username;
res.redirect('/');
}
else {
res.send('Incorrect Username and/or Password!');
}
}
catch (err) {
//res.status(500).send();
res.send('Something wrong happened');
console.log(err);
}
} else {
res.send('Incorrect Username and/or Password!');
}
res.end();
});
} else {
res.send('Please enter Username and Password!');
res.end();
}
});

Cannot set headers after they are sent to the client using nodejs mysql

What I am attempting to do is write a statement to check if email exists in my mysql database when a user registers. In postman it sends me the correct error message of "user already taken" however the server crashes after and displays "cannot set headers after they are sent to the client." I have read similar posts but did not help.
//The following code is in my user.service.js file:
const pool = require("../../config/database");
module.exports = {
//Create new user
createUser: (data, callBack) =>{
pool.query(
`insert into registration(name, email, password, confirm_password)
values(?,?,?,?)`,
[
data.name,
data.email,
data.password,
data.confirm_password
],
(error, results, fields) =>{
if(error){
return callBack(error);
}
return callBack(null, results);
}
);
}
}
//The following code is in my user.controller.js file:
const {
createUser,
} = require("./user.service");
const pool = require("../../config/database");
module.exports = {
createUser: (req, res) =>{
const body = req.body;
const salt = genSaltSync(10);
pool.query('SELECT email FROM registration WHERE email = ?', [body.email], (error, results) =>{
if(error){
console.log(error);
}
if(results.length > 0){
return res.status(400).json({
message: 'User already taken'
})
}
})
createUser(body, (err, results) => {
if(err){
console.log(err);
return res.status(500).json({
success:0,
message:"Error in database connection"
});
}
return res.status(200).json({
success: 1,
message: `User ${results.insertId} signed up successfully`,
data: results
});
});
}
}
//The following code is from user.router.js file:
const {
createUser,
} = require("./user.controller");
const router = require("express").Router();
router.post("/signup", createUser);
module.exports = router;
In your createUser function that is executed on the post request you are doing two things. First you check whether a user with the provided email exists and, second, you create a user. However, those functions are not executed consecutively, instead they are running simultaneously and thus create a race condition.
So going off on your example, if the email check query SELECT email FROM registration WHERE email = ? is faster and the user already exists, it will respond with:
return res.status(400).json({
message: 'User already taken'
})
but the createUser function (below) is still running and once it is finished, it will try to also send a response. Therefore, you are presented with an application crash in the console even though in the postman you can see the response stating that the user already exists.
In order to fix this error you should execute the createUser function only if the results.length is 0 inside the callback provided to the email check query, like so:
createUser: (req, res) => {
const body = req.body;
const salt = genSaltSync(10);
pool.query('SELECT email FROM registration WHERE email = ?', [body.email], (error, results) =>{
if(error){
console.log(error);
}
if(results.length > 0){
return res.status(400).json({
message: 'User already taken'
})
}
createUser(body, (err, results) => {
if(err){
console.log(err);
return res.status(500).json({
success:0,
message:"Error in database connection"
});
}
return res.status(200).json({
success: 1,
message: `User ${results.insertId} signed up successfully`,
data: results
});
});
})
}
Now you execute the createUser function only if a user with the provided email doesn't exist, which effectively removes the race condition between the two functions.

Node js MongoDB login system database values undefined

I am currently working on a login system with Nodejs, Express & MongoDB. Everything works except the values in the database are coming up as undefined. At the two console.log statements where "database ___" is stated, the result is undefined. Not too sure why, from some testing it seems that the user inputted values work fine so I don't know why it's returning undefined.
app.post("/login", (req, res) => {
//Get user fields
const userEmail = req.body.loginEmail;
const userPass = req.body.loginPassword;
//Is user in database?
User.find({ email: userEmail }, (err, user) => {
console.log("database email: " + user.email)
if (!err) {
//Compare password to database password
bcrypt.compare(userPass, user.password, (err, result) => {
console.log("database password: " + user.password);
//If user pass in database, check if verified & redirect to success
if (userPass === user.password) {
if (user.isVerified) {
res.redirect("/success");
} else {
res.send(
"You are not verified. Please check your email to access your account."
);
}
} else {
res.send("Incorrect password");
}
});
} else {
res.send(err);
}
});
});
Mongoose will return an array as the second argument to the callback function when you use find(). If you use findOne() a single document will be returned instead.

Cannot set headers after they are sent to the client error

I have a login form that authenticates using postgresql I'm trying to check if users exists then redirect the client to the other page. The code is:
app.post('/login', (req, res) => {
var Enteredusername = req.body.username;
var Enteredpassword = req.body.password;
pool.query("SELECT * FROM tbl_users WHERE username = $1 AND password = $2", [Enteredusername, Enteredpassword], (err, result) => {
if (err) return console.log('error in query', err);
// need to check if user exists
let user = (result.rows.length > 0) ? result.rows[0] : null;
if (!user) {
req.flash('notify', 'This is a test notification.')
res.render('login', {
messages: req.flash('Username or Password is incorrect !')
});
return res.redirect('/login')
}
res.redirect('/posts')
});
});
And I got the error:
_http_outgoing.js:470
throw new ERR_HTTP_HEADERS_SENT('set');
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client.
How Can I fix it?
It's the async behavior of javascript res.redirect('/posts') is executed before req.flash and res.render you can hack it like this :
req.session.userId = Enteredusername;
if (!user) {
req.flash('notify', 'This is a test notification.')
res.render('login', {
messages: req.flash('Username or Password is incorrect !')
});
return res.redirect('/login')
}else{
return res.redirect('/posts')
}

Update user information

Tried this for updating user information , only phone number but it's not getting update.
router.post('/edit', checkAuth, function (req, res, next) {
console.log(req.userData.userId)
User.update({_id: req.userData.userId}, {$set:req.userData.phoneNo}, function (err){
if (err) {
console.log(err);
}
res.status(200).send(req.userData);
});
});
My user controller const mongoose = require ('mongoose');
const User = mongoose.model('User');
module.exports.register = (req, res, next) =>{
var user = new User();
user.fullName = req.body.fullName;
user.email = req.body.email;
user.password = req.body.password;
user.phoneNumber = req.body.phoneNumber;
user.save((err, doc) =>{
if(!err)
res.send(doc);
else{
if (err.code == 11000)
res.status(422).send(["Entered duplicate email address. Please check"]);
else
return next(err);
}
});
}
And then I am authenticating by passing jwt on this field
phoneNo: user[0].phoneNumber
The auth-token verifies and decode the fields
const token = req.headers.authorization.split(" ")[1];
const decoded = jwt.verify(token, process.env.JWT_KEY)
req.userData = decoded;
Update is not working and getting error message Invalid atomic update value for $set. Expected an object, received string .
first of all, you should use PATCH-method - because you are updating only one item in existed object, in body you should send id of user and new value of certain value. If you use mongoose you can try it
User.findOneAndUpdate({ _id: id }, updatedItem, { new: true }, (err, doc) => {
if (err) return res.send(err.message)
if (doc) return res.send(doc);
})
const id = req.body._id;, if you dont use mongoose you should try findAndModify method
Your code
User.update({_id: req.userData.userId}, {$set:req.userData.phoneNo}
Correct code:
User.update({_id: req.userData.userId}, {$set:{phoneNumber:req.userData.phoneNo}}
Try this method:
User.findByIdAndUpdate(req.userData.userId, { $set:{phoneNumber:req.userData.phoneNo}}, { new: true }, function (err, user) {
if (err) console.log(err);
res.send(user);
});

Categories