I'm using Mysql in my Express app
i hashed users pass using bcryptjs in mysql db and its fine.
using this code :
// register
router.post("/register", async (req, res) => {
const hashed = await bcrypt.hash(req.body.pass, 10);
const user = {
uname: req.body.uname,
phone: req.body.phone,
pass: hashed
};
let sql = "INSERT INTO user SET ? ";
db.query(sql, user, (err, result) => {
if (err) throw err;
console.log(`${user.uname} INSERTED INTO users`);
});
});
// GET USERS
router.get("/users", (req, res) => {
db.query("SELECT * FROM user", (err, results) => {
if (err) {
return res.send(err);
} else {
return res.json({
data: results
});
}
});
});
but when i want to log in users and let bcrypt compare requested pass with user pass it will give me this err :
SyntaxError: Unexpected identifier
And this is what i tried :
// loggin
router.post("/login", async (req, res) => {
var username = req.body.uname;
var password = req.body.pass;
db.query(
"SELECT pass FROM user WHERE uname = ?",
[username],
(err, result, fields) => {
try {
if (await bcrypt.compare(password, result)) {
console.log('Success')
}
} catch {
console.log('catched')
}
}
);
});
💡 The only one reason why you got some error, it's because you're using await in a function without async
👨🏻🏫 You can use this code below 👇:
router.post("/login", async (req, res) => {
var username = req.body.uname;
var password = req.body.pass;
db.query(
"SELECT pass FROM user WHERE uname = ?",
[username],
async (err, result, fields) => {
try {
// if you're using mysql2, don't forget to change `result` with `result[0].pass`.
// you can console.log(result) to see where is the field of your password plain text
const isPassword = await bcrypt.compare(password, result);
console.log(isPassword); // true
} catch(ex) {
console.log(ex); // false
}
}
);
});
I hope it's can help you 🙏.
Related
I use a sqlite3 database for a node.js express. If I return the request as in the tutorial in router.js it works and I get all the items. Now I have created a service to get the sql from the route (controller). But unfortunately I don't get anything back. I had already tried it with async await in the service. That didn't help either.
my code:
// router.js
const dbService = require("../services/dbService/");
router.get("/users", (req, res, next) => {
try {
res.status(200).send({
data: dbService.getAllUsers();
})
return;
} catch(err) {
next(err);
}
});
// dbService.js
const db = require("../db/database.js");
module.exports = {
getAllUsers() {
const sql = "select * from users";
db.all(sql,[], (err, rows) => {
return {"data": rows};
});
}
}
For simple reasons, I have not included error handling in the code. Why can't I get database values from the service? What do I have to do?
Thanks in advance! Mike
You're running afoul of asynchronous JS. db.all returns results to the callback.
A refactor to use callbacks would look something like:
// router.js
const dbService = require("../services/dbService/");
router.get("/users", (req, res, next) => {
dbService.getAllUsers((err, result) => {
if (err) next(err);
res.json({
data: result;
});
});
});
// dbService.js
const db = require("../db/database.js");
module.exports = {
getAllUsers(cb) {
const sql = "select * from users";
db.all(sql,[], (err, rows) => {
cb(err, rows);
});
}
}
And promises woudl look like:
// router.js
const dbService = require("../services/dbService/");
router.get("/users", async (req, res, next) => {
try {
const result = await dbService.getAllUsers();
res.json({
data: result;
});
} catch (err) {
next(err);
}
});
// dbService.js
const db = require("../db/database.js");
module.exports = {
getAllUsers(cb) {
const sql = "select * from users";
return new Promise((resolve, reject) =>
db.all(sql,[], (err, rows) => {
if (err) reject(err);
resolve(rows);
})
);
}
}
I'm trying to create a register route in my NodeJS rest api, but whenever I try to send the data to the db, it's showing me some error like SyntaxError: await is only valid in async function.
I know what's the meaning of the error but, don't know why this error is coming here.
Here's my register route code:
router.post("/register", async (req, res) => {
const firstName = req.body.firstName;
const lastName = req.body.lastName;
const email = req.body.email;
const phone = req.body.phone;
const gender = req.body.gender;
const country = req.body.country;
const password = req.body.passwordHash;
bcrypt.hash(password, 10, (err, hash) => {
if (err) {
console.log("error: " + err);
} else {
const newUser = new User({
firstName,
lastName,
email,
phone,
gender,
country,
passwordHash: hash,
});
try {
const savedUser = await newUser.save()
res.send(savedUser)
} catch (err) {
res.status(400).send(err)
}
}
});
});
Can someone please help me?
await is inside the (err, hash) => function. So you need async (err, hash) =>, not async (req, res) =>.
I am changing my backend (switching over from Mongo to MySql). I know the error is getting thrown because a return statement is being executed before my SQL query has finished and then when my sql query finishes, it tires to send another res.send, hence why I am trying to use mysql2 with Promise wrappers to use await on queries in my async function.
I have a separate file that creates the DB connection so I can access the connection throughout my Nodejs backend:
const mysql = require('mysql2');
async function pool(){
const pool = await mysql.createPool({
host: "ip",
user: "username",
password: "password",
database: "db"
});
return pool
}
exports.getConnection = async function(callback) {
const currentPool = await pool();
currentPool.getConnection(function(err, conn) {
if(err) return callback(err);
callback(err,conn)
});
};
Then, to create a query that follows async/await:
sql.getConnection(async function(err, client){
client.query(`select email from users where email = "${email}"`, function (error, result){
if(error) return res.status(500).send('an internal db error occurred');
// carry on with code ...
});
});
I've tried using await on the query too:
await sql.getConnection(async function(err, client){
client.query(`select email from users where email = "${email}"`, function (error, result){
if(error) return res.status(500).send('an internal db error occurred');
// carry on with code ...
});
});
What am I missing? I haven't tired to use the normal mysql NPM library and make my own promise wrapper yet...
NEW CODE:
I've updated my function:
const mysql = require('mysql2');
const pool = mysql.createPool({
host: "ip",
user: "user",
password: "pass",
database: "db"
});
exports.db = (sql) => {
new Promise((resolve, reject) => {
pool.getConnection((err, conn) => {
if(err) return reject(err);
conn.query(sql, (err, results, fields) => {
conn.release()
if(err) return reject(err)
console.log(results)
resolve(results);
});
});
});
}
Then I call it via:
try{
const emailExisit = await sql.db(`SELECT email FROM users WHERE email = "${email}"`);
console.log(emailExisit);
if(emailExisit.length > 0) return res.status(422).send({"data": "", "code": "105", "message": "An account with given email already exists"});
}catch (err) {
console.log(err)
return res.status(500).send({"data": "", "code": "108", "message": `There seems to be an error contacting the database. Try again later <br> ${err}`});
}
However, my code still continues, leaving my emailExists variable undefined (yes, it is inside an async function)
This is my configuration to use MySQL with Node.js. I hope it works with you.
/config/mysql.js
const mysql = require('mysql2');
const pool = mysql.createPool({
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
port: process.env.MYSQL_PORT,
database: process.env.MYSQL_DB_NAME,
});
const query = (query, args = []) =>
new Promise((resolve, reject) => {
pool.getConnection((err, connection) => {
if (err) {
return reject(err);
}
connection.query(query, args, (err, results) => {
connection.release();
if (err) {
return reject(err);
}
resolve(results);
});
});
});
module.exports = { query };
/index.js
const { query } = require('./mysql');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.get('/api/v1/sum', (req, res) => {
query('SELECT 1 + 1 as sum')
.then(results => {
res.json({ sum: results[0].sum });
})
.catch(err => {
console.error(err);
res.status(500).json({ error: 'error msg' });
});
});
// anther example with async
app.get('/api/v1/sum', async (req, res) => {
try {
const results = await query('SELECT 1 + 1 as sum');
res.json({ sum: results[0].sum });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'error msg' });
}
});
app.listen(3000);
I'm working with PostgreSQL and NodeJS with its "PG Module".
CRUD works but sometimes doesn't update automatically the views when i save or delete some item. this is my code and I think that the error is here but i cannot find it, i tried everything :'(
Error Message:
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = (request, response) => {
pool.query('SELECT * FROM recipes', (err, result) => {
if (err) {
return next(err);
}
return response.render('recipes', { data: result.rows });
});
};
controller.save = (req, res) => {
pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2, $3)',
[req.body.name, req.body.ingredients, req.body.directions]);
return res.redirect('/');
};
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id]);
return res.redirect('/');
}
module.exports = controller;
PD: CRUD works but sometimes appears that error.
This error occurs when you sent a response before and then you try to send response again. For this you have to check if there is any piece of code that is sending your response twice. Sometimes it happens due to asynchronous behavior of nodejs. Sometimes a process will be in event loop and we send response and when it finishes execution response will be sent again. So You can use callbacks or async await to wait for execution.
Callback
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = (request, response) => {
pool.query('SELECT * FROM recipes', (err, result) => {
if (err) {
return next(err);
}
return response.render('recipes', { data: result.rows });
});
};
controller.save = (req, res) => {
pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2,$3)',
[req.body.name, req.body.ingredients, req.body.directions],function(err,resp)
{
if(err){
console.log(err)
}else{
return res.redirect('/');
}
});
};
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id],function(err,resp){
if(err){
console.log(err)
}else{
return res.redirect('/');
}
});
}
module.exports = controller;
Or You can also use async await to wait for execution and then send response.
Async/Await
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = async(request, response) => {
try{
const result = await pool.query('SELECT * FROM recipes');
return response.render('recipes', { data: result.rows });
}
catch(err){
return next(err);
}
};
controller.save = async(req, res) => {
try{
await pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2,$3)',[req.body.name, req.body.ingredients, req.body.directions]);
return res.redirect('/');
}
catch(err){
return next(err);
}
};
controller.delete = async(req, res) => {
try{
await pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id]);
return res.redirect('/');
}catch(err){
console.log(err);
}
}
module.exports = controller;
Check res.send() should not call two times.
In Controller
const getAll = function(req, res){
res.send(service.getAll(req,res));
}
In Service
const Type = require("../models/type.model.js");
exports.getAll = (req, res) => {
Type.getAll((err, data) => {
res.send(data);
});
};
Above res.send(data); two-time calling will create a problem. better to use
const getAll = function(req, res){
service.getAll(req,res);
}
You need to embed your response in the callback to the query. Since the call is asynchronous, sending the response earlier will terminate the call stack never waiting for the webapi(Behaviour may vary).
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id],(err, result)
=> {
// error handling can be done accordingly
return res.redirect('/');
})
}
I have a mongodb database called interview_prac. In interview_prac there is a collection called Users. When a user signs up the username and password are stored in this collection such as {name:_username,password:_password}.
I already inserted an item into Users. when I type db.Users.find() I get the following: { "_id" : ObjectId("58a22abd0321b10be42f82ac"), "name" : "reddit", "password" : "1234" }
Now when a user signs up the new users name should be inserted into this collection, however it doesn't happen.
Here is my code:
router.post('/adduser', function (req, res, next) {
var _username = req.body.username;
var _password = req.body.password;
var url = 'mongodb://localhost:27017/interview_prac';
MongoClient.connect(url, function (err, db) {
//if we didn't connect, throw error
if (err)
throw err;
console.log("connected")
var users = db.collection('Users')
users.findOne({
name: _username
}, function (err, user) {
if (user) {
err = 'The username already exists'
res.render('about', {
msg: err
})
} else {
users.insert({
name: _username,
password: _password
}, function (err, result) {
console.log("entry saved")
var new_msg = "Welcome " + _username
res.render('about', {
msg: new_msg
})
})
}
})
db.close()
})
console.log("Database closed")
})
Every time a new user signs up, the shows entry saved and closes the database, which means that the new user should be in my collection. However when I do db.Users.find(). I only get one user, there should be two. I can't seem to figure out why this error occurs.
Mongo's functions are asynchronous. You're closing the db connection before it has even done any of the code inside your connect callback.
Change your db.close() call inside the insert's callback.
router.post('/adduser', function (req, res, next) {
var _username = req.body.username;
var _password = req.body.password;
var url = 'mongodb://localhost:27017/interview_prac';
MongoClient.connect(url, function (err, db) {
//if we didn't connect, throw error
if (err)
throw err;
console.log("connected")
var users = db.collection('Users')
users.findOne({
name: _username
}, function (err, user) {
if (user) {
err = 'The username already exists'
res.render('about', {
msg: err
})
} else {
users.insert({
name: _username,
password: _password
}, function (err, result) {
db.close()
console.log("Database closed")
console.log("entry saved")
var new_msg = "Welcome " + _username
res.render('about', {
msg: new_msg
})
})
}
})
})
})