Sanitizing input fields in express app - mongodb

I have several input fields for emails on my website. For these, I have 1 POST-route:
app.post('/', function(req, res){
Email.create(req.body.email, function(err, newEmail){
if(err){
console.log(err);
} else {
res.redirect('/');
};
});
});
The bootcamp I am learning from tells me that nefarious actors could use scripts in these inputs. However, when I try something like this:
<script>alert('test')</script>
nothing happens. In fact, it just gets added to my mongo database.
I installed express-sanitizer anyway as the bootcamp suggested and did this:
app.post('/', function(req, res){
req.body.email = req.sanitize(req.body.email);
Email.create(req.body.email, function(err, newEmail){
if(err){
console.log(err);
} else {
res.redirect('/');
};
});
});
However, when I do this and I input something I get an error stating 'ObjectParameterError' when I put in any string or script.
My app.use's look like this:
app.use(bodyParser.urlencoded({extended: true}));
app.use(expressSanitizer());
Any suggestions on how to best protect myself against scripts and how to implement express-sanitizer correctly?

It might be an issue with how you're doing the value changing.
I've done mine like this and it works:
const expressSanitizer = require('express-sanitizer')
let bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true}))
//For Sanitising SQL
app.use(expressSanitizer())
And then when I want to sanitise:
//Pulling the sanitised values from request body
var name = req.sanitize(req.body.name)
var email = req.sanitize(req.body.email)

Instead of sanitizing entire object try to sanitize only the required one.
req.body.email = req.sanitize(req.body.email) should look like this req.body.email.yoursanitizationfield = req.sanitize(req.body.email.yoursanitizationfield);
req.body.email.yoursanitizationfield = req.sanitize(req.body.email.yoursanitizationfield);
Email.create(req.body.email, function(err, newEmail){
if(err){
console.log(err);
} else {
res.redirect('/');
};
});
});```

Can I suggest adding some debugging to get insights to program execution. Add a console.log(req.body.email); after req.body.email = req.sanitize(req.body.email); to see if that has worked? (Or indeed if the execution has even reached that point.)

Related

How do I check if a field already exists in the database?

My problem is about checking if the name or email of a staff already exist in the database. They say its good to do it in the pre update middleware. I tried it but it's not working.
Im passing the (id_of_staff, updatedStaff_info and callback_function) to the update function.
Here's my update function:
module.exports.updateStaff = function(id, updatedStaff, callback){
var query = {_id: id};
Staff.update(query, updatedStaff, callback);
}
Everytime the Staff.update() is called the pre update middleware is executed. What I want here is check if the name or email if they already exist. The problem is, it seems that the name and email in the pre update middleware is undefined.
My pre update middleware:
staffSchema.pre("update", function(next){
var staff = this;
Staff.find({_id:{$ne: staff.id}, $or:[{name: staff.name}, {email: staff.email}]}, function (err, docs) {
if (!docs.length){
next();
}else{
next(new Error("Name or email already exist"));
}
});
});
The result that I got is always "Name or email already exist". And I tried to print in the console log the value of staff.name but it says its undefined. Am I doing it right? Can you help me to get it working. Thank you very much guys.
I found a solution to my question. Instead of using pre update middleware, I just create a function to check if the name or email already exist.
Here's the code:
module.exports.updateStaff = function(id, updatedStaff, callback){
var query = {_id: id};
//check name and email if already available
function updateStaff(id, updatedStaff, callback){
//get staff that has the same name or email
Staff.find({_id:{$ne:id}, $or:[{name: updatedStaff.name}, {email_pc: updatedStaff.email_pc}]}).exec(
function(err, result){
console.log(result);
if(!err){
if(result.length){
console.log("Name or email already exist.");
callback("Conflict", null);
}
else{
//udpate the staff
Staff.update(query, updatedStaff, callback);
}
}else{
callback(err);
}
})
}
updateStaff(id, updatedStaff, callback);
}
But I'm still open to answer using pre update middleware. Thanks :)

Post TypeScript Object without '_id' field?

I use Express, Mongoose and Angular 2 (TypeScript) making an web app. Now I want to post a MyClass Instance without any _id field.
In mongoose we could use _id to do a lot of operations on mongoDB, so here is what I have done on the server side using mongoose
router.post('/', function(req, res, next) {
Package.create(req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
/* GET /package/id */
router.get('/:id', function(req, res, next) {
Package.findById(req.params.id, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
/* PUT /package/:id */
router.put('/:id', function(req, res, next) {
Package.findByIdAndUpdate(req.params.id, req.body, function (err, post, after) {
if (err) return next(err);
res.json(post);
});
});
To contain the field _id I created a ts Class like this:
export class Package{
constructor(
public guid: string,
...
[other fields]
...
public _id: string
){}
}
Please note the _id at the end.
In my angular 2 service I am doing this to post the json object to server
//create new pakcage
private post(pck: Package): Promise<Package> {
let headers = new Headers({
'Content-Type': 'application/json'
});
return this.http
.post(this.packageUrl, JSON.stringify(pck), { headers: headers })
.toPromise()
.then(res => res.json())
.catch(this.handleError);
}
Then I received an error as shown in the screenshot below:
In which it indicates that the object I post back got a empty _id field.
How do I post a ts class without the _id field or should I do it totally differently?
Since no one has given an answer I went to the internet and found a good example of how to implement a Angular2 -- Mongoose -- Express System.
https://github.com/moizKachwala/Angular2-express-mongoose-gulp-node-typescript
A very good example with the original Hero App from official tutorial. Although it is based on RC1 but it provides a good start point on how to do the RESTFUL Request properly.
Hope this would help someone who is looking for a similar answer.

Express JS routing based on the user names

I am working on a express js project.I have got all my basic routing set up working perfectly. Usually when I want to search a record based on id I do this:
router.route('/sensors_home/:sensor_id')
.get(function (req, res) {
Sensor.findById(req.params.sensor_id,function(err, sensorInfo) {
if (err)
res.send(err);
res.send(sensorInfo);
});
});
This allows me to retrieve the data when I do http://localhost:4000/sesnors_home/45000cbsfdhjbnabfbajhdb
(45000cbsfdhjbnabfbajhdb = Object id from the MongoDB )
Now my goal is to have several users to my application. I have my mongoose schema set up and the mongoDB looks like this :
Here is the issue: I wanna retrieve data corresponding to John Peterson based on his _id that is "John".Instead of doing this http://localhost:4000/sesnors_home/45000cbsfdhjbnabfbajhdb I wanna do something like this http://localhost:4000/sesnors_home/John and retrieve all the data specific to John. I tried various methods but still stuck with this issue. I tried using req.params._id and also some Mongodb queries on the User Collection but still no luck. Please suggest some ideas.
Thanks!
UPDATE:
I tried using the following code :
router.route('/sensors_home/:id')
.get(function (req, res) {
res.send(_id.toString());
User.findOne({_id: req.params._id} ,function(err, sensorInfo) {
if (err)
res.send(err);
res.send(sensorInfo);
});
});
This gives me the following error :
ReferenceError: _id is not defined
Have you tried the following?
router.route('/sensors_home/:_id')
.get(function (req, res) {
Sensor.findOne({_id: req.params._id},function(err, sensorInfo) {
if (err)
res.send(err);
res.send(sensorInfo);
});
});

How to Use NodeJs without Mongoose

I am getting really good at NodeJs and AngularJs. After building a sizable application, I have come to the conclusion that Mongoose is not for me. I want to use pure MongoDb.
I have done a pretty good job refactoring my server code. I pulled all my functions out of my routes and into controllers. Currently however, my controllers are using Mongoose and they are connected to Mongo via the schema.
Current code:
var express = require('express'),
errMsg = require('../../../utilities/errorMsg'),
MyMongooseSchema = require('./models/myMongooseModel');
module.exports = {
all: function (req, res) {
MyMongooseSchema.find({}).exec(function (err, results) {
if (err) {
....
});
}
res.send(results);
})
}
Again I do not want this. I want the dynamism of MongoDb. I tried this to no avail.
db.js:
function MongoDbConnect(dbName){
var db = 'mongodb://localhost/' + dbName;
MongoClient.connect(db, function (err, db) {
if(err){
console.log('Error connecting to database')
} else {
return db; }
});}
exports.MongoDbConnect = MongoDbConnect;
controller: [that is called from respective router]
var database = require('../../../config/db');
module.exports = {
all: function (req, res) {
var db = database.MongoDbConnect('myDbName');
db.collection('MyCollectionName').find({}, function (err, results) {
if (err) {
return res.status(400).send({
message: errMsg.getErrorMessage(err)
});
}
res.send(results);
})
}}
Obviously, this is not working.
What would be the appropriate way to create a well refactored database connection that any controller can call on, with whatever database the controller needs?
Thank you.
Hey everybody, thanks sooooo much for your help !
var mongoskin = require('mongoskin');
var db = mongoskin.db('mongodb://localhost:27017/myDatabase?auto_reconnect', {safe:true});
db.collection('Menu').find({}).toArray(function(error, menu){
if (error) return next(error);
res.send(menu || [])
})

Mongoose findByIdAndUpdate not working

I have a fairly straight forward method below to update a document based on its ObjectId. It does not return an error but it fails to make the required updates to the document. I think it is failing because, according to my research, findByIdAndUpdate() takes only plain Javascript whereas job._id is an ObjectId from the document that I want to update. Can someone tell me how to make this work correctly?
function handleEncoderResponse(xmlResponse, job) {
var r = et.parse(xmlResponse);
var mediaID = r.findtext('./MediaID');
var message = r.findtext('./message');
EncodingJob = mongoose.model('EncodingJob');
EncodingJob.findByIdAndUpdate( job._id, {
"MediaID": mediaID,
"Status": message
}, function(err, result) {
if (err) console.log(err);
console.log(result);
});
}
Edit: Per this question Mongoose update document Fail with findByIdAndUpdate
I also tried the following code to no avail.
job.MediaID = mediaID;
job.Status = message;
job.save(function(err, res) {
if(err) console.log(err);
});
This approach yields the issue. It does not update the document and it does not return an error.
As it turns out, my mistake was forgetting to define MediaID and Status in the Schema as follows:
var encodingJobSchema = new mongoose.Schema({
...
MediaID: String,
Status: String
});