AXIOS POST in vue not working: Suggestions? - vue.js

I'm trying to get a sign up feature. I have used expressjs to make the backend POST method that looks like this:
export const insertUser = (data, result) => {
db.query("INSERT INTO users VALUES ?", [data], (err, results) => {
if(err) {
console.log(err);
result(err, null);
} else {
result(null, results);
}
});
}
I then have a frontend where I use axios to post the values into the database, as this:
async insertUser() {
try {
await axios.post("http://localhost:5000/users", {
first_name: this.first_name,
second_name: this.second_name,
email: this.email,
road: this.road,
town: this.town,
post_code: this.post_code,
user_name: this.username,
password: this.password,
});
this.first_name = "";
this.second_name = "";
this.email = "";
this.road = "";
this.town = "";
this.post_code = "";
this.username = "";
this.password = "";
this.$router.push("/");
} catch (err) {
console.log(err);
}
However, I have used postman to try and post the information but I get an error saying that INSERT INTO users VALUES is incorrect. I have triple checked everything but for the life of me can't see the issue.

seem's the problem is in the nodejs function
"INSERT INTO users VALUES (?,?,?)"
for each data you need to put an '?' in the values
also if you have an id in our database that is auto increment you need to specify columns to update
"INSERT INTO users(name,email) VALUES (?,?)"
i think your data is an array no need to put it in brackets just : ,data,

Related

Return Values from a callback SQL function in node.js

Currently I'm working on a node.js application, with a register function. For this function I need to check a username is already taken or not. Unfortunately the SQL module in node just accepts a callback function from which I cannot send any booleans back.
Here is some code from my controller module:
async function createUser(req, res) {
try {
const salt = await bcrypt.genSalt(); //standard ist 10
const hashedPassword = await bcrypt.hash(req.body.password, salt);
const newUser = {
userName: req.body.username,
userPassword: hashedPassword
};
const userExists = model.checkIfUserExists(newUser.userName);
if (userExists == false){
// create new user
} else {
// Send json back "user already exists
}
res.status(201).json(newUser);
} catch {
res.status(500);
}
}
And here is the code of the model:
function checkIfUserExists(Username){
console.log("Checking if user exists");
let sql = "select * from users where user_name = ?";
db_conn.query(sql, Username, (err, result) => {
if (err){
throw err;
}
console.log(result);
if (result.length > 0){
return true;
} else {
return false;
}
});
}
Unfortunately the "checkIfUserExists" method never returns back a true or false which leads to the "userExists " variable to be null.
I'd like to know how to do return the bollean there or how to solve the problem in a more elegant way.
Please help me to fix this code. Thanks :)
You can either pass a callback to checkIfUserExists or use promises. If I were you, and since you are already using async/await, I would make your return of checkIfUserExists be a promise. So...your code could become
function checkIfUserExists(Username) {
return new Promise((resolve,reject) => {
console.log("Checking if user exists");
let sql = "select * from users where user_name = ?";
db_conn.query(sql, Username, (err, result) => {
if (err) {
throw err;
}
console.log(result);
if (result.length > 0) {
resolve()
} else {
reject()
}
});
})
}
Then, your code that calls this function would be:
async function createUser(req, res) {
try {
const salt = await bcrypt.genSalt(); //standard ist 10
const hashedPassword = await bcrypt.hash(req.body.password, salt);
const newUser = {
userName: req.body.username,
userPassword: hashedPassword
};
await model.checkIfUserExists(newUser.userName).catch(() => {
// Send json back "user already exists
});
// create user
res.status(201).json(newUser);
} catch {
res.status(500);
}
}
First check your catch statement and also add await before model.checkIfUserExists(newUser.userName)
async function createUser(req, res) {
try {
const salt = await bcrypt.genSalt(); //standard ist 10
const hashedPassword = await bcrypt.hash(req.body.password, salt);
const newUser = {
userName: req.body.username,
userPassword: hashedPassword
};
const userExists = await model.checkIfUserExists(newUser.userName);
if (userExists == false){
// create new user
} else {
// Send json back "user already exists
}
res.status(201).json(newUser);
} catch(ex) {
res.status(500);
}
}
return promise from this function:
function checkIfUserExists(Username){
return new Promise((resolve, reject) => {
console.log("Checking if user exists");
let sql = "select * from users where user_name = ?";
db_conn.query(sql, Username, (err, result) => {
if (err){
return reject(err);
}
console.log(result);
if (result.length > 0){
return resolve(true);
} else {
return resolve(false);
}
});
})
}

How to store third-party API array data into elephantSQL database using React.js front-end and node.js back-end?

Coding newbie here. So I've been trying to build a dictionary app using wordsapi and was trying to find a way to store the dictionary api into my back end. Below is my code on the front end using React.
const _addToQuollection = async (e) => {
e.preventDefault();
const apiUrl = 'http://127.0.0.1:3333/quollection/add';
const submitResponse = await fetch(apiUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ word: word, definition: definition }),
})
.then((response) => response)
.catch((e) => {
console.log(e);
});
console.log("word added to quollection: ", submitResponse)
if (submitResponse.status === 200) {
console.log("submit response is success")
}
}
In my console, the req body information for word and definition array pops up as so... console.log picture showing req body for string word and array definition
But the post request is only inserting into word and not definition... QUERY: INSERT INTO quollection (word) VALUES ('quote'
My backend route using Node.js looks like this...
router.post('/add', async(req, res) => {
console.log('backend reqBody: ', req.body);
const { word, definition } = req.body;
const response = await quollectionModel.addToQuollection(word, definition);
if (response.rowCount >= 1) {
console.log('def added success!')
res.sendStatus(200)
} else {
res.sendStatus(500)
}
});
And the backend model looks like this...
static async addToQuollection(word, definition) {
try {
const response = await db.result(`INSERT INTO quollection (word, definition) VALUES ($1, $2);`, [word, definition]);
return response;
} catch (error) {
console.log('error', error.message)
return error.message
}
}
This was how I created my schema...
CREATE TABLE quollection (
id serial PRIMARY KEY,
word text,
definition text[1000000]
);
And this is the result in postico...
postico screenshot with successful word column and null definition column
Ahhh I hope this was a decent enough explanation. Any help would be much appreciated T_T Thank you!

Query works but cant retrieve the data

I am new to Node.js (3 days total experience). I am using Node.js and the tedious package to query a database (azure SQL). I use the example as explained here: https://learn.microsoft.com/en-us/azure/azure-sql/database/connect-query-nodejs?tabs=macos
const connection = new Connection(config);
// Attempt to connect and execute queries if connection goes through
connection.on("connect", err => {
if (err) {
console.error(err.message);
} else {
console.log("Reading rows from the Table...");
// Read all rows from table
const request = new Request(
"SELECT * FROM clients",
(err, rowCount, columns) => {
if (err) {
console.error(err.message);
} else {
console.log(`${rowCount} row(s) returned`);
}
}
);
request.on("row", columns => {
columns.forEach(column => {
console.log("%s\t%s", column.metadata.colName, column.value);
});
});
connection.execSql(request);
}
});
I have two issues:
I do not know how to get the queried data into an object and
If I run the script it does print the items to the console, but it doesn't close the connection after it has done so. If I add a connection.close() at the bottom, it will close the connection before its done. I get the feeling that node.js executes everything at the same time (I am used to Python..).
Update
I found a way to close the connection, to my understanding the request object has several "events" that are predefined by the library. It seems I need to add the event "done" through request.on('done', ...) in order to make sure that it can even BE done. My updated code looks like this:
var connection = new Connection(config);
connection.connect(function(err) {
// If no error, then good to go...
executeStatement();
}
);
connection.on('debug', function(text) {
//remove commenting below to get full debugging.
//console.log(text);
}
);
function executeStatement() {
request = new Request("SELECT * FROM clients", function(err, rowCount) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
connection.close();
});
request.on('row', function(rows) {
_.forEach(rows, function(value, collection){
console.log(value)
console.log(value.value);
console.log(value.metadata.colName)
console.log(collection)
})
});
request.on('done', function(rowCount, more) {
console.log(rowCount + ' rows returned');
});
// In SQL Server 2000 you may need: connection.execSqlBatch(request);
connection.execSql(request);
}
Anyways, your help would be much appreciated!
Regards
Pieter
The package tedious is synchronous package, it uses the callback to return results. So when we call connection.close(), it will disable connection and stop the callback function. If will want to close the connection, I suggest you use async package to implement it.
For example
const { Connection, Request } = require("tedious");
const async = require("async");
const config = {
authentication: {
options: {
userName: "username", // update me
password: "password", // update me
},
type: "default",
},
server: "your_server.database.windows.net", // update me
options: {
database: "your_database", //update me
encrypt: true,
validateBulkLoadParameters: true,
},
};
const connection = new Connection(config);
let results=[]
function queryDatabase(callback) {
console.log("Reading rows from the Table...");
// Read all rows from table
const request = new Request("SELECT * FROM Person", (err, rowCount) => {
if (err) {
callback(err);
} else {
console.log(`${rowCount} row(s) returned`);
callback(null);
}
});
request.on("row", (columns) => {
let result={}
columns.forEach((column) => {
result[column.metadata.colName]=column.value
console.log("%s\t%s", column.metadata.colName, column.value);
});
// save result into an array
results.push(result)
});
connection.execSql(request);
}
function Complete(err, result) {
if (err) {
callback(err);
} else {
connection.close();
console.log("close connection");
}
}
connection.on("connect", function (err) {
if (err) {
console.log(err);
} else {
console.log("Connected");
// Execute all functions in the array serially
async.waterfall([queryDatabase], Complete);
}
});
connection.connect();
Besides, you also can use the package mssql. It supports asynchronous methods and depends on package tedious. We can directly call close after querying.
For example
const mssql = require("mssql");
const config = {
user: "username",
password: "password",
server: "your_server.database.windows.net",
database: "your_database",
options: {
encrypt: true,
enableArithAbort: true,
},
};
let pool = new mssql.ConnectionPool(config);
async function query() {
try {
await pool.connect();
const request = pool.request();
const result = await request.query("SELECT * FROM Person");
console.dir(result.recordset);
await pool.close();
console.log(pool.connected);
} catch (error) {
throw error;
}
}
query().catch((err) => {
throw err;
});
You can custom a class first and declare an Array to save ojects such as:
let sales = new Array();
class SalesLT{
constructor(catagryName,productName){
this.catagryName = catagryName;
this.productName = productName;
}
Here my sql statement returns 2 properties, so every time the loop takes out two elements from the ColumnValue[].
request.on("row", columns => {
for(let i=0; i<columns.length; i=i+2){
let sale = new SalesLT(columns[i].value,columns[i+1].value);
sales.push(sale);
}
sales.forEach( item => {
console.log("%s\t%s",item.catagryName, item.productName)
})
});
The code is as follows:
const { Connection, Request } = require("tedious");
let sales = new Array();
class SalesLT{
constructor(catagryName,productName){
this.catagryName = catagryName;
this.productName = productName;
}
}
// Create connection to database
const config = {
authentication: {
options: {
userName: "<***>", // update me
password: "<***>" // update me
},
type: "default"
},
server: "<****>.database.windows.net", // update me
options: {
database: "<***>", //update me
encrypt: true
}
};
const connection = new Connection(config);
// Attempt to connect and execute queries if connection goes through
connection.on ("connect", err => {
if (err) {
console.error(err.message);
} else {
queryDatabase();
}
});
function queryDatabase() {
console.log("Reading rows from the Table...");
// Read all rows from table
const request = new Request(
`SELECT TOP 2 pc.Name as CategoryName,
p.name as ProductName
FROM [SalesLT].[ProductCategory] pc
JOIN [SalesLT].[Product] p ON pc.productcategoryid = p.productcategoryid`,
(err, rowCount) => {
if (err) {
console.error(err.message);
} else {
console.log(`${rowCount} row(s) returned`);
}
connection.close();
}
);
request.on("row", columns => {
for(let i=0; i<columns.length; i=i+2){
let sale = new SalesLT(columns[i].value,columns[i+1].value);
sales.push(sale);
}
sales.forEach( item => {
console.log("%s\t%s",item.catagryName, item.productName)
})
});
connection.execSql(request);
}
this article should help you, to solve all the issues you are facing...which were the same I had when I started using Node :)
https://devblogs.microsoft.com/azure-sql/promises-node-tedious-azure-sql-oh-my/

NodeJS: bcrypt is returning false even when the password is correct

I am having trouble with the bcrypt.compare portion of my code. My route is able to hash the password and store the password in the database. The database is able to store 255 characters and I have verified that the password is 60 characters long. Every time I compare the password to the hashed password on the db, I get a false returned on from bycrypt.compare.
Has anyone encountered this and know what I may be doing wrong?
Auth Route for creating the user in the database:
app.post('/register/local', async (req, res) => {
const hashedPassword = await bcrypt.hash(req.body.password, 10) || undefined
const existingLocalUser = await db.User.findOne({ where: { email: req.body.email } }) || undefined
if (!existingLocalUser) {
try {
const newUser = await db.User.create({
given_name: req.body.given_name,
family_name: req.body.family_name,
email: req.body.email,
password: hashedPassword,
}
)
res.redirect('/login')
} catch {
res.redirect('/register')
}
} else if (existingLocalUser.dataValues.google_id) {
const updateUser = await db.User.update(
{ password: hashedPassword },
{ where: { email: req.body.email } }
)
} else {
console.log("You already have an account. Please login.")
res.redirect('/login');
}
})
Local Strategy from Passport:
passport.use(new LocalStrategy( async (username, password, done) => {
const existingLocalUser = await User.findOne({ where: { email: username }})
if (!existingLocalUser) {
console.log("No user exisits")
return done(null, false)
}
console.log("password", password)
console.log("existingLocalUser.password", existingLocalUser.password)
await bcrypt.compare(password, existingLocalUser.dataValues.password, function(error, result) {
if (error) {
return done(error)
} else if (result) {
return done(null, existingLocalUser)
} else {
return done(null, false)
}
})
}
));
bcrypt.compare(password, existingLocalUser.password, function(error, result) {
if (error) {
return done(error)
} else if (result) {
return done(null, existingLocalUser)
} else {
return done(null, false)
}
})
You are trying to use callback and await together, kindly remove await and stick to callbacks or you refactor and use async-await alone
As #cristos rightly pointed out the problem could be that you are mixing up async/await and callbacks. Stick to one pattern.
Here's how your code would be with async/await,
try {
const result = await bcrypt.compare(password, existingLocalUser.password);
if (result) {
return done(null, existingLocalUser);
} else {
return done(null, false);
}
} catch (error) {
return done(error);
}
Also on another note, are you sure you are comparing the correct values?
Going by the code sample you have provided I can see that you are logging,
console.log("password", password)
console.log("existingLocalUser.password", existingLocalUser.password)
However, the values compared in bcrypt.compare() is different,
bcrypt.compare(password, existingLocalUser.dataValues.password)
I figured out why it wasn't working... React or Redux was masking the password with asterisks so changing it to a sting of asterisks which gets hashed..

Node js make request to SQL Server, return result

Working with Node.js and am having some trouble understanding how to return the result after making a request to SQL Server. When running independently and writing to the console, I can get the result just fine, however using it as a function and having it return the result is where I am running into problems.
I'm pretty sure I have to use a callback/promise, but don't really understand how either of those are set up. Hoping someone on here can help me out!
Here is my code:
var sql = require("mssql");
var config = {
user: 'username',
password: 'password',
server: 'localhost',
database: 'Master'
};
function updateTable() {
var connection = new sql.ConnectionPool(config, function(err) {
var request = new sql.Request(connection);
request.query('select LastName from Persons', function(err, result) {
return result.recordset;
});
});
};
console.log(updateTable());
Basically trying to print the result to the console by calling the function through console.log. Right now it's printing 'undefined', but I assume putting in a callback would do the trick. Again, just need some help understanding how it works and getting it set up. Thanks!
If you just want to print it to the console then you can simply tweak your code as follows:
var sql = require("mssql");
var config = {
user: 'username',
password: 'password',
server: 'localhost',
database: 'Master'
};
function updateTable(callback) {
var connection = new sql.ConnectionPool(config, function(err) {
var request = new sql.Request(connection);
request.query('select LastName from Persons', function(err, result) {
callback(result.recordset);
});
});
};
updateTable(console.log);
To send the result from an express handler, assuming >= NodeJS v8:
Wrap the actual database interfacing logic inside an async function which will not block the main thread and export it from your module.
sqlConnector.js
const sql = require('mssql');
const config = {
user: 'username',
password: 'password',
server: 'localhost',
database: 'Master'
};
const updateTable = async () => {
try {
const pool = await sql.connect(config);
const sqlQuery = 'SELECT LastName FROM Persons';
const result = await pool.request().query(sqlQuery);
return result;
} catch (err) {
throw err;
}
};
export.updateTable = updateTable;
In express handler
Import your module which talks with MS-SQL (assumed sqlConnector.js) and mark your handler with the async keyword and return it from res.json at the end.
const sqlConnector = require('sqlConnector');
app.get('/someroute', async (req, res, next) => {
try {
const result = await sqlConnector.updateTable();
return res.status(200).json(result);
} catch (error) {
next(error);
}
});