Express JS query Error Handling not working - mysql

this is my first post on Stackoverflow, so please be kind.
I have a huge problem, which I couldn't fix by googling (which is pretty rare).
I want to create a simple error handling in my query, but it won't work.
Here's the code:
pool.query("SELECT password_hash FROM User WHERE email = ?",
req.body.EMailLogin, (error, results, fields) => {
if(error) {
// It executes the if aswell as the else statement and I dont know why (if(error) seems to be ignored even if its true)
} else {
// And then it crashes here, because password_hash is undefined
let hash = results[0].password_hash;
bcrypt.compare(req.body.PasswordLogin, hash, function(err, result) {
if (result == true) {
ses.user = req.body.EMailLogin;
req.session.cookie.expires = false;
req.session.save(() => {
return res.redirect('/index');
});
} else {
res.render(); // My Page for Wrong Password (ignore this)
}
});
}
}
);

Throw the error inside the if
if(error) {
throw error;
} else {
I think that the error is how you're passing the parameter, it should be an array:
pool.query("SELECT password_hash FROM User WHERE email = ?",
[req.body.EMailLogin],
I hope this fixes your problem.

You missed to check weather query return data or not and also you can pass values either using object or array(in your case, should be array)
pool.query("SELECT password_hash FROM User WHERE email = ?", [req.body.EMailLogin],
(error, results, fields) => {
if (error) {
// any error like wrong query, connection closed, etc.
// It executes the if aswell as the else statement and I dont know why (if(error) seems to be ignored even if its true)
} else if (results.length === 0) {
// email not found in database
// My Page for Wrong Email ???
} else {
// And then it crashes here, because password_hash is undefined
let hash = results[0].password_hash;
bcrypt.compare(req.body.PasswordLogin, hash, function (err, result) {
if (result == true) {
ses.user = req.body.EMailLogin;
req.session.cookie.expires = false;
req.session.save(() => {
return res.redirect('/index');
});
} else {
res.render(); // My Page for Wrong Password (ignore this)
}
});
}
}
);

Related

res.send() not working for two different callbacks

I am unable to get res.send() to work for all the callbacks, an idea I had was to move the return res.send({ error, success }); to a callback placed above but then it doesn't do the potential error/success messages for below.
I tried doing it a different way where I used a function like createUser() that used a callback to return an error/success message but also wasn't able to get it to work. Is there anything that can point me to how I can make this work properly?
A friend suggested using await and async callbacks, but when searching it I wasn't too familiar to understand how it properly works.
app.post('/create', function(req, res) {
// -- Default Variables
let error = "";
let success = "";
let formData = req.body.formData;
if (formData.userName, formData.userPass, formData.userEmail) {
console.log(formData);
conn.query("SELECT COUNT(userId) AS rowCount FROM users WHERE userName = ?", [formData.userName], function(error, results, fields) {
if (results[0].rowCount == 0) {
conn.query("INSERT INTO users ( userName, userEmail, userPass ) VALUES ( ?, ?, ? )", [ formData.userName, formData.userEmail, formData.userPass ], function(error, results, fields) {
if (results.affectedRows >= 1)
success = "Your account has successfully been created!";
else
error = "Unexpected error occured, please try again!";
});
} else { error = "You already have an account!"; }
});
} else {
error = "Please make sure all fields are entered correctly!";
}
// -- Return
return res.send({ error, success });
});
conn.query calls an async callback and return res.send({ error, success }); returns immediately. The values changed in the asynchonous callback are in a closure, that executes only after return res.send({ error, success }); already returned the value. So the only error that might show up is the only one in else branch.
Try rewriting it with promises:
app.post('/create', function x(req, res) {
return new Promise(function(resolve, reject){
let error = "";
let success = "";
let formData = req.body.formData;
if (formData.userName && formData.userPass && formData.userEmail) {
console.log(formData);
conn.query("SELECT COUNT(userId) AS rowCount FROM users WHERE userName = ?", [formData.userName], function(error, results, fields) {
if (results[0].rowCount == 0) {
conn.query("INSERT INTO users ( userName, userEmail, userPass ) VALUES ( ?, ?, ? )", [ formData.userName, formData.userEmail, formData.userPass ], function(error, results, fields) {
if (results.affectedRows >= 1)
success = "Your account has successfully been created!";
else
error = "Unexpected error occured, please try again!";
resolve({ error, success });
});
} else {
error = "You already have an account!";
resolve({ error, success }); }
});
}
else{
error = "Please make sure all fields are entered correctly!";
resolve({ error, success });
}
});
});
Even though I know that always resolving is not a clean way to use Promises. You should consider changing your API return proper errors with appropriate HTTP error codes to client.
I can see multiple issues with your code:
It's actually working, BUT it's logically incorrect, returning your empty error and success variables immediately, without waiting for your queries to finish.
You have some conflict with your error variable, consider renaming to something that doesn't overlap with your outside declaration. While it does work, it gives you room for confusion.
Your if has incorrect conditions and logical operators.
Here's a quick fix, but not considering that this can be much much cleaner. Also some quick tips:
Return/Terminate early if possible.
Avoid very long lines to make your code much easier to read
app.post('/create', function(req, res) {
// -- Default Variables
let error = "";
let success = "";
const formData = req.body.formData;
const {
username,
userPass,
userEmail
} = formData;
// Avoid too much nested code, terminate/Return early if possible.
if (!userName || !userPass || !userEmail) {
error = "Please make sure all fields are entered correctly!";
return res.send({ error, success });
}
conn.query("SELECT COUNT(userId) AS rowCount FROM users WHERE userName = ?", [userName], function(error, results, fields) {
if (results[0].rowCount == 0) {
const parameters = [ userName, userEmail, userPass ];
// Avoid very long lines. It becomes harder to read (TIP: Consider using lint)
conn.query("INSERT INTO users ( userName, userEmail, userPass ) VALUES ( ?, ?, ? )", parameters , function(error, results, fields) {
if (results.affectedRows >= 1) {
success = "Your account has successfully been created!";
} else {
error = "Unexpected error occurred, please try again!";
}
res.send({ error, success }); return;
});
} else {
error = "You already have an account!";
res.send({ error, success }); return;
}
});
});

if -else condition is not working in node js

What I am trying to implement is that after logged in ,system will check user's role and redirect the user accordingly.
1- Admin
2- User
role field is integer type. below is my code
router.post('/signin', function (req, res, next) {
session_store = req.session;
req.assert('Emailid', 'Please fill register Email Address').notEmpty();
req.assert('Emailid', 'Email not valid').isEmail();
req.assert('password', 'Please fill the Password').notEmpty();
var errors = req.validationErrors();
if (!errors) {
Emailid = req.sanitize('Emailid').escape().trim();
password = req.sanitize('password').escape().trim();
var query = 'select * from userdetails where Emailid=? and password=?';
var sql='select role from userdetails where Emailid=?'
db.query(query, [Emailid, password], function (err, rows) {
if (err) {
var errornya = ("Error Selecting : %s ", err.code);
console.log(err.code);
req.flash('msg_error', errornya);
res.redirect('/login-Form');
} else {
if (rows.length <= 0) {
req.flash('msg_error', "Wrong email address or password. Try again.");
res.redirect('/login-Form');
}
else {
session_store.is_login = true;
session_store.user = Emailid;
db.query(sql, Emailid, function (err, result) {
if (err) throw err
else {
if (result == 1) { // facing issue here. It is directly going to else block though the user role is 1 in the mysql table
console.log(result)
res.redirect('/Dashboard');
}
else {
res.redirect('/Audit-Record');
}
}
});
}
}
});
}
else {
res.redirect('/login-Form');
}
});
I guess I am making some mistake while comparing the result value. Can anyone of you please check and let me know where I am going wrong.
Thanks in advance!
The issue got resolved. Actually I was comparing in wrong way. we need to write it like this
else {
session_store.is_login = true;
session_store.user = Emailid;
db.query(sql, Emailid, function (err, result) {
if (err) throw err
else {
**if (result[0].role == 1)** {
console.log(result)
res.redirect('/Dashboard');
}
else {
res.redirect('/Audit-Record');
}
}
});

Catching exception errors when logging in via NodeJS + MySQL

Recently I've been trying to learn NodeJS to set up a log in process, so I decided to write all the errors and make exceptions for them. My question is how can I make sure each if is responsible for each error code. I haven't worked with try and catch before so this is a new territory for me.
Also is it better to use multiple try-catch or should I consider using 1 block where I can use a switch for example (used else if here as a quick example).
Table with Status errors
0 - no connection with database.
1 - connection ok but we dont have any privileges for access to the
database or something like that.
2 - all ok.
3 - ok, but no data found in query results.
4 - error getting results of query.
5 - other.
module.exports = (username,password,connection ) => {
var data ={
"Status" : null,
"Data" : {} //JSON results inside of Data Json
}
try{
connection.query("SELECT id FROM players", function (error, results, fields) {
if (error){
data.Status = 0;
data.Data= "No connection can be established with the database";
return data
}
else if(error){
data.Status = 1;
data.Data= results + "Connection OK but no priviliges";
return data
}
else if(error){
data.Status = 2;
data.Data=results + "connection running";
return data
}
else if(error){
data.Status = 3;
data.Data=results + "No data found in query results";
return data
}
else if(error){
data.Status = 4;
data.Data=results;
return data
}
else if(error){
data.Status = 5;
data.Data=results;
return data
}
});
}
catch(e){
console.log(e);
data.Status= 2;
data.Data=null;
return data;
}
};
Welcome to async programming, your try/catch block won't do anything for any I/O process, all errors are handled by error object in the callback function. (unless you use the last async/await ES6 pattern)
connection.query("SELECT id FROM players", function (error, results, fields) {
if (!error) { // no error, return results
data.status = 2;
data.Data = results;
return data;
}
// for all error code, please check mysql library document
// https://www.npmjs.com/package/mysql#error-handling
if (error.code === 'ER_ACCESS_DENIED_ERROR') {
data.Status = 1;
data.Data=results;
return data
}
// handle any other error codes
// if ....
});
Edit: please note that, your exported function in module.exports won't return anything because you are calling database query which is an async I/O process and requires another callback function to get the data returned by database
This will never work as expected :
if (error){
console.log("I'm the error");
return;
} else if(error){
console.log("I will never be display on error because of return in the first if");
}
Should be :
if (!error){
// No error
} else if(error === 'something'){
// Error something
} else if ....
// Other type of error
} else {
// Unknown error
}
You can use a switch instead in a more elegant way :
const data = { Status: 1, Data: results }
if(error) {
switch(error.code) {
case 'ER_ACCESS_DENIED_ERROR' :
data.Satus = 2;
return data;
...
}
}
return data;

Custom express-validator

My custom-validator always return true although when result is not undefined and i have returned false in that case
const validatorOptions = {
customValidators: {
not_exist: (inputParam) => {
let qry = 'select * from Users where email = ?';
let exist= db.query(qry, inputParam, (err, result) => {
if (err)
throw err;
if (result) {
console.log("Exist");
return false;
} else
return true;
});
return exist;
}
}
};
I tried using Promise, but still it's not working.
const validatorOptions = {
customValidators: {
isUniqueEmail: (email) => {
function getRecord(email) {
return new Promise(function(resolve, reject) {
let qry = 'select * from Users where email = ?';
db.query(qry, email, (err, result) => {
if (err)
reject(err);
else {
resolve(result);
}
});
});
};
getRecord(email).then(function(res) {
return (res.length == 0);
}).catch((err) => { throw err; });;
}
}
};
req.checkBody('email', 'Email already exist').isUniqueEmail();
That is because you're returning the variable exist which is equal to db.query() (and always a truthy value).
I had some questions about this code (because I don't see how it could run in the current state):
Seems odd to have customValidators as a child to validatorOptions, is there a reason for this?
Is there a reason you're mixing camel and snake case?
Do you think the custom validator method name could be more descriptive as to its' purpose, such as isUniqueEmailAddress?
Why isn't the SQL statement concatenating the argument into the
Do you think this code should implement some SQL input cleansing for security reasons?
Does db.query() really expect 3 arguments??? (I would think it just needs SQL and callback)
Since db.query() is performing an asynchronous operation, have you considered using Promises?

promise returns undefined while calling from two different mysql queries

I Have two mysql queries that runs with promise.
The first one is updates information on a mysql table and then resolves the issue and calls the next mysql query. The problem is that, when it calls the next mysql query the promise returns UNDEFINED and I am not sure why. When I console.log it out in my node js server post request, it gives undefined. I documented on the code which areas are problems.
UpdateUserPath = (data) => new Promise((resolve,reject)=>{
data.UPDATE_DT = getDateTime();
db.query('UPDATE path UPDATE_DT = ? where Owner = ?',
[data.UPDATE_DT, data.Owner], function(err,results,fields){
if(err){
reject('Could not update user path');
}else{
if(results.affectedRows > 0){
data.ID = null;
data.UPDATE_DT = null;
// The problem is here, when this gets resolved it calls the other function SaveUserPath
resolve(saveUserPath(data));
}else{
reject('Could not update user path');
}
}
});
});
saveUserPath = (data) => new Promise((resolve, reject) => {
db.query('INSERT INTO path SET ?', data, function (error, results, fields) {
if (error) {
reject('Could not insert path');
}else{
var Id = results.insertId;
db.query('UPDATE path SET ORIG_ID = ? where ID = ?',[Id, Id], function(err,results,fields){
if(err){
reject('Could not insert row to path table - saveuserpath');
}else{
if(results.affectedRows > 0){
// THIS INFORMATION HERE IS UNDEFINED
return resolve(results[0]);
}else{
reject('Could not update path');
}
}
});
}
});
});
In the server it gets called like this.
getUserPath(req.session.userid).then((path_data)=>{
path_data.status = 1;
UpdateUserPath(path_data).then((result)=>{
console.log(result); // THIS IS UNDEFINED
});
});
I am wondering if resolve(saveUserPath(data)); is the right way to call another promise which is not outside in the server.
I was thinking of just doing it this way.
UpdateUserPath(path_data).then((result)=>{
saveUserPath(result).then((result_save) => {
console.log(result_save); // THIS MIGHT WORK
});
});
But why is the normal way wrong.
I have several guesses why it isn't working, but there are a number of things wrong such that it's better to just clean up the code to a much better design.
When combining multiple asynchronous callback-driven operations in an otherwise promise-based interface, you really want to promisify the underlying functions at their lowest level and then you can implement all your control flow and error handling using the benefits of promises. I think that will also make your problem go away and probably fix a couple other bugs too.
// promisify db.query()
// if a promisified interface is built into your database, use that one instead
db.queryP = function(q, d) {
return new Promise((resolve, reject) {
db.query(q, d, (err, results, fields) => {
if (err) {
reject(err);
} else {
resolve(results);
}
});
});
}
UpdateUserPath = function(data) {
data.UPDATE_DT = getDateTime();
let q = 'UPDATE path UPDATE_DT = ? where Owner = ?';
return db.queryP(q, [data.UPDATE_DT, data.Owner]).then(results => {
if (results.affectedRows > 0) {
data.ID = null;
data.UPDATE_DT = null;
return saveUserPath(data);
} else {
throw new Error('Could not update user path');
}
});
}
saveUserPath = function(data) {
let q = 'INSERT INTO path SET ?'
return db.queryP(q, data).then(results => {
let q2 = 'UPDATE path SET ORIG_ID = ? where ID = ?';
var Id = results.insertId;
return db.queryP(q2, [Id, Id]).then(results2 => {
if (results2.affectedRows > 0) {
return results2[0];
} else {
throw new Error('Could not update path');
}
});
});
}
getUserPath(req.session.userid).then(path_data => {
path_data.status = 1;
return UpdateUserPath(path_data);
}).then(result => {
// process result here
}).catch(err => {
// process error here
});