Save to database on change, angular and node js - node.js

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 :)
};

Related

Prevent SQL injection in api call

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

How can I run a search in my postgress database, return the result and then send it to be displayed on an ejs page?

I am using Node.js w/ Heroku & Postgres
My code needs to pull data from Postgres, store that data, send that data to a webpage to be displayed.
The code looks like this. I want to get the information from
SELECT * FROM people;, then I want to store it somehow, and then I want to res.render it onto 'pages/sql'.
So when I visit myURL.com/sql I will see a stringified version of the results gotten from the database. So far I can see this information in my console when I run heroku logs --tail but I want it to be rendered on a live webpage visible to anybody.
Ideally I'd like to be able to do a lot more than this, but this would help for now.
By wanting to do much more I'd like to eventually find out how to have a full ejs webpage and to pull in a large amount of data from the db onto one page and not use res.render just for one table.
const { Client } = require('pg');
const client = new Client({
connectionString: process.env.DATABASE_URL,
ssl: true,
});
app.get('/sql',function(req,res){
res.status(200);
client.connect();
client.query('SELECT * FROM people;', (err, res) => {
if (err) throw err;
for (let row of res.rows) {
console.log(JSON.stringify(row));
}
client.end();
})
res.render('pages/sql', {body:"HELLO"});
});
Ideally where it says HELLO, I would be sending the data I get from the stringified JSON
So you have to send the response when you got the result, so you should do something like this
app.get('/sql',function(req,res){
res.status(200);
client.connect();
client.query('SELECT * FROM people;', (err, res) => {
if (err) throw err;
for (let row of res.rows) {
// If you want to get the single row
res.render('pages/sql',JSON.stringify(row));
console.log(JSON.stringify(row));
}
// if you want all rows return then
res.render('pages/sql',JSON.stringify(res.rows));
client.end();
})
});

Effective way to get data that's needed on all pages

I'm using nodejs and express and I have a navigation menu that is built using data that is in mongodb currently I'm just making a call to the database to get a list of companies and passing that back inside each route. There doesn't seem to be a way to store this information in localstorage client side. So I"m wondering what is the most effective way to handle this situation. Sample of my code
admin.get('/', function(res, resp){
mongodb.connect(url, function(err, db){
var collection = db.collection('companies')
collection.find({}).toArray(function(err, companies){
res.render('adminview', {companies:companies})//once the page is rendered I would like to save the company list to localstorage.
})
})
})
admin.get('/:company', function(res, resp){
/* repeating code from above because I need this list */
mongodb.connect(url, function(err, db){
var collection = db.collection('companies')
collection.find({}).toArray(function(err, companies){
/* more code to do stuff to render the company page */
res.render('companyadminview', {companies:companies, company:company})
}) })
I could be going about this the wrong way I'm new to web development this feels wrong to me but can't figure out a different way.
So, first off you should be able to store it in localstorage or sessionstorage just fine, unless you're targeting browsers that don't support it.
That said, I think it's best not to, as the fact that you're storing it in the DB implies that it changes with enough frequency that you will get buggy clientside behavior if you cache it there for too long.
Instead, I'd just setup a middleware and attach it to the locals object on a per request basis, unless you want to do some kind of cache on the server:
app.use(function(req, res, next) {
mongodb.connect(url, function(err, db){
if (err) return next(err);
var collection = db.collection('companies')
collection.find({}).toArray(function(err, companies){
if (err) return next(err);
res.locals.companies = companies;
next();
});
});
});

Disconnect PostgreSQL when client goes to new page

I'm trying to build a real time web page and use postgreSQL as my database. I use node.js and express to build backend stuff. Since this is a real time webpage and needs to update information very frequently, I keep a long connection with postgreSQL, which looks like:
app.get('/:A/:B', function(req,res){
var A = req.params.A;
var B = req.params.B;
var client = new pg.Client(config[A][B]);
client.connect(function(err){
if (err) {
console.log("Error occurred when try to connect the database",err);
}
else {
console.log("Connected to the database");
}
});
Do some queries with current database connection...
}
The problem is, when I change the value of A and B in browser and try to connect to a new database, I didn't disconnect with the old one so the info on my page are still from the old database. I'm new to node and web development. Can anyone let me know how to disconnect with the old database when client try to go to a new url?
I think is not good way to create connection for each request. If size of A-B variants is limited then create of connection pool on start is better.
app.get('/:A/:B', function(req, res, next){ // next to forwarding error
var A = req.params.A;
var B = req.params.B;
var client = new pg.Client(config[A][B]);
client.connect(function(err){
if (err)
return next(err); // go to error-middleware
console.log("Connected to the database");
// Do some queries with current database connection...
// Keep it mind that they're also asynchronous, so better way is use promises or async (https://github.com/caolan/async)
client.end(function (err) {
if (err)
next(err);
});
});
}
// Error middleware
app.use(function(err, req, res, next) {
console.log(req.url, err.message);
})

Express keeping connection open?

I'm using node js, express and postgresql as backend.
This is the approach I used to make a rest API:
exports.schema = function (inputs, res) {
var query = knex('schema')
.orderBy('sch_title', 'asc')
.select();
query.exec(function (err, schemas) {
if(err){
var response = {
message: 'Something went wrong when trying to fetch schemas',
thrownErr: err
};
console.error(response);
res.send(500, response);
}
if(schemas.length === 0){
var message = 'No schemas was found';
console.error(message);
res.send(400, message);
return;
}
res.send(200, schemas);
});
};
It works but after a while postgres logs an error and it's no longer working:
sorry, too man clients already
Do I need a close each request somehow? Could not find any about this in the express docs. What can be wrong?
This error only occurs on production server. Not on developing machine.
Update
The app only brakes in one 'module'. The rest of the app works fine. So it's only some queries that gives the error.
Just keep one connection open for your whole app. The docs shows an example how to do this.
This code goes in your app.js...
var Knex = require('knex');
Knex.knex = Knex.initialize({
client: 'pg',
connection: {
// your connection config
}
});
And when you want to query in your controllers/middlewares...
var knex = require('knex').knex;
exports.schema = function (req, res) {
var query = knex('schema')
.orderBy('sch_title', 'asc')
.select();
// more code...
};
If you place Knex.initialize inside an app.use or app.VERB, it gets called repeatedly for each request thus you'll end up connecting to PG multiple times.
For most cases, you don't need to do an open+query+close for every HTTP request.

Resources