I have a React project. It has a PostgreSQL database. I created the api calls. Im pretty sure the way I have it written makes it succeptable to SQL injection. How can I rewrite it that can avoid this? Keeping in mind I have tons of api calls I would have to rewrite.
app.post("/comment/add", function (req, res) {
let sqlquery = `INSERT INTO dbo.comments(
eqid,empid,comment, createddate)
VALUES ('${req.body.eqid}', '${req.body.empid}', '${req.body.comment}',now()
) RETURNING commid`;
try{
console.log(req.body)
pool.query(sqlquery, (err, result) => {console.log(result , err)
if (result.rowCount) {
res.json({eqid:result.rows[0].eqid});
}else {
console.log(err);
res.status(400).json({ error: "Error while adding comment" });
}
});
}catch(error){
}
});
Add validation to your params (req.body , req.params etc), and proceed to run query only if valid params are received.
You can build your own custom middlewares for apis that does so , or use other services for example if using express express-validator
Related
I am kind of stuck at something, I am working on a personal blog that is full stack using mongodb with node.js and express. In that blog website only one user can sign up, and all posts are connected to that user. I am using the REST API to create a controller that deletes a user along with all the posts. I have the User and the Post object available and I was wondering if there is a way where I can use the User and Post schema objects to delete the user and ALL posts. I dont want to use the db.collection('posts') thing because I havent used that anywhere else. I went through mongodb node.js driver docs and I still cant figure out how to do it.
exports.deleteUser = (req, res, next) => {
User.find().then(user => {
//what do i do here?
})
.catch(err => {
if (!err.statusCode) {
err.statusCode = 500;
}
// you need to do next() otherwise error will not reach
// our middlewear in app.js file
next(err);
})
Post.find().then(allPosts => {
if (!allPosts) {
//what do i do here?
}
res.status(200).json({message: message})
})
.catch(err => {
if (!err.statusCode) {
err.statusCode = 500;
}
// you need to do next() otherwise error will not reach
// our middlewear in app.js file
next(err);
})
}
I would recommend using deleteOne and deleteMany directly instead of using find.
I am working on API Get request. I have created a POST request to add the data in firebase realtime database. The code is as follows:
// CREATE POST
app.post("/post", (req, res) => {
let key;
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in.
var newPost = firebase.database().ref("posts/");
var myPost = newPost.push({
createdBy: user.uid,
from: req.body.from,
to: req.body.to,
duration: req.body.duration,
comments: req.body.comments,
});
res.send(newPost);
const postId = myPost.key;
console.log(postId);
} else {
// No user is signed in.
res.status(404).send("No user is signed in right now!");
}
});
});
Now, in order to get a specific post, I have written the following code:
// GET SPECIFIC POST
app.get("/post/:id", (req, res) => {
let response;
firebase
.database()
.ref("posts/" + req.params.id)
.on("value", (snapshot) => {
response = snapshot.val();
});
res.send(response);
});
I am new at Firebase, so I dont really know how to get a specific post. Please help me out
Calls to Firebase are asynchronous, because they require a call to the server. While that call is happening, your main code continues. And then when the data is available, your callback is invoked with the data from the server.
Right now your res.send(response) runs before the response = snapshot.val() is ever called. The rule with asynchronous APIs is simple: any code that needs the data needs to be inside the callback, or be called from there.
So in your case:
app.get("/post/:id", (req, res) => {
firebase
.database()
.ref("posts/" + req.params.id)
.once("value")
.then((snapshot) => {
res.send(snapshot.val());
});
});
You'll note that I also change from on to once, since you only care about getting the value once (instead of attaching a permanent listener that monitors the database for changes).
Dealing with asynchronous API is a common stumbling block, so I recommend spending some time reading these answers to learn more:
Why Does Firebase Lose Reference outside the once() Function?
Firebase response is too slow
Best way to retrieve Firebase data and return it, or an alternative way
I simply did this:
app.get("/post/:id", (req, res) => {
var key = req.params.id;
console.log(key);
firebase
.database()
.ref("posts")
.child(key)
.get()
.then((snapshot) => {
res.send(snapshot.val());
});
});
this solved the problem
I'm using Node and Express and vanilla Postgres (no ORM) to create a simple CRUD API.
I have the following endpoint to delete a resource:
// #desc Delete an Envelope
// #route DELETE /api/v1/envelopes/:id
exports.deleteEnvelope = async (req, res) => {
const { id } = req.params;
try {
const sql = "DELETE FROM envelopes WHERE id=$1";
await db.query(sql, [id]);
console.log("Data deleted");
return res.status(200).send({
message: "Envelope deleted",
});
} catch (err) {
return res.status(500).send(err);
}
};
I realized this query doesn't have error handling when deleting non-existing records. I'm not sure what the best way to handle this would be. Should I make another SQL query to search for the record and handle that query? Any suggestions?
There will be no error if the record doesn't exist.
If you mean there is a requirement that your service should return an error when the record doesn't exist, then yes, I suggest you to make another query that finds the row you're about to delete. If the query returns an empty result, you return an error to the client.
The Problem
I deployed a create-react-app webapp to aws ec2. It's used to display data from a database and send data to it. I use ExpressJS, CORS and MySQL.
With the following code i fetch the corresponding URL and the server.js sends back the database content. Until here, everything works fine.
getBets = _ => {
fetch("http://ec2***.amazonaws.com
.then(response => response.json())
.then(response => this.setState({bets: response.data}))
.catch(err => console.error(err))
};
The problem begins when sending data to the database with the following code:
addBet = _ => {
const { bet } = this.state;
fetch(`http://ec2***.amazonaws.com/bets/add?name=${bet.person_name}&bet=${bet.time_bet}`)
.then(response => response.json())
.then(this.getBets)
.catch(err => console.error(err))
};
On click the addBet-function populates the db, but in chrome I following error:
GET http://ec2***.amazonaws.com/bets/add?name=Peter%20Pan5&bet=10:17%205 net::ERR_EMPTY_RESPONSE
and
TypeError: Failed to fetch
Regarding chrome dev-tools, the first error corresponds to the fetch in the addBet function and the second error to the catch part.
On the server side I've the following code for processing the fetch:
app.get("/bets/add", (req, res) => {
const {name, bet} = req.query;
const INSERT_BET = `INSERT INTO bets (name, bet, timestamp) VALUES("${name}", "${bet}", CURTIME())`;
connection.query(INSERT_BET, (err, res) => {
if (err) {
return res.send(err);
}
else {
return res.send("succesfully added your bet");
}
})
});
I want to mention, that the res paramter in the app.get part is unused. That tells me my IDE.
After a lot of hours digging deeper in the topics of expressJS and the fetch api, I guess, that the app.get part doesn't send a response to the server. But the fetch need some response.
My Question
How do I have to change the code in the app.get part to send a proper response back to the server?
AND
Am I right with my guess?
In MYSQL when you do an insert query you get back err,results and fields in the callback function like this:
connection.query('INSERT INTO posts SET ?', {title: 'test'}, function (error,
results, fields) {
if (error) throw error;
console.log(results.insertId);
});
You have used the parameter res for result and then you have used res.send() which now corresponds to that res parameter in the callback function and not the res object.Rewrite it like this:
app.get("/bets/add", (req, res) => {
const {name, bet} = req.query;
const INSERT_BET = `INSERT INTO bets (name, bet, timestamp) VALUES(?,?,?)`;
connection.query(INSERT_BET,[name,bet,CURTIME()] ,(err, result) => {
if (err) {
return res.send(err);
}
else {
return res.send("succesfully added your bet");
}
})
});
I have also used prepared statement in place of normal sql queries. These are used to prevent sql injections. I hope it will work now.
I'm converting an MS Access database to a webapp. I'm using Angular JS, Node JS with the express framework and MySQL as database.
In ms access you don't have any edit/save features. When you edit something, the database changes instantly. I like this. Feels smooth. So I want to have this the same way in the web app. My question is. Will there be any problems with this approach in my webbapp?
This is a piece of my node js code which updates the database with a restcall:
/*
Post /api/products/ HTTP/1.1
*/
exports.editProduct = function(req, res) {
console.log(req.body);
var post = [{title_en: req.body.title_en},req.params.id];
if (connection) {
connection.query("UPDATE products SET ? WHERE id = ?", post, function(err, rows, fields) {
if (err) throw err;
res.contentType('application/json');
res.write(JSON.stringify(rows));
res.end();
});
}
};
And on the client side I use the a the $resource object
$scope.save = function(){
$scope.product.$save(function(){
console.log('Save successfull);
});
};
And in the view. I simply have inputs with ng-change:
<input ng-model="product.title_en" ng-change="save()".
Will this work good in production mode with a couple hundred users? Is the chances of blocking/crashing etc?
The only thing I see is if (err) throw err;
if there is an error the server crash so change it with a json response with a 500 status.
By the way express has a build-in way to output json
It's better off to validate title_en and id
exports.editProduct = function(req, res) {
console.log(req.body);
var post = [{title_en: req.body.title_en},req.params.id];
if (connection) {
connection.query("UPDATE products SET ? WHERE id = ?", post, function(err, rows, fields) {
if (err) {
return res.json(500,{ error: 'Cannot update the product' });
}
res.json(200,rows);
});
}
an other thing try to use restangular instead of resource it's a lot of fun :)
};