How to send multiple requests with Axios? - mysql

I'm working on a react registration form which contain some fields (idStudent(primary key & auto increment), first name, last name, ....., faculty, prerequisites), I'm using Formik & yup for validation.
Later on, I have to link my app with a recommendation system (recommend a final year project to students) based on prerequisites and the obtained grades in some subjects.
At first, I used just one table to store the data coming from the form in frontend,
student(firstname, lastname, ... ,prerequisites)
A student can select prerequisites from a react select that contain prerequisites according to the faculty (example : if a student study computer science, the react select will show only computer science prerequisites like react, angular, machine-learning ....).
Taking into consideration a student can have multiple prerequisites, so the prerequisites column in students table will contain multiple id's of the selected prerequisites,
The prerequisites are stored in an other table in my database ( prerequisites(idFaculty, idPrerequisites, prerequisite) )
I know that I can store multiple id's in one column using a JSON file but after some researches here on Stackoverflow in some previous posts, I found that it's difficult to deal with JSON especially if I want to update a column.
So I created another table to store the selected prerequisites by a student when registering
(studentPrerequisites(idStd (foreign key reference to idStudent from students table), idPrerequisite(foreign key reference to idPrerequisites from Prerequisites table))
The problem I'm facing is how to send two post's requests via axios, taking into
consideration that maybe I should use a loop to store multiple rows in case a student select multiple Prerequisites.
This is what I did :
My backend file
app.post("/registerStudent", (req, res) => {
const faculty = req.body.faculty;
const firstName = req.body.firstName;
const lastName = req.body.lastName;
const phone = req.body.phone;
const email = req.body.email;
const password = req.body.password;
db.query(
"INSERT INTO students (email, password, firstName, lastName, faculty, phone) VALUES (?,?,?,?,?,?)",
[email, password, firstName, lastName, filiere, phone],
(err, result) => {
if (err) {
console.log(err);
} else {
// store chosen prerequisites
//result.insertId is the current idStudent of the student who registering
const idStd = result.insertId;
const idPrerequisite = req.body.idprerequis;
db.query(
"INSERT INTO studentPrerequisites (idStd, idPrerequisite) VALUES (?,?)",
[idFiliere, idPrerequisite],
(err, result) => {
if (err) {
console.log(err);
} else {
res.send("Values Inserted");
}
}
);
}
}
);
});
My frontend code
const onSubmit = (values, actions) => {
Axios.post("http://localhost:3001/registerStudent", {
faculty: values.faculty,
firstName: values.firstName,
lastName: values.lastName,
phone: values.phone,
email: values.email,
password: values.password,
})
.then(() => {
//preId is an array that contains the selected prerequisites(id's) from react select
//I try to use a for loop to store multiple of prerequisites dynamically in case a
//student select multiple prerequisites
for (let i = 0; i < preId.length; i++) {
idPrerequisites: preId[i],
}
})
.then(() => {
console.log("success!");
});
actions.resetForm();
};

It might be best to let the backend handle multiple prereqs by passing in an array of prereqs to your request. I'd also use Knex and async/await to avoid a lot of .then chaining and to make use of transactions. Transactions will revert all queries if any errors occur within the transaction. Knex also makes querying databases super easy with built-in methods instead of writing raw SQL. You should also be using object destructuring instead of doing firstName = req.body.firstName, lastName = req.body.lastName, etc. You can learn more about knex and getting your db connected to it here: https://knexjs.org/guide/#node-js
Also, WHY ARE YOU NOT HASHING YOUR PASSWORDS? That is the most basic security you should be doing at a minimum!

Related

Looping vue object in express/sql

I have a form that adds a project with x number of persons.
I'm using Nuxt with express and MySQL database.
I have a route method like this that inserts a project to my database:
app.post('/addNewProject', function (req, res) {
var sql = "INSERT INTO project (name, startDate, endDate) VALUES ('"+req.body.projectName+"', '"+req.body.projectStart+"', '"+req.body.projectEnd+"'); INSERT INTO persons (projectID, name, workHours) VALUES (LAST_INSERT_ID(), '"+req.body.persons[0].personName+"', '"+req.body.persons[0].personHours+"')";
connection.query(sql, function (err, rows) {
if (err) throw err
res.send(rows)
})
})
The persons is a vue object persons: [{ personName: '', personHours: '' }], that can be filled in the form.
So since its persons[0] now, it only adds the first item to the database.
Im wondering if there is a way to loop the object inside this sql variable.
And I think I have to loop it here since I need the LAST_INSERT_ID() because I need to get the projectID that is a AUTO_INCREMENT primary key in the project table.
I have tried to use sql wihle loop but it doesn't seem to work here.

Nodejs passport setup confusion

I have been trying to setup my Nodejs MySQL database configuration. I found this passport.js config for MySQL on Github. The config works properly but there is a part that I do not understand.
var insertQuery = "INSERT INTO users ( email, password ) values ('" + email +"','"+ password +"')";
console.log(insertQuery);
connection.query(insertQuery,function(err,rows){
newUserMysql.id = rows.insertId;
return done(null, newUserMysql);
});
I am confused about the insertID field. The table I am using does not have a field called insertID. It does however have a field named ID. I tried changing that line to
newUserMysql.id = rows.Id;
bu doing so gives me:
Error: Failed to serialize user into session
Leaving it as it is gives me no error
Looks like insertID has nothing to do with the ID field of my table but I do not understand what it means
That probably represents LAST_INSERT_ID() which is the ID of the last row inserted.
The response of an INSERT is not "rows" but a result object, so maybe better named it'd be:
connection.query("...", function(err, result) {
newUserMysql.id = result.insertId;
return done(null, newUserMysql);
});
It's important to note that using Promises dramatically simplifies your code, and async/await can take that even further. This could be as simple as:
let result = await connection.query("...");
newUserMysql.id = result.insertId;
return newUserMysql;
Where that's inside an async function with a Promise-driven database library like Sequelize. You're not handling the potential errors in your first case. In the second you'll get exceptions which will wake you up when there's problems.

email verification from database using express js node js and angular 6 with mysql database

i am creating a user, with 'email' field so i want to verify whether that email is already exist or not, if exists error must display. i have my code in express js, node js, angular 6 and mysql database and below is the code to create new user
exports.create = (req, res) => {
// Save to MySQL database
let customer = req.body;
Customer.create(customer).then(result => {
// Send created customer to client
res.json(result);
});
};
where should i use if statement in above code
Thanks in advance
I'm thinking the simplest way of solving your problem is making the email column in the database unique. If you try to insert a new user with an already existing email the query will fail.
Another solution would be that you first do a query that looks in the database if an already existing user has the email (from req.body.email). But that would require having two different SQL queries, which I personally would not prefer.
i think you are using Sequelize ORM.
You can do like this
Customer.findOrCreate({
where: {
email: req.body.email,
},
// other datas needs to inserted
defaults: {
name: req.body.name,
username: req.body.username,
},
}).spread((data, created) => {
if (created) {
// your logics
} else {
res.status(400).send(`${req.body.email} already exists.`);
}
});

NodeJs and MySQL ER_BAD_FIELD_ERROR

I have a problem I need help with a question. So the problem is I have a route to display all rows of my students table and it works, but know when I try the code below to search for a specific student_id I get:
"Failed to query for users: Error: ER_BAD_FIELD_ERROR: Unknown column 'undefined' in 'where clause'"
I have tried the queryString as:
My table has student_id, firstName, lastName, checkIn, and checkOut as columns.
They are all VARCHARS.
queryString = SELECT * FROM students WHERE student_id = ${id}
queryString = SELECT * FROM students WHERE student_id = ? and then getConnection().query(queryString, [id], (err, rows, fields) => {
But I get the same error, I would really appreciate the help.
The question that I have would be implementing after all my different search routes work as intended to display the data nicely in html, but I'm new to this and I can't find anything to help me with this problem. I would like it to display as a list almost like MySQL displays it. Is that possible? I'm using the ejs view engine as my html pages.
// Route to search by id
router.get("/searchById", (req, res) => {
const id = req.body.id
queryString = `SELECT * FROM students WHERE student_id = ${id}`
getConnection().query(queryString, (err, rows, fields) => {
// If error occures
if(err) {
console.log("Failed to query for users: " + err)
res.sendStatus(500)
return
}
if(rows) {
console.log(rows)
console.log("We fetched Students successfully")
res.json(rows)
}
})
})
For GET request you should use req.query.id
For post request you should use req.body.id
In your code you have used get request and tried to fetch req.body.id

store mysql query results in redis

I am trying to use redis to store a list of users and weather or not they are online or offline and displaying that information to other users.
I am fairly new to node and I believe that I need to use either a list or sorted sets.
when it gets to the console.log(reply); line it only shows "Object"
I think I need to loop through the results of the query to build the list but I am not really sure 1) how to loop through the results directly in the server application and 2) how to build the list or sorted set based on that query.
Any advice or suggestions would be greatly appreciated.
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'password',
database : 'users'
});
var redis = require('redis')
, client = redis.createClient();
connection.connect();
connection.query('SELECT * FROM user_profile', function(err, rows, fields)
{
if (err) throw err;
client.set('string key', rows[0], redis.print);
client.get("string key", function (err, reply) {
console.log(reply);
});
});
connection.end();
1) I assume rows contains an array of objects, each object representing a user data record.
client.set('string key', rows[0], redis.print);
is storing the whole first object of rows array, you can use a foreach statement to loop over all values returned.
You are saving the whole object in redis, but you only need the online/offline state 1 or 0. Besides, you can store only strings in redis keys (see Redis Keys Docs and Redis Set Docs)
2) You don't need a list or sorted sets only for online/offline state of a user, unless you need some sorting operations later.
You can use simple keys, I suggest using a pattern like this for key name: "user:".
// assuming that user_name property exists, holds username data "david" and it's unique
client.set("user:"+row[0].user_name, 0, redis.print); // stores key "user:david" = "0";`
Then to retrieve it use:
client.get("user:"+row[0].user_name);
So, your sql query callback function could look like this:
function(err, rows, fields) {
if (err) throw err;
rows.forEach(function(element, index, array){
client.set('user:'+element.user_name, 0, redis.print);
client.get("user:"+element.user_name, function (err, reply) {
console.log(reply);
});
});
}
Please note that the user name must be unique. You can use user ID's if not