added tests for backend

This commit is contained in:
David Baldwynn 2015-08-11 13:32:27 -07:00
parent 9c22020214
commit 0476e51730
10 changed files with 201 additions and 174 deletions

View file

@ -54,10 +54,9 @@ var UserSchema = new Schema({
required: false, required: false,
trim: true trim: true
}, },
password: { passwordHash: {
type: String, type: String,
default: '', default: '',
validate: [validateLocalStrategyPassword, 'Password should be longer']
}, },
salt: { salt: {
type: String type: String
@ -129,21 +128,35 @@ UserSchema.pre('save', function (next) {
/** /**
* Hook a pre save method to hash the password * Hook a pre save method to hash the password
*/ */
UserSchema.pre('save', function(next) { UserSchema.virtual('password').set(function (password) {
if (this.password && this.password.length > 6) { this.passwordHash = this.hashPassword(password);
this.salt = crypto.randomBytes(16).toString('base64');
this.password = this.hashPassword(this.password);
}
next();
}); });
UserSchema.virtual('password').get(function () {
return this.passwordHash;
});
// UserSchema.pre('save', function(next) {
// if (this.password && this.password.length > 6) {
// this.salt = crypto.randomBytes(16).toString('base64');
// this.password = this.hashPassword(this.password);
// }
// next();
// });
/** /**
* Create instance method for hashing a password * Create instance method for hashing a password
*/ */
UserSchema.methods.hashPassword = function(password) { UserSchema.methods.hashPassword = function(password) {
if (this.salt && password) { //Generate salt if it doesn't exist yet
return crypto.pbkdf2Sync(password, new Buffer(this.salt, 'base64'), 10000, 64).toString('base64'); if(!this.salt){
this.salt = crypto.randomBytes(64).toString('base64');
}
if (password) {
return crypto.pbkdf2Sync(password, new Buffer(this.salt, 'base64'), 10000, 128).toString('base64');
} else { } else {
return password; return password;
} }
@ -188,5 +201,4 @@ UserSchema.methods.isAdmin = function() {
return false; return false;
}; };
mongoose.model('User', UserSchema); mongoose.model('User', UserSchema);

View file

@ -182,7 +182,7 @@ describe('Form Model Unit Tests:', function() {
// }); // });
afterEach(function(done) { afterEach(function(done) {
Form.remove({}, function() { Form.remove().exec(function() {
User.remove().exec(done); User.remove().exec(done);
}); });
}); });

View file

@ -1,118 +1,118 @@
'use strict'; // 'use strict';
var should = require('should'), // var should = require('should'),
_ = require('lodash'), // _ = require('lodash'),
app = require('../../server'), // app = require('../../server'),
request = require('supertest'), // request = require('supertest'),
Session = require('supertest-session')({ // Session = require('supertest-session')({
app: app // app: app
}), // }),
mongoose = require('mongoose'), // mongoose = require('mongoose'),
User = mongoose.model('User'), // User = mongoose.model('User'),
config = require('../../config/config'), // config = require('../../config/config'),
tmpUser = mongoose.model(config.tempUserCollection), // tmpUser = mongoose.model(config.tempUserCollection),
agent = request.agent(app), // agent = request.agent(app),
mailosaur = require('mailosaur')(config.mailosaur.key), // mailosaur = require('mailosaur')(config.mailosaur.key),
mailbox = new mailosaur.Mailbox(config.mailosaur.mailbox_id); // mailbox = new mailosaur.Mailbox(config.mailosaur.mailbox_id);
/** // /**
* Globals // * Globals
*/ // */
var credentials, _User, _Session; // var credentials, _User, _Session;
/** // /**
* Form routes tests // * Form routes tests
*/ // */
describe('User CRUD tests', function() { // describe('User CRUD tests', function() {
var userSession; // var userSession;
beforeEach(function(done) { // beforeEach(function(done) {
//Initialize Session // //Initialize Session
userSession = new Session(); // userSession = new Session();
// Create user credentials // // Create user credentials
credentials = { // credentials = {
username: 'test@test.com', // username: 'test@test.com',
password: 'password' // password: 'password'
}; // };
// Create a new user // // Create a new user
_User = { // _User = {
firstName: 'Full', // firstName: 'Full',
lastName: 'Name', // lastName: 'Name',
email: credentials.username, // email: credentials.username,
username: credentials.username, // username: credentials.username,
password: credentials.password, // password: credentials.password,
}; // };
console.info('config.mailosaur.mailbox_id: '+config.mailosaur.mailbox_id) // console.info('config.mailosaur.mailbox_id: '+config.mailosaur.mailbox_id)
done(); // done();
}); // });
it('should be able to create a temporary (non-activated) User', function(done) { // it('should be able to create a temporary (non-activated) User', function(done) {
userSession.post('/auth/signup') // userSession.post('/auth/signup')
.send(_User) // .send(_User)
.expect(200) // .expect(200)
.end(function(FormSaveErr, FormSaveRes) { // .end(function(FormSaveErr, FormSaveRes) {
(FormSaveRes.text).should.equal('An email has been sent to you. Please check it to verify your account.'); // (FormSaveRes.text).should.equal('An email has been sent to you. Please check it to verify your account.');
tmpUser.findOne({username: _User.username}, function (err, user) { // tmpUser.findOne({username: _User.username}, function (err, user) {
should.not.exist(err); // should.not.exist(err);
should.exist(user); // should.exist(user);
console.log(user); // console.log(user);
(_User.username).shoud.equal(user.username); // (_User.username).shoud.equal(user.username);
(_User.firstName).shoud.equal(user.firstName); // (_User.firstName).shoud.equal(user.firstName);
(_User.lastName).shoud.equal(user.lastName); // (_User.lastName).shoud.equal(user.lastName);
// Call the assertion callback // // Call the assertion callback
done(); // done();
}); // });
}); // });
}); // });
it('should be able to create and activate/verify a User Account', function(done) { // it('should be able to create and activate/verify a User Account', function(done) {
credentials.username = _User.email = _User.username = 'testUserCreation.be1e58fb@mailosaur.in'; // credentials.username = _User.email = _User.username = 'testUserCreation.be1e58fb@mailosaur.in';
userSession.post('/auth/signup') // userSession.post('/auth/signup')
.send(_User) // .send(_User)
.expect(200) // .expect(200)
.end(function(FormSaveErr, FormSaveRes) { // .end(function(FormSaveErr, FormSaveRes) {
should.not.exist(FormSaveErr); // should.not.exist(FormSaveErr);
(FormSaveRes.text).should.equal('An email has been sent to you. Please check it to verify your account.'); // (FormSaveRes.text).should.equal('An email has been sent to you. Please check it to verify your account.');
mailbox.getEmails(_User.email, // mailbox.getEmails(_User.email,
function(err, emails) { // function(err, emails) {
should.not.exist(err); // should.not.exist(err);
email = emails[0]; // email = emails[0];
console.log(email); // console.log(email);
done(); // done();
// userSession.get('/auth/verify/'+token) // // userSession.get('/auth/verify/'+token)
// .send(_User) // // .send(_User)
// .expect(200, 'User successfully verified') // // .expect(200, 'User successfully verified')
// .end(function (VerifyErr, VerifyRes) { // // .end(function (VerifyErr, VerifyRes) {
// should.not.exist(VerifyErr); // // should.not.exist(VerifyErr);
// }); // // });
} // }
); // );
}); // });
}); // });
afterEach(function(done) { // afterEach(function(done) {
User.remove().exec(function () { // User.remove().exec(function () {
tmpUser.remove().exec(function(){ // tmpUser.remove().exec(function(){
mailbox.deleteAllEmail(function (err, body) { // mailbox.deleteAllEmail(function (err, body) {
console.log(err); // console.log(err);
userSession.destroy(); // userSession.destroy();
}); // });
}); // });
}); // });
}); // });
}); // });

View file

@ -30,7 +30,7 @@ module.exports = {
secure: true, secure: true,
// Only set the maxAge to null if the cookie shouldn't be expired // Only set the maxAge to null if the cookie shouldn't be expired
// at all. The cookie will expunge when the browser is closed. // at all. The cookie will expunge when the browser is closed.
maxAge: null, maxAge: 7200,
// To set the cookie in a specific domain uncomment the following // To set the cookie in a specific domain uncomment the following
// setting: // setting:
domain: 'forms.polydaic.com' domain: 'forms.polydaic.com'

View file

@ -30,7 +30,7 @@
"connect-mongo": "~0.4.1", "connect-mongo": "~0.4.1",
"consolidate": "~0.10.0", "consolidate": "~0.10.0",
"cookie-parser": "~1.3.2", "cookie-parser": "~1.3.2",
"email-verification": "^0.1.9", "email-verification": "whitef0x0/node-email-verification",
"express": "~4.10.1", "express": "~4.10.1",
"express-session": "~1.9.1", "express-session": "~1.9.1",
"forever": "~0.11.0", "forever": "~0.11.0",

View file

@ -475,22 +475,33 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope
$state.go(route, {'formId': id}, {reload: true}); $state.go(route, {'formId': id}, {reload: true});
}; };
$scope.duplicate = function(form, form_index){
delete form._id;
$http.post('/forms', {form: form})
.success(function(data, status, headers){
console.log('form duplicated');
$scope.myforms.splice(form_index, 0, data);
}).error(function(errorResponse){
console.log(errorResponse);
$scope.error = errorResponse.data.message;
});
}
// Create new Form // Create new Form
$scope.createNew = function(){ $scope.createNew = function(){
var form = {}; var form = {};
form.title = $scope.myform.name.$modelValue; form.title = $scope.myform.name.$modelValue;
form.language = $scope.myform.language.$modelValue; form.language = $scope.myform.language.$modelValue;
console.log(form); // console.log(form);
$rootScope.showCreateModal = true; $rootScope.showCreateModal = true;
console.log($scope.myform); // console.log($scope.myform);
if($scope.myform.$valid && $scope.myform.$dirty){ if($scope.myform.$valid && $scope.myform.$dirty){
$http.post('/forms', {form: form}) $http.post('/forms', {form: form})
.success(function(data, status, headers){ .success(function(data, status, headers){
console.log('form created'); console.log('form created');
// Clear form fields
$scope.myform = {};
// Redirect after save // Redirect after save
$scope.goToWithId('viewForm', data._id+''); $scope.goToWithId('viewForm', data._id+'');
}).error(function(errorResponse){ }).error(function(errorResponse){
@ -500,28 +511,17 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope
} }
}; };
$scope.remove = function(form_id) { $scope.removeFromList = function(deleted_form_id) {
console.log('Remove existing form'); console.log('Remove existing form');
var form = {};
if(!form_id){
form = CurrentForm.getForm();
if(!form) form = $scope.myform;
}else {
form._id = form_id;
}
$http.delete('/forms/'+form._id) $http.delete('/forms/'+deleted_form_id)
.success(function(data, status, headers){ .success(function(data, status, headers){
console.log('form deleted successfully'); console.log('form deleted successfully');
if(!form_id){
$state.go('listForms', {}, {reload: true});
}
if($scope.myforms.length > 0){ if($scope.myforms.length > 0){
$scope.myforms = _.filter($scope.myforms, function(myform){ $scope.myforms = _.filter($scope.myforms, function(myform){
return myform._id !== form._id; return myform._id !== deleted_form_id;
}); });
} }
@ -618,7 +618,6 @@ angular.module('forms').controller('ViewFormController', ['$rootScope', '$scope'
$event.stopPropagation(); $event.stopPropagation();
}; };
$scope.rowClicked = function(row_index) { $scope.rowClicked = function(row_index) {
// obj.selected = !obj.selected;
$scope.table.rows[row_index].selected = !$scope.table.rows[row_index].selected; $scope.table.rows[row_index].selected = !$scope.table.rows[row_index].selected;
}; };
@ -655,16 +654,16 @@ angular.module('forms').controller('ViewFormController', ['$rootScope', '$scope'
}; };
//Export selected submissions of Form //Export selected submissions of Form
$scope.exportSelectedSubmissions = function(){ $scope.exportSubmissions = function(){
// console.log('exportSelectedSubmissions'); // console.log('exportSelectedSubmissions');
var export_ids = _.chain($scope.table.rows).filter(function(row){ // var export_ids = _.chain($scope.table.rows).filter(function(row){
return !!row.selected; // return !!row.selected;
}).pluck('_id').value(); // }).pluck('_id').value();
var blob = new Blob([document.getElementById('table-submission-data').innerHTM], { var blob = new Blob([document.getElementById('table-submission-data').innerHTM], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8" type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"
}); });
saveAs(blob, $scope.form.title+'_export_'+Date.now()+".xls"); saveAs(blob, $scope.myform.title+'_export_'+Date.now()+".xls");
}; };
@ -849,7 +848,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
return false; return false;
}; };
var updateFields = function () { var debounceSave = function () {
$rootScope.saveInProgress = true; $rootScope.saveInProgress = true;
$rootScope[$attrs.autoSaveCallback](false, $rootScope[$attrs.autoSaveCallback](false,
function(err){ function(err){
@ -863,14 +862,12 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
console.error(err); console.error(err);
} }
}); });
} };
$scope.$watch(function(newValue, oldValue) { $scope.$watch(function(newValue, oldValue) {
if($scope.anyDirtyAndTouched($scope.editForm) && !$rootScope.saveInProgress){ if($scope.anyDirtyAndTouched($scope.editForm) && !$rootScope.saveInProgress){
// console.log('ready to save text input'); debounceSave();
// console.log('Saving Form');
updateFields();
} }
}); });
@ -900,7 +897,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
savePromise = $timeout(function() { savePromise = $timeout(function() {
console.log('Saving Form'); console.log('Saving Form');
updateFields(); debounceSave();
}); });
}else if($rootScope.finishedRender && $rootScope.saveInProgress){ }else if($rootScope.finishedRender && $rootScope.saveInProgress){
$rootScope.saveInProgress = false; $rootScope.saveInProgress = false;
@ -1053,10 +1050,7 @@ angular.module('forms')
}, },
// transclude: true, // transclude: true,
controller: function($scope){ controller: function($scope){
// Log that the directive has been linked.
// console.log( "Linked: editForm Controller");
/* /*
** Initialize scope with variables ** Initialize scope with variables
*/ */
@ -1069,7 +1063,7 @@ angular.module('forms')
return type; return type;
}); });
// accordion settings // Accordion settings
$scope.accordion = {}; $scope.accordion = {};
$scope.accordion.oneAtATime = true; $scope.accordion.oneAtATime = true;
@ -1081,9 +1075,8 @@ angular.module('forms')
*/ */
$scope.dropzone = { $scope.dropzone = {
handle: ' .handle' handle: ' .handle'
} };
// console.log($scope.myform);
// $scope.draggable = { // $scope.draggable = {
// connectWith: ".dropzone", // connectWith: ".dropzone",
@ -1199,6 +1192,33 @@ angular.module('forms')
// } // }
}; };
/*
** StartPage Button Methods
*/
// add new Button to the field
$scope.addButton = function (Button){
var lastButtonID = 0;
if($scope.myform.StartPage.buttons[$scope.myform.StartPage.buttons.length-1])
lastButtonID = $scope.myform.StartPage.buttons[$scope.myform.StartPage.buttons.length-1].button_id;
// put new option into fieldOptions array
Button.backgroundColor = '#5bc0de';
Button.button_id = lastButtonID;
Button.color = '#ffffff';
$scope.myform.StartPage.buttons.push(Button);
};
// delete particular option
$scope.deleteButton = function (button_index){
$scope.myform.StartPage.buttons.splice(button_index, 1);
};
/* /*
** Field Option Methods ** Field Option Methods
*/ */
@ -1277,7 +1297,7 @@ angular.module('forms').directive('fieldIconDirective', function($http, $compile
'statement': 'fa fa-quote-left', 'statement': 'fa fa-quote-left',
'yes_no': 'fa fa-toggle-on', 'yes_no': 'fa fa-toggle-on',
'number': 'fa fa-slack' 'number': 'fa fa-slack'
} };
$scope.typeIcon = iconTypeMap[$scope.typeName]; $scope.typeIcon = iconTypeMap[$scope.typeName];
}, },
@ -1331,7 +1351,7 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
scope.dateOptions = { scope.dateOptions = {
changeYear: true, changeYear: true,
changeMonth: true, changeMonth: true,
altFormat: "mm/dd/yyyy", altFormat: 'mm/dd/yyyy',
yearRange: '1900:-0', yearRange: '1900:-0',
defaultDate: 0, defaultDate: 0,
}; };
@ -1417,17 +1437,17 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCo
angular.element(document).ready(function() { angular.element(document).ready(function() {
$scope.selected = null; $scope.selected = null;
$scope.startPage = true; timeCounter.startClock()
$rootScope.setActiveField = function (field_id) { $rootScope.setActiveField = function (field_id) {
console.log('form field clicked: '+field_id); console.log('form field clicked: '+field_id);
$scope.selected = field_id; $scope.selected = field_id;
console.log($scope.selected); console.log($scope.selected);
} };
$scope.hideOverlay = function (){ $scope.hideOverlay = function (){
$scope.selected = null; $scope.selected = null;
console.log($scope.myForm); console.log($scope.myForm);
} };
$scope.submit = function(){ $scope.submit = function(){
var _timeElapsed = timeCounter.stopClock(); var _timeElapsed = timeCounter.stopClock();
@ -1454,8 +1474,8 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCo
$scope.exitStartPage = function () { $scope.exitStartPage = function () {
$scope.startPage = false; $scope.form.startPage.showStart = false;
} };
$scope.reloadForm = function(){ $scope.reloadForm = function(){
timeCounter.stopClock(); timeCounter.stopClock();
@ -1594,10 +1614,10 @@ angular.module('forms').service('FormFields', [
name : 'statement', name : 'statement',
value : 'Statement' value : 'Statement'
}, },
{ // {
name : 'natural', // name : 'natural',
value : 'Natural Language Input' // value : 'Natural Language Input'
}, // },
]; ];
} }
@ -1823,7 +1843,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
$scope.signin = function() { $scope.signin = function() {
User.login($scope.credentials).then( User.login($scope.credentials).then(
function(response) { function(response) {
console.log(response) // console.log(response);
Auth.login(response); Auth.login(response);
$scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User); $scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -28,7 +28,7 @@
<div class="col-sm-12 col-md-10"> <div class="col-sm-12 col-md-10">
<accordion close-others="accordion.oneAtATime" ui-sortable="dropzone" ng-model="myform.form_fields" class="dropzone"> <accordion close-others="accordion.oneAtATime" ui-sortable="dropzone" ng-model="myform.form_fields" class="dropzone">
<accordion-group is-open="accordion[$index].isOpen" ng-if="myform.startPage.showStart"> <!-- <accordion-group is-open="accordion[$index].isOpen" ng-if="myform.startPage.showStart">
<accordion-heading> <accordion-heading>
@ -130,14 +130,10 @@
</div> </div>
</div> </div>
<!-- <div class="row description">
<div class="col-md-4 col-sm-12">Button Text:</div>
<div class="col-md-8 col-sm-12">
<textarea type="text" ng-model="form.startPage.buttonText" name="buttonStartPage" value="{{form.startPage.buttonText}}"></textarea>
</div>
</div> -->
</div> </div>
</accordion-group> </accordion-group> -->
<accordion-group ng-repeat="field in myform.form_fields" is-open="accordion[$index].isOpen" on-finish-render="editFormFields" ng-if="!field.deletePreserved"> <accordion-group ng-repeat="field in myform.form_fields" is-open="accordion[$index].isOpen" on-finish-render="editFormFields" ng-if="!field.deletePreserved">

View file

@ -22,8 +22,7 @@ var db = mongoose.connect(config.db.uri, config.db.options, function(err) {
mongoose.connection.on('error', function(err) { mongoose.connection.on('error', function(err) {
console.error(chalk.red('MongoDB connection error: ' + err)); console.error(chalk.red('MongoDB connection error: ' + err));
process.exit(-1); process.exit(-1);
} });
);
// Init the express application // Init the express application
var app = require('./config/express')(db); var app = require('./config/express')(db);