Getting Async Await Error and blank value in Array - mysql

I am getting the below error:
SyntaxError: await is only valid in async function
Also I got the blank array "console.log(userTasklist)".
const mysql = require('mysql2/promise');
// create the connection to database
const connection = async ()=> {
return await mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'whosin'
})
}
exports.allUserList = async (req, res) => {
const db = await connection()
let userID = req.params.userid;
const userdata = await db.query('SELECT name, user_id, employee_code FROM users WHERE under_gh = ?', [userID]);
//console.log(userdata[0])
if (userdata[0] && userdata[0].length > 0) {
let userTasklist = [];
userdata[0].map((datauser) => {
var objtask = {};
const taskdata = await db.query("SELECT DATE_FORMAT(created_date, '%Y-%m-%d') as created_date, created_time, tasklist, user_id, DATE_FORMAT(created_by, '%Y-%m-%d') as date, DATE_FORMAT(created_by, '%H:%i:%s') as time FROM tasklist where user_id = ?", [datauser.user_id]);
if (taskdata[0] && taskdata[0].length > 0) {
objtask = {
userid: datauser.user_id,
tasklist: taskdata[0]
}
console.log(objtask);
userTasklist.push(objtask);
}
})
console.log(userTasklist)
//res.send({ message: "user list fetched", userdata: userdata[0], tasklistdata: userTasklist })
}
}

The scope of the wait for the db.query is within the map function. The map function needs to have the async keyword. However, it still will not work unless you wrap it in a Promise.all. This will make sure all the map iterations are resolved before moving forward in your code.
exports.allUserList = async (req, res) => {
const db = await connection()
let userID = req.params.userid
const userdata = await db.query('SELECT name, user_id, employee_code FROM users WHERE under_gh = ?', [userID])
// console.log(userdata[0])
if (userdata[0] && userdata[0].length > 0) {
let userTasklist = []
await Promise.all(
userdata[0].map(async (datauser) => {
var objtask = {}
const taskdata = await db.query("SELECT DATE_FORMAT(created_date, '%Y-%m-%d') as created_date, created_time, tasklist, user_id, DATE_FORMAT(created_by, '%Y-%m-%d') as date, DATE_FORMAT(created_by, '%H:%i:%s') as time FROM tasklist where user_id = ?", [datauser.user_id])
if (taskdata[0] && taskdata[0].length > 0) {
objtask = {
userid: datauser.user_id,
tasklist: taskdata[0]
}
console.log(objtask)
userTasklist.push(objtask)
}
})
)
console.log(userTasklist)
// res.send({ message: "user list fetched", userdata: userdata[0], tasklistdata: userTasklist })
}
}

You should change userdata[0].map((datauser) => { to userdata[0].map(async (datauser) => {

Related

NodeJS with MySQL - Return blank Array

I have initialized an array "userTasklist". I have pushed the object in this array in .map function. After .map, I have console this Array but array is blank.
Than I have console the object in .map function and all the value print successfully but in Array there are no value. Don't know why.
exports.allUserList = (req, res) => {
let userID = req.params.userid;
const ghusersQuery = "SELECT user_id, name, employee_code FROM users WHERE under_gh = ?";
conn.query(ghusersQuery, [userID], (err, userdata) => {
if (err) {
res.send({ message: err })
} else {
if (userdata && userdata.length > 0) {
let userTasklist = [];
userdata.map((datauser) => {
var objtask = {};
const userDataQuery = "SELECT * FROM tasklist WHERE user_id = ?";
conn.query(userDataQuery, [datauser.user_id], (errnew, taskdata) => {
if (taskdata && taskdata.length > 0) {
objtask = {
userid: datauser.user_id,
tasklist: taskdata
}
userTasklist.push(objtask);
}
})
})
console.log(userTasklist)
res.send({ message: "user list fetched", userdata: userdata, tasklistdata: userTasklist })
} else {
res.send({ message: "Data not found!" })
}
}
})
}
Simplified solution using mysql21 for handling queries as Promises.
exports.allUserList = async (req, res) => {
const { userid } = req.params
const users = await connection.query('SELECT user_id, name, employee_code FROM users WHERE under_gh = ?', [userid])
if (!users.length)
return res.send({ message: "Data not found!" })
// better fetch all relevant tasks in bulk
const tasks = await connection.query('SELECT * FROM tasklist WHERE user_id IN (?)', [users.map(r => r.user_id)])
res.send({ message: "user list fetched", users, tasks })
}

Foreach loop in nodejs

My Project uses Node JS + My SQL
I am running a simple query that checks whether entries exist in database for some params.
If they exist, it then updates them, else it inserts them.
The problem is, it is entering the last entry n times instead of each being unique.
When updating also, it is not able to identify the right row.
router.post('/feeRegister', asyncMiddleware( async(req, res) => {
let post= {
...........
}
JSON.parse(req.body.fees).forEach((i,index) => {
let sql = `SELECT id, period, amount FROM feeregister WHERE schoolId = '${req.body.schoolId}' AND studentId = '${req.body.student}' AND classes = '${req.body.classes}' AND year = '${req.body.year}' AND type = '${JSON.parse(req.body.fees)[index][1]}';`
pool.query(sql, async(err, results) => {
try{
if(err){ throw err }
if(results){
if(results.length){
console.log('Entry Exists', index, results[0].id)
let post2= {
...............
}
let sql2 = `UPDATE feeregister SET ? WHERE id = '${results[0].id}'`;
pool.query(sql2, post2, async(err, results) => {
try{
if(err){ throw err }
if(results){}
}catch(e){ func.logError(e); res.status(500); return; }
})
}else{
console.log('Entry does not exist', index)
let sql = `INSERT INTO feeregister SET ?`
pool.query(sql, post, async(err, results) => {
try{
if(err){ throw err }
if(results){}
}catch(e){ func.logError(e); res.status(500); return; }
})
}
}
}catch(e){ func.logError(e); res.status(500); return; }
})
});
}))
Iam connecting to database like :
var mysql = require('mysql')
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
database: 'dBName',
password: '',
multipleStatements: true
});
module.exports = pool;
Perhaps you should call the query function with async-await method.
router.post('/feeRegister', asyncMiddleware( async(req, res) => {
let post= {
//
}
JSON.parse(req.body.fees).forEach(async (i,index) => {
let sql = `SELECT id, period, amount FROM feeregister WHERE schoolId = '${req.body.schoolId}' AND studentId = '${req.body.student}' AND classes = '${req.body.classes}' AND year = '${req.body.year}' AND type = '${JSON.parse(req.body.fees)[index][1]}';`
const promisePool = pool.promise();
let results = await promisePool.query(sql);
if(results){
if(results.length){
console.log('Entry Exists', index, results[0].id)
let post2= {
//
}
let sql2 = `UPDATE feeregister SET ? WHERE id = '${results[0].id}'`;
await promisePool.query(sql2);
}else{
console.log('Entry does not exist', index)
let sql = `INSERT INTO feeregister SET ?`
await promisePool.query(sql);
}
}
});}));

using bcrypt for login in nodejs

I'm having a hard time with integrating bcrypt to try to make my login system safe.
I basically get the username, password the user inputs and try to compare it from the hashed password in my db. here's what I have.
const inputUsername = req.body.inputUsername;
const inputPassword = req.body.inputPassword;
var userLogin = "select * from login where USERNAME = ?"
ibmdb.open(ibmdbconnMaster, function(err, conn) {
if (err) return console.log(err);
conn.query(userLogin, [inputUsername], function(err, rows) {
if (err) {
console.log(err)
}
if (rows.length > 0) {
var pass = ""
for (var i = 0; i < rows.length; i++) {
pass = rows[i]['PASSWORD'];
console.log(pass)
bcrypt.compare(inputPassword, hash, function(err, result) {
if (pass == result) {
console.log("this works")
userAuth = true;
res.redirect('/index')
}
})
}
console.log("does not work")
} else {
userAuth = "false";
res.render('login.ejs')
alert('Incorrect username or password. Please try again')
}
conn.close(function() {
console.log('closed the function /login');
});
})
})
what happens right now is I get the error ReferenceError: hash is not defined
not sure how to fix this. thanks in advance
Where have you defined hash? I don't see it in your code.
Here's an example of auth routes that I've used with bcrypt/node/express:
const Users = require("../users/users-model.js");
router.post("/register", (req, res) => {
// Pull the user's credentials from the body of the request.
const user = req.body;
// Hash the user's password, and set the hashed password as the
// user's password in the request.
const hash = bcrypt.hashSync(user.password, 10);
user.password = hash;
Users.add(user)
.then((newUser) => {
const token = generateToken(newUser);
res
.status(201)
.json({ created_user: newUser, token: token, user_id: newUser.id });
})
.catch((err) => {
res.status(500).json({
message: "There was an error adding a user to the database",
err,
});
});
});
router.post("/login", (req, res) => {
const { username, password } = req.body;
Users.findBy({ username })
.first()
.then((user) => {
if (user && bcrypt.compareSync(password, user.password)) {
const token = generateToken(user);
res
.status(200)
.json({
username: user.username,
first_name: user.first_name,
last_name: user.last_name,
email: user.email,
token: token,
user_id: user.id,
});
} else {
res.status(401).json({ message: "Invalid Credentials" });
}
})
.catch((err) => {
res.status(500).json(err);
});
});
function generateToken(user) {
const payload = {
userid: user.id,
username: user.username,
};
const options = {
expiresIn: "1h",
};
const token = jwt.sign(payload, secrets.jwtSecret, options);
return token;
}
module.exports = router;

How can I make my Node.js MySQL connection as a promise work?

I have just started to work with node.js and my js knowledge is a bit rusty.
I started with callbacks and then I found out about promises. This syntax was more like my brain works, so I rewrote my code with promises.
But now my MySql connection does not work. It can't even get reached (I think...)
I have logged the word "test" in the file userDB, that worked. But then in the mySql file the console.log "test2" didn't work.
Thanks to you all!
Chris
Here is my server.js (the file that node starts):
/* REQUIRE */
const oAuth2Server = require('node-oauth2-server');
const express = require('express');
const bodyParser = require('body-parser');
const oAuthModel = require('./endpoints/auth/authModel');
const util = require('util');
const dbCon = require('./subsystem/mySql')
/* CONST */
const port = 3000;
const debug = true;
const app = express();
/* INIT */
app.oauth = oAuth2Server({
model: oAuthModel,
grants: ['password'],
debug: debug
})
/* ROUTER */
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(app.oauth.errorHandler());
const authRoutes = require('./router/auth')(express.Router(), app, dbCon)
app.use('/auth', authRoutes);
app.all('*', (req, res) => {
res.status(404).send({message: "This service was not found"});
});
/* Start Server */
app.listen(port, () => {
console.log(`listening on port ${port}`)
})
Here is my router file auth.js:
module.exports = (router, expressApp, dbCon) => {
const userDB = require('../endpoints/user/userDB')(dbCon)
const authMiddleware = require('../endpoints/auth/authMiddleware')
const userMiddleware = require('../endpoints/user/userMiddleware')(userDB)
router.post('/registerUser', userMiddleware.registerUser)
//router.post('/login', expressApp.oauth.grant(), authMiddleware.login)
router.post('/login', expressApp.oauth.grant())
return router
}
Here is my userDB file:
let mySqlConnection;
module.exports = injectedMySqlConnection => {
mySqlConnection = injectedMySqlConnection
return {
registerUserInDB: registerUserInDB,
getUserFromCrentials: getUserFromCrentials,
doesUserExist: doesUserExist,
getUserByUsername: getUserByUsername
}
}
const registerUserInDB = (username, password) => {
return new Promise((resolve,reject) => {
//execute the query to register the user
mySqlConnection.query(`INSERT INTO users (username, user_password) VALUES ('${username}', SHA('${password}'))`)
.then(data => {resolve(true)})
.catch(error => {reject(error)})
})
}
const getUserFromCrentials = (username, password) => {
return new Promise((resolve,reject) => {
//create query using the data in the req.body to register the user in the db
const getUserQuery = `SELECT * FROM users WHERE username = '${username}' AND user_password = SHA('${password}')`
console.log('getUserFromCrentials query is: ', getUserQuery);
//execute the query to get the user
mySqlConnection.query(getUserQuery)
.then(data => {resolve(data)})
.catch(error => {reject(error)})
})
}
const doesUserExist = username => {
return new Promise((resolve,reject) => {
console.log('test');
//execute the query to check if the user exists
mySqlConnection.query(`SELECT * FROM users WHERE username = '${username}'`)
.then(data => {resolve(data.results !== null ? data.results.length == 1 ? true : false : false)})
.catch(error => {reject(error)})
})
}
const getUserByUsername = username => {
return new Promise((resolve,reject) => {
//execute the query to check if the user exists
mySqlConnection.query(`SELECT id, username FROM users WHERE username = '${username}'`)
.then(data => {resolve(data)})
.catch(error => {reject(error)})
})
}
Here is my userMiddleware (is this middleware?):
let userDb;
module.exports = injectedUserDb => {
userDb = injectedUserDb
return {
registerUser: registerUser
}
}
function registerUser(req, res){
console.log(`authRoutesMethods: registerUser: req.body is:`, req.body);
//query db to see if the user exists already
userDb.doesUserExist(req.body.username)
.then(data => {
if(data)
{
sendResponse(res, "User already exists", 200)
return
}
else
{
//register the user in the db
userDb.registerUserInDB(req.body.username, req.body.password)
.then(data => {
userDb.getUserByUsername(req.body.username)
.then(data => {sendResponse(res, data.results, "")})
.catch(error => {sendResponse(res, "Failed to register user", error)})
})
.catch(error => {sendResponse(res, "Failed to register user", error)})
}
})
.catch(err => {
sendResponse(res, "User already exists", 200)
return
})
}
function sendResponse(res, message, error) {
res
.status(error !== null ? error !== null ? 400 : 200 : 400)
.json({
'message': message,
'error': error,
})
}
And last but not least my mySql.js file:
var mySql = require('mysql');
const query = sql => {
return new Promise( ( resolve, reject ) => {
let connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'oauth2test'
});
console.log('test2');
connection.query( sql, ( err, rows ) => {
if ( err )
{
connection.end();
reject( err );
}
else
{
connection.end();
resolve( rows );
}
});
});
}
module.exports.query = query;
You have a simple typo in your mySql.js file:
The line
var mySql = require('mysql');
should be replaced with
var mysql = require('mysql');
Other than that the query code works ok on my machine:
var mysql = require('mysql');
const query = sql => {
return new Promise( ( resolve, reject ) => {
let connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'oauth2test'
});
console.log('test2');
connection.query( sql, ( err, rows ) => {
if ( err )
{
connection.end();
reject( err );
}
else
{
connection.end();
resolve( rows );
}
});
});
}
module.exports.query = query;

Strange nodejs behaviour when logging in a user

The problem is that it shows that it is successfully logged in (201) without the redirect code, but with it, it shows a 302 error and the email_address is undefined.
What could be the problem here? I still can't come to a conclusion.
The problem may be in the order of the code I guess?
const login = async (req, res, next) => {
const { email_address, password, user_email, user_password}: { email_address: string, password: string, user_email: string, user_password: string } = req.body;
try {
const userWithDetails = 'SELECT * FROM users WHERE email_address = user_email AND password = user_password'; //w form info
if (userWithDetails) {
req.session.loggedin = true; //true
req.session.email_address = email_address; //undefined
console.log(req.session.email_address)
// return res.redirect('./index.html')
}
res.status(201).send('Succesfully signed in');
// res.status(403).send('Password is not correct');
} catch(error) {
res.status(404).send(`User with email ${email_address} not found!`);
}
await next;
};
NEW CODE ***
const login = async (req, res, next) => {
const { email_address, password}: { email_address: string, password: string} = req.body;
const userWithDetails = 'SELECT * FROM users WHERE email_address = ?';
return con.query(userWithDetails, email_address, (err, results) => {
if (err) {
console.error(err);
}
const user = results.find(emailObj => emailObj.email_address === email_address);
if (results && results.length && user.email_address) {
req.session.loggedin = true;
req.session.email_address = email_address;
const matchPassword: boolean = bcrypt.compareSync(password, user.password);
if (matchPassword) {
const token = jwt.sign({ user }, 'aaaa', { expiresIn: '1h'});
res.status(200).send({message: 'Logged in', token: token});
} else {
res.status(403).send('Password is not correct');
}
} else {
res.status(404).send(`User with email ${email_address} not found!`);
}
});
await next;
}
You don't execute your sql query at any point.
You just say :
query = 'select blabla'
if(query){...}
Of course this will always be true. You want to run the query on your database.
Also in your query you don't properly use the variables, see string formatting :
let my_var = `SELECT xxx from xxx where username = '${username}'`
Also please sanitize the parameters to prevent SQL Injection...