mysql insertion query and check by postman - mysql

I'm stuck in this problem, before postman told me that it lacked the default value and now...
when I run the insert tells me that one of the columns, in this case the column full_name, is not defined
I restarted the database and changed the restrictions for the NN fields
'use strict';
const bcrypt = require('bcrypt');
const Joi = require('joi');
const uuidV4 = require('uuid/v4');
const sendgridMail = require('#sendgrid/mail');
const mysqlPool = require('../../../ddbb/mysql-pool');
sendgridMail.setApiKey(process.env.SENDGRID_API_KEY);
async function validateSchema(payload) {
/**
* rellenar campos obligatorios: nombre, email, contraseña
* nombre String con 3 caracteres mínimos y un máximo de 50
* correo electrónico válido
* contraseña letras mayúsculas, minúscula y número. Mínimo 3 caracteres y máximo 30, usando regular expression
*/
const schema = {
full_name: Joi.string()
.min(3)
.max(50)
.required(),
email: Joi.string()
.email({ minDomainAtoms: 2 })
.required(),
password: Joi.string()
.regex(/^[a-zA-Z0-9]{3,30}$/)
.required(),
};
return Joi.validate(payload, schema);
}
/**
* creo perfil de usuario e inserto uuid y name en tabla users
* #param {number} uuid
* #return {String} name
*/
async function createUserProfile(uuid, name) {
const fullName = full_name;
const verificationCode = uuid;
const sqlQuery = `INSERT INTO users SET ?`;
const connection = await mysqlPool.getConnection();
await connection.query(sqlQuery,{
uuid: verificationCode,
full_name: fullName
});
connection.release();
return fullName;
}
/**
* creo un codigo de verificacion de usuario e inserto
* #param {String} uuid
* #return {String} verificationCode
*/
async function addVerificationCode (uuid){
const verificationCode = uuidV4();
const now = new Date();
const createdAt = now
.toISOString()
.substring(0, 19)
.replace('T', ' ');
const sqlQuery = 'INSERT INTO users_activation SET ?';
const connection = await mysqlPool.getConnection();
await connection.query(sqlQuery, {
users_uuid:uuid,
verification_code: verificationCode,
created_at: createdAt,
});
connection.release();
return verificationCode;
}
/**
* utilizo sendgrid para verificacion del email
* #param {String} userEmail
* #param {String} verificationCode
*/
async function sendEmailRegistration(userEmail, verificationCode) {
const linkActivacion = `${
process.env.API_BASE_URL
}/account/activate?verification_code=${verificationCode}`;
const msg = {
to: userEmail,
from: {
email: 'rebook#yopmail.com',
name: 'reBook',
},
subject: 'Welcome to reBook',
text: 'Where books take on a new life!',
html: `To confirm the account activate it here`,
};
const data = await sendgridMail.send(msg);
return data;
}
async function createAccount(req, res, next) {
const accountData = req.body;
try {
await validateSchema(accountData);
}catch (e) {
return res.status(400).send(e);
}
/**
* inserto usuario en ddbb:
* 3.hash de la password para almacenamiento seguro
*/
const now = new Date();
const securePassword = await bcrypt.hash(accountData.password, 10);
const uuid = uuidV4();
const connection = await mysqlPool.getConnection();
const sqlInsercion = `INSERT INTO users SET ?`;
try {
const result = await connection.query(sqlInsercion, {
uuid: uuid,
email: accountData.email,
password: securePassword,
});
connection.release();
const verificationCode = await addVerificationCode(uuid);
await sendEmailRegistration(accountData.email, verificationCode);
await createUserProfile(uuid, accountData.name);
return res.status(201).send();
} catch (e) {
if(connection){
connection.release();
}
return res.status(500).send(e.message);
}
}
module.exports = createAccount;
This is the json I introduce by postman.
{
"full_name":"Arturo",
"email":"arturos2006#yopmail.com",
"password":"1234567"
}
,and answers me that the full_name field is not defined

Related

How can I display data in mysql in web page?

I am using nodejs and mysql to display several words in database in webpage with express.
I recently noticed that if I use SELECT inside of async/await, I can only use that data inside of it.
Therefore, I tried to do writeHead inside that function, but did not work.
Below is my code segments.
Could you please give me some advice?
const mysql = require('mysql2/promise');
const getData = async (lang, word) => {
try {
// db connection
var connection = await mysql.createConnection({
host: "-----",
user: "-----",
password: "-----",
database: "-----",
});
var [idA, fieldsA] = await connection.query(`SELECT id FROM en WHERE word=${"'"+word+"'"}`);
var [idB, fieldsB] = await connection.query(`SELECT id FROM ${lang} WHERE word=${"'"+word+"'"}`);
if(idA[0] === undefined && idB === undefined){
return null;
}else{
if(idB[0] === undefined) wordId = idA[0].id;
else wordId = idB[0].id;
var [dataA, fieldsA] = await connection.query(`SELECT * FROM en WHERE id=${"'"+wordId+"'"}`);
var [dataB, fieldsB] = await connection.query(`SELECT * FROM ${lang} WHERE id=${"'"+wordId+"'"}`);
if(lang === 'en' || dataB[0] === undefined){
[dataB, fieldsB] = await connection.query(`SELECT * FROM en WHERE id='null'`);
}
var data = [
{'id': dataA[0].id, 'word': dataA[0].word, 'def': dataA[0].def, 'syn': dataA[0].syn, 'ref': dataA[0].ref, 'area': dataA[0].area},
{'id': dataB[0].id, 'word': dataB[0].word, 'def': dataB[0].def, 'syn': dataB[0].syn, 'ref': dataB[0].ref, 'area': dataB[0].area}
];
return data;
}
} catch (error) {
console.log(error);
}
};
app.get('/search/:lang/:word', (req, res) => {
getData(req.params.lang, req.params.word)
.then((response) => {
console.log(response)
let page = templateSearch.getPage(response, req.params.lang, req.params.word);
res.writeHead(200);
res.end(page);
});
});

Node.js help creating a function

I'm not sure what did i miss in my code.. I'm new on this
I have this code
helpers.encryptPassword = async (password) => {
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(password, salt);
return hash;
};
module.export = helpers;
But when i execute this code
**newUser.password = await helpers.encryptPassword(password);**
it gives me an error, say "encryptPassword is not a function", but i don't know what am doing wrong
I understand that encryptPassword seems to store the result of a function with no name, but it is not a function. I need to change it, making possible to recive a parameter (the password, so bcrypt could hash it)
If You need all the code, there is it
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const pool = require ('../../database');
const helpers = require('../lib/helpers');
passport.use ('local.signup', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
}, async (req, username, password, done) => {
const { fullname } = req.body;
const newUser = {
username,
password,
fullname
};
**newUser.password = await helpers.encryptPassword(password);**
const result = await pool.query('INSERT INTO users SET ?', [newUser]);
console.log(result);
}));

Return will return empty object even it shoudn't

here is my code
(email) => {
let con = {};
connection.query(
"SELECT * FROM users WHERE email=?",
email,
(error, result) => {
con.id = result[0].id;
con.email = result[0].email;
con.name = result[0].name;
con.password = result[0].password;
}
);
return con;
},
It's simple, it should return con object, but it returns it empty. I think because this query will execute last in function. Any help?
You can try to turn your function into async and wrap connection.query with new Promise like this:
(email) => {
return new Promise((resolve, reject) => {
connection.query(
"SELECT * FROM users WHERE email=?",
email,
(error, result) => {
if (error) {
reject(error);
}
const con = {};
con.id = result[0].id;
con.email = result[0].email;
con.name = result[0].name;
con.password = result[0].password;
resolve(con);
}
);
}
And using it like this:
func(email).then(con => {
console.log(con)
});
or with await:
const con = await func(email);
You're right, the query will take a bit of time and con will be already returned by the time it finishes running.
Even if it doesn't take any time, the callback function is going to be run separately so con will not be updated either way.
You have two options:
use a promise version of the query() method if it's available.
promise-ify the query.
This is roughly how you can do it (2nd option):
return new Promise((resolve) => {
connection.query(
"SELECT * FROM users WHERE email=?",
email,
(error, result) => {
let con = {};
con.id = result[0].id;
con.email = result[0].email;
con.name = result[0].name;
con.password = result[0].password;
resolve(con);
}
});
...
// and you can use it like this
const result = await myFunc(email);

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...

How to send multiple results of multiple db.query to client through res.render() function?

I am building an website. My client code is in EJS and my server code is in Node.js. I am successful on sending the results variable of db.query through res.send();. But now I want to use two queries and retrieve and send values of those queries to the client. But if I use only one variable then its fine but when I am using both variables of 2 queries in client it's giving me error: Error: Can't set headers after they are sent.
Here is my login.js file:
var username;
var password;
var result;
module.exports = {
inserttest : (req,res) => {
// let query = "SELECT * FROM `login` where username"; // query database to get all the players
db.query('SELECT * FROM login WHERE username = ? AND password = ?', [username, password], function(error, result, fields) {
if (error) {
res.redirect('/login');
}
var moisture = 11232;
var ph = 1121;
var ec = 543;
var date1=new Date();
const sqlq='insert into usertest values ?';
var values = [
[result[0].kitno,moisture,ph,ec,date1]
];
db.query(sqlq, [values], function(error, results, fields) {
if(error)
{
console.log("error");
//var a
//res.send(500,'showAlert')
}
else{
console.log("1 row inserted successfully");
}
var result2= doQuery1();
res.render('mytest',
{
url:"/mytest",
title:"WELCOME2",
results1:result,
results2:result2
});
});
});
function doQuery1(){
let query = "SELECT * FROM usertest WHERE kitno IN(select kitno from login where username = ? AND password = ?)";
var resource;
db.query(query, [username, password], function(error, result4, fields){
resource=result4;
});
return resource;
};
},
Here is my EJS i.e. login.ejs file code:
Here I am using result1[0].name as a title. and result2[i].ph in for loop.
<main class="page-content">
<div class="container-fluid">
<h2>My Tests</h2>
<hr>
<div id="main">
<div id="left" class="container">
<br>
<form method="get" action="/insertvalues">
<input type="submit" value="Start Test" />
</form>
<% for (var i = 0; i < results2.length; i++) { %>
<%=results2[i].ph%>
<%}%>
<br>
I tried several ways of sending that both variable results1 and result2 through res.render() but its running only when I am removing the result2 codes from client.
Error I am getting:
_http_outgoing.js:491
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:491:11)
at ServerResponse.setHeader (_http_outgoing.js:498:3)
at Array.write (C:\Users\Rohit\Desktop\Project_me\soil2\node_modules\finalhandler\index.js:285:9)
at listener (C:\Users\Rohit\Desktop\Project_me\soil2\node_modules\on-finished\index.js:169:15)
at onFinish (C:\Users\Rohit\Desktop\Project_me\soil2\node_modules\on-finished\index.js:100:5)
at callback (C:\Users\Rohit\Desktop\Project_me\soil2\node_modules\ee-first\index.js:55:10)
at IncomingMessage.onevent (C:\Users\Rohit\Desktop\Project_me\soil2\node_modules\ee-first\index.js:93:5)
at emitNone (events.js:106:13)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
There is a Promise version of mysql package: mysql2. Using promise you can wait for Promise to resolve or reject akin to sync code.
You can achieve what you're trying to achieve like:
const mysql = require('mysql2/promise');
module.exports = {
inserttest : async (req,res) => {
// let query = "SELECT * FROM `login` where username"; // query database to get all the players
const connection = await mysql.createConnection({host:'localhost', user: 'root', database: 'test'});
try {
const [rows, fields] = await connection.execute('SELECT * FROM login WHERE username = ? AND password = ?', [username, password]);
} catch (e) {
console.error(e);
res.redirect('/login');
}
var moisture = 11232;
var ph = 1121;
var ec = 543;
var date1=new Date();
const sqlq='insert into usertest values ?';
var values = [
[result[0].kitno,moisture,ph,ec,date1]
];
try {
// will wait till execution finishes
await connection.execute(sqlq, [values]);
console.log("1 row inserted successfully");
} catch (e) {
console.error(e)
}
var result2= doQuery1();
res.render('mytest',
{
url:"/mytest",
title:"WELCOME2",
results1:result,
results2:result2
});
}
async function doQuery1(){
let query = "SELECT * FROM usertest WHERE kitno IN(select kitno from login where username = ? AND password = ?)";
var resource;
try {
const connection = await mysql.createConnection({host:'localhost', user: 'root', database: 'test'});
resource = await connection.execute(query, [username, password]);
return resource;
} catch (e) {
console.error(e);
}
};
}
Using promise and async/await in this way you can make it sequential like.