added helper function to remove sensitive data from forms/users

This commit is contained in:
David Baldwynn 2017-10-29 14:04:13 -07:00
parent aa554c8210
commit 3dbfe2f88d
7 changed files with 129 additions and 51 deletions

View File

@ -9,7 +9,8 @@ var mongoose = require('mongoose'),
FormSubmission = mongoose.model('FormSubmission'),
config = require('../../config/config'),
diff = require('deep-diff'),
_ = require('lodash');
_ = require('lodash'),
helpers = require('./helpers.server.controller');
/**
* Delete a forms submissions
@ -96,7 +97,7 @@ exports.listSubmissions = function(req, res) {
exports.create = function(req, res) {
if(!req.body.form){
return res.status(401).send({
return res.status(400).send({
message: 'Invalid Input'
});
}
@ -104,14 +105,15 @@ exports.create = function(req, res) {
form.admin = req.user._id;
form.save(function(err) {
form.save(function(err, createdForm) {
if (err) {
return res.status(500).send({
message: errorHandler.getErrorMessage(err)
});
}
return res.json(form);
createdForm = helpers.removeSensitiveModelData('private_form', createdForm);
return res.json(createdForm);
});
};
@ -132,6 +134,8 @@ exports.read = function(req, res) {
message: 'Form Does Not Exist'
});
}
newForm = helpers.removeSensitiveModelData('private_form', newForm);
return res.json(newForm);
}
};
@ -147,9 +151,7 @@ var readForRender = exports.readForRender = function(req, res) {
});
}
delete newForm.lastModified;
delete newForm.__v;
delete newForm.created;
newForm = helpers.removeSensitiveModelData('public_form', newForm);
if(newForm.startPage && !newForm.startPage.showStart){
delete newForm.startPage;
@ -165,11 +167,8 @@ exports.update = function(req, res) {
var form = req.form;
var updatedForm = req.body.form;
if(form.form_fields === undefined){
form.form_fields = [];
}
if(form.analytics === undefined){
if(!form.analytics){
form.analytics = {
visitors: [],
gaCode: ''
@ -213,6 +212,7 @@ exports.update = function(req, res) {
message: errorHandler.getErrorMessage(err)
});
} else {
savedForm = helpers.removeSensitiveModelData('private_form', savedForm);
res.json(savedForm);
}
});
@ -254,6 +254,8 @@ exports.list = function(req, res) {
});
} else {
for(var i=0; i<forms.length; i++){
forms[i] = helpers.removeSensitiveModelData('private_form', forms[i]);
forms[i].numberOfResponses = 0;
if(forms[i].submissions){
forms[i].numberOfResponses = forms[i].submissions.length;
@ -274,6 +276,7 @@ exports.formByID = function(req, res, next, id) {
message: 'Form is invalid'
});
}
Form.findById(id)
.populate('admin')
.exec(function(err, form) {
@ -286,12 +289,7 @@ exports.formByID = function(req, res, next, id) {
}
else {
//Remove sensitive information from User object
var _form = form;
_form.admin.password = null;
_form.admin.salt = null;
_form.provider = null;
req.form = _form;
req.form = helpers.removeSensitiveModelData('private_form', form);
return next();
}
});
@ -319,13 +317,7 @@ exports.formByIDFast = function(req, res, next, id) {
}
else {
//Remove sensitive information from User object
var _form = form;
if(_form.admin){
_form.admin.password = null;
_form.admin.salt = null;
_form.provider = null;
}
req.form = _form;
req.form = helpers.removeSensitiveModelData('public_form', form);
return next();
}
});

View File

@ -0,0 +1,44 @@
module.exports = {
removeSensitiveModelData: function(type, object){
var privateFields = {
'public_form': ['__v', 'analytics.visitors', 'analytics.views', 'analytics.conversionRate', 'analytics.fields', 'lastModified', 'created'],
'private_form': ['__v'],
'public_user': ['passwordHash', 'password', 'provider', 'salt', 'lastModified', 'created', 'resetPasswordToken', 'resetPasswordExpires', 'token', 'apiKey', '__v'],
'private_user': ['passwordHash', 'password', 'provider', 'salt', 'resetPasswordToken', 'resetPasswordExpires', 'token', '__v']
}
function removeKeysFromDict(dict, keys){
for(var i=0; i<keys.length; i++){
var curr_key = keys[i];
if( dict.hasOwnProperty(curr_key) ){
delete dict[curr_key];
}
}
}
switch(type){
case 'private_form':
removeKeysFromDict(object, privateFields['private_form']);
if(object.admin){
removeKeysFromDict(object.admin, privateFields['private_user']);
}
break;
case 'public_form':
removeKeysFromDict(object, privateFields['public_form']);
if(object.admin){
removeKeysFromDict(object.admin, privateFields['public_user']);
}
break;
default:
if(privateFields.hasOwnProperty(type)){
removeKeysFromDict(object, privateFields[type]);
}
break;
}
return object;
}
}

View File

@ -12,7 +12,8 @@ var errorHandler = require('../errors.server.controller'),
fs = require('fs'),
i18n = require('i18n'),
async = require('async'),
pug = require('pug');
pug = require('pug'),
helpers = require('../helpers.server.controller');
var nev = require('email-verification')(mongoose);
@ -179,6 +180,8 @@ exports.signin = function(req, res, next) {
}
res.cookie('langCookie', user.language, { maxAge: 90000, httpOnly: true });
user = helpers.removeSensitiveModelData('private_user', user);
return res.json(user);
});
}
@ -199,7 +202,7 @@ exports.signout = function(req, res) {
/* Generate API Key for User */
exports.generateAPIKey = function(req, res) {
if (!req.isAuthenticated()){
return res.status(400).send({
return res.status(401).send({
message: 'User is not Authorized'
});
}
@ -226,11 +229,8 @@ exports.generateAPIKey = function(req, res) {
}
var newUser = _user.toObject();
delete newUser.salt;
delete newUser.__v;
delete newUser.passwordHash;
delete newUser.provider;
newUser = helpers.removeSensitiveModelData('private_user', newUser);
return res.json(newUser);
});

View File

@ -5,7 +5,8 @@
*/
var _ = require('lodash'),
errorHandler = require('../errors.server.controller.js'),
mongoose = require('mongoose');
mongoose = require('mongoose'),
helpers = require('../helpers.server.controller');
/**
* Update user details
@ -32,6 +33,7 @@ exports.update = function(req, res) {
if (err) {
res.status(500).send(loginErr);
} else {
user = helpers.removeSensitiveModelData('private_user', user);
res.json(user);
}
});
@ -48,13 +50,9 @@ exports.update = function(req, res) {
* Send User
*/
exports.getUser = function(req, res) {
var _user = req.user;
delete _user.password;
delete _user.salt;
delete _user.provider;
delete _user.__v;
var _user = helpers.removeSensitiveModelData('private_user', req.user);
res.json(req.user || null);
res.json(_user);
res.end();
};

View File

@ -101,12 +101,17 @@ var FormSchema = new Schema({
visitors: [VisitorDataSchema]
},
form_fields: [FieldSchema],
submissions: [{
type: Schema.Types.ObjectId,
ref: 'FormSubmission'
}],
form_fields: {
type: [FieldSchema],
default: []
},
submissions: {
type: [{
type: Schema.Types.ObjectId,
ref: 'FormSubmission'
}],
dfeault: []
},
admin: {
type: Schema.Types.ObjectId,
ref: 'User',
@ -153,6 +158,7 @@ var FormSchema = new Schema({
type: Boolean,
default: false
},
isLive: {
type: Boolean,
default: true
@ -218,7 +224,7 @@ FormSchema.virtual('analytics.fields').get(function () {
var visitors = this.analytics.visitors;
var that = this;
if(this.form_fields.length === 0) {
if(!this.form_fields || this.form_fields.length === 0) {
return null;
}

View File

@ -85,8 +85,6 @@ var UserSchema = new Schema({
type: String,
default: 'local'
},
providerData: {},
additionalProvidersData: {},
roles: {
type: [{
type: String,

View File

@ -82,7 +82,7 @@ describe('Form Routes Unit tests', function() {
});
});
it(' > should be able to read/get a Form if not signed in', function(done) {
it(' > should be able to read/get a live Form if not signed in', function(done) {
// Create new Form model instance
var FormObj = new Form(myForm);
@ -104,6 +104,23 @@ describe('Form Routes Unit tests', function() {
});
});
it(' > should be able to read/get a non-live Form if not signed in', function(done) {
// Create new Form model instance
var FormObj = new Form(myForm);
FormObj.isLive = false;
// Save the Form
FormObj.save(function(err, form) {
if(err) return done(err);
userSession.get('/subdomain/' + credentials.username + '/forms/' + form._id + '/render')
.expect(401, {message: 'Form is Not Public'})
.end(function(err, res) {
done(err);
});
});
});
it(' > should not be able to delete an Form if not signed in', function(done) {
// Set Form user
myForm.admin = user;
@ -145,6 +162,16 @@ describe('Form Routes Unit tests', function() {
});
});
it(' > should not be able to create a Form if body is empty', function(done) {
loginSession.post('/forms')
.send({form: null})
.expect(400, {"message":"Invalid Input"})
.end(function(FormSaveErr, FormSaveRes) {
// Call the assertion callback
done(FormSaveErr);
});
});
it(' > should not be able to save a Form if no title is provided', function(done) {
// Set Form with a invalid title field
myForm.title = '';
@ -167,7 +194,20 @@ describe('Form Routes Unit tests', function() {
});
it(' > should be able to update a Form if signed in', function(done) {
it(' > should be able to create a Form if form_fields are undefined', function(done) {
myForm.analytics = null;
myForm.form_fields = null;
loginSession.post('/forms')
.send({form: myForm})
.expect(200)
.end(function(FormSaveErr, FormSaveRes) {
// Call the assertion callback
done(FormSaveErr);
});
});
it(' > should be able to update a Form if signed in and Form is valid', function(done) {
// Save a new Form
loginSession.post('/forms')
@ -181,7 +221,7 @@ describe('Form Routes Unit tests', function() {
}
// Update Form title
myForm.title = 'WHY YOU GOTTA BE SO MEAN?';
myForm.title = 'WHY YOU GOTTA BE SO FORMULAIC?';
// Update an existing Form
loginSession.put('/forms/' + FormSaveRes.body._id)
@ -196,7 +236,7 @@ describe('Form Routes Unit tests', function() {
// Set assertions
(FormUpdateRes.body._id).should.equal(FormSaveRes.body._id);
(FormUpdateRes.body.title).should.match('WHY YOU GOTTA BE SO MEAN?');
(FormUpdateRes.body.title).should.match(myForm.title);
// Call the assertion callback
done();