diff --git a/app/controllers/forms.server.controller.js b/app/controllers/forms.server.controller.js index a7092a27..0eb1c1ca 100644 --- a/app/controllers/forms.server.controller.js +++ b/app/controllers/forms.server.controller.js @@ -76,14 +76,10 @@ exports.createSubmission = function(req, res) { } var form = req.body.form; - + /* if (form.selfNotifications && form.selfNotifications.enabled && form.selfNotifications.recipients) { - var formFieldDict = {}; - form.form_fields.forEach(function(field){ - formFieldDict[field._id] = field.fieldValue; - }); - + formFieldDict = emailNotifications.createFieldDict(form.form_fields); form.selfNotifications.from = formFieldDict[form.selfNotifications.fromField].fieldValue; emailNotifications.send(form.selfNotifications, formFieldDict, smtpTransport, constants.varFormat, function(err){ @@ -95,8 +91,9 @@ exports.createSubmission = function(req, res) { }); }); } else { + */ res.status(200).send('Form submission successfully saved'); - } + //} }); }; diff --git a/app/libs/constants.js b/app/libs/constants.js index 0669eca8..90340ce2 100644 --- a/app/libs/constants.js +++ b/app/libs/constants.js @@ -4,7 +4,6 @@ module.exports = { fieldTypes: ['textfield', 'date', 'email', - 'link', 'legal', 'url', 'textarea', @@ -74,8 +73,9 @@ module.exports = { regex: { url: /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/, hexCode: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/, - email: /^(([^<>()\[\]\\.,;:\s@']+(\.[^<>()\[\]\\.,;:\s@']+)*)|('.+'))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + email: /^(([^<>()\[\]\\.,;:\s@']+(\.[^<>()\[\]\\.,;:\s@']+)*)|('.+'))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, + templateVariable: /(.|\n)*?<\/var>/g }, - varFormat: ['${', '}'], + varFormat: ['(.|\n)*?'], }; \ No newline at end of file diff --git a/app/libs/send-email-notifications.js b/app/libs/send-email-notifications.js index d7a8b2c7..c37530b3 100644 --- a/app/libs/send-email-notifications.js +++ b/app/libs/send-email-notifications.js @@ -1,7 +1,11 @@ +'use strict'; + +const constants = require('./constants'); + module.exports = { send: function(emailSettings, emailTemplateVars, smtpTransport, varFormat, cb){ - var parsedTemplate = parseTemplate(emailSettings.htmlTemplate, emailTemplateVars); - var parsedSubject = parseTemplate(emailSettings.body, emailTemplateVars); + var parsedTemplate = this.parseTemplate(emailSettings.htmlTemplate, emailTemplateVars); + var parsedSubject = this.parseTemplate(emailSettings.body, emailTemplateVars); var mailOptions = { from: emailSettings.from, cc: emailSettings.recipients, @@ -22,5 +26,15 @@ module.exports = { replaceTemplateVal: function(key, val, template, varFormat){ return template.replace( new RegExp(varFormat[0] + key + varFormat[1], 'g'), value ) + }, + + createFieldDict: function(form_fields){ + var formFieldDict = {} + form_fields.forEach(function(field){ + if(field.hasOwnProperty('_id') && field.hasOwnProperty('fieldValue')){ + formFieldDict[field._id] = field.fieldValue; + } + }); + return formFieldDict; } } \ No newline at end of file diff --git a/app/models/form.server.model.js b/app/models/form.server.model.js index 483dce79..2e30a47a 100644 --- a/app/models/form.server.model.js +++ b/app/models/form.server.model.js @@ -9,7 +9,8 @@ var mongoose = require('mongoose'), timeStampPlugin = require('../libs/timestamp.server.plugin'), async = require('async'), Random = require('random-js'), - mt = Random.engines.mt19937(); + mt = Random.engines.mt19937(), + constants = require('../libs/constants'); mt.autoSeed(); @@ -57,11 +58,12 @@ var VisitorDataSchema = new Schema({ type: Boolean }, language: { - type: String + type: String, + enum: constants.languageTypes, + default: 'en', }, ipAddr: { - type: String, - default: '' + type: String }, deviceType: { type: String, @@ -179,7 +181,7 @@ var FormSchema = new Schema({ }, subject: { type: String, - default: 'Tellform: Thank you for filling out Tellform name' + default: 'Tellform: Thank you for filling out this TellForm' }, htmlTemplate: { type: String, diff --git a/app/models/form_field.server.model.js b/app/models/form_field.server.model.js index 31f96e71..4df9c741 100644 --- a/app/models/form_field.server.model.js +++ b/app/models/form_field.server.model.js @@ -9,7 +9,8 @@ var mongoose = require('mongoose'), _ = require('lodash'), Schema = mongoose.Schema, LogicJumpSchema = require('./logic_jump.server.model'), - tokgen = require('../libs/tokenGenerator'); + tokgen = require('../libs/tokenGenerator'), + constants = require('../libs/constants'); var FieldOptionSchema = new Schema({ option_id: { @@ -34,21 +35,7 @@ var RatingFieldSchema = new Schema({ }, shape: { type: String, - enum: [ - 'Heart', - 'Star', - 'thumbs-up', - 'thumbs-down', - 'Circle', - 'Square', - 'Check Circle', - 'Smile Outlined', - 'Hourglass', - 'bell', - 'Paper Plane', - 'Comment', - 'Trash' - ] + enum: constants.ratingShapeTypes }, validShapes: { type: [String] @@ -103,29 +90,7 @@ function BaseFieldSchema(){ }, fieldType: { type: String, - enum: [ - 'textfield', - 'date', - 'email', - 'link', - 'legal', - 'url', - 'textarea', - 'statement', - 'welcome', - 'thankyou', - 'file', - 'dropdown', - 'scale', - 'rating', - 'radio', - 'checkbox', - 'hidden', - 'yes_no', - 'natural', - 'stripe', - 'number' - ] + enum: constants.fieldTypes }, fieldValue: Schema.Types.Mixed }); @@ -140,7 +105,7 @@ function BaseFieldSchema(){ this.validFieldTypes = mongoose.model('Field').schema.path('fieldType').enumValues; if(this.fieldType === 'rating' && this.ratingOptions.validShapes.length === 0){ - this.ratingOptions.validShapes = mongoose.model('RatingOptions').schema.path('shape').enumValues; + this.ratingOptions.validShapes = constants.ratingShapeTypes; } next(); diff --git a/app/models/user.server.model.js b/app/models/user.server.model.js index f8b16236..b9656488 100755 --- a/app/models/user.server.model.js +++ b/app/models/user.server.model.js @@ -10,7 +10,8 @@ var mongoose = require('mongoose'), timeStampPlugin = require('../libs/timestamp.server.plugin'), path = require('path'), querystring = require('querystring'), - nodemailer = require('nodemailer'); + nodemailer = require('nodemailer'), + constants = require('../libs/constants'); var smtpTransport = nodemailer.createTransport(config.mailer.options); @@ -37,14 +38,6 @@ var validateLocalStrategyProperty = function(property) { return ((this.provider !== 'local' && !this.updated) || propHasLength); }; -/** - * A Validation function for username - */ -var validateUsername = function(username) { - return (username.match(/^[a-zA-Z0-9.-_]+$/) !== null); -}; - - /** * User Schema */ @@ -64,7 +57,7 @@ var UserSchema = new Schema({ trim: true, lowercase: true, unique: 'Account already exists with this email', - match: [/.+\@.+\..+/, 'Please fill a valid email address'], + match: [constants.regex.email, 'Please fill a valid email address'], required: [true, 'Email is required'] }, username: { @@ -90,13 +83,13 @@ var UserSchema = new Schema({ roles: { type: [{ type: String, - enum: ['user', 'admin', 'superuser'] + enum: constants.userRoleTypes }], default: ['user'] }, language: { type: String, - enum: ['en', 'fr', 'es', 'it', 'de'], + enum: constants.languageTypes, default: 'en', }, lastModified: { diff --git a/app/tests/form.server.routes.test.js b/app/tests/form.server.routes.test.js index e1aa2654..e648786a 100644 --- a/app/tests/form.server.routes.test.js +++ b/app/tests/form.server.routes.test.js @@ -68,7 +68,7 @@ describe('Form Routes Unit tests', function() { .send({form: myForm}) .expect(401) .end(function(FormSaveErr, FormSaveRes) { - + console.log(FormSaveRes.text) // Call the assertion callback done(FormSaveErr); }); diff --git a/app/tests/form_submission.model.test.js b/app/tests/form_submission.model.test.js index f60e599e..899ffca9 100644 --- a/app/tests/form_submission.model.test.js +++ b/app/tests/form_submission.model.test.js @@ -82,8 +82,7 @@ describe('FormSubmission Model Unit Tests:', function() { user = new User({ firstName: 'Full', lastName: 'Name', - displayName: 'Full Name', - email: 'test1@test.com'+Date.now(), + email: 'test1@test.com', username: 'test1'+Date.now(), password: 'password', provider: 'local' @@ -210,8 +209,8 @@ describe('FormSubmission Model Unit Tests:', function() { should.not.exist(err); should.exist(_form.form_fields); - var actual_fields = _.deepOmit(_form.toObject().form_fields, ['deletePreserved', 'globalId', 'lastModified', 'created', '_id', 'submissionId']); - old_fields = _.deepOmit(old_fields, ['deletePreserved', 'globalId', 'lastModified', 'created', '_id', 'submissionId']); + var actual_fields = _.deepOmit(_form.toObject().form_fields, ['deletePreserved', 'globalId', 'lastModified', 'created', '_id', 'submissionId', 'isSubmission', 'validFieldTypes', 'title']); + old_fields = _.deepOmit(old_fields, ['deletePreserved', 'globalId', 'lastModified', 'created', '_id', 'submissionId', 'isSubmission', 'validFieldTypes', 'title']); should.deepEqual(actual_fields, old_fields, 'old form_fields not equal to newly saved form_fields'); done(); diff --git a/app/tests/libs/send-email-notifications.test.js b/app/tests/libs/send-email-notifications.test.js new file mode 100644 index 00000000..7630094e --- /dev/null +++ b/app/tests/libs/send-email-notifications.test.js @@ -0,0 +1,54 @@ +'use strict'; + +/** + * Module dependencies. + */ +var emailNotifications = require('../../libs/send-email-notifications'); + +/** + * Globals + */ +var validFormFields = [ + {fieldType:'textfield', title:'First Name', fieldValue: 'John Smith', deletePreserved: false, _id:'56340745f59a6fc9e22028e9'}, + {fieldType:'link', title:'Your Website', fieldValue: 'https://johnsmith.me', deletePreserved: false, _id:'5c9e22028e907634f45f59a6'}, + {fieldType:'number', title:'Your Age', fieldValue: 45, deletePreserved: false, _id:'56e90745f5934fc9e22028a6'} +]; + +var validFieldDict = { + '56340745f59a6fc9e22028e9': 'John Smith', + '5c9e22028e907634f45f59a6': 'https://johnsmith.me', + '56e90745f5934fc9e22028a6': 45 +}; + +var invalidFormFields = [ + {fieldType:'textfield', title:'First Name', fieldValue: 'John Smith', deletePreserved: false}, + {fieldType:'link', title:'Your Website', deletePreserved: false, _id:'5c9e22028e907634f45f59a6'}, + {fieldType:'number', title:'Your Age'} +] + +/** + * Unit tests + */ +describe('Send Email Notification Unit Tests', function() { + + describe('Method createFieldDict', function() { + it('should be return a fieldDict from valid form fields', function() { + var actualFieldDict = emailNotifications.createFieldDict(validFormFields); + actualFieldDict.should.deepEqual(validFieldDict); + }); + + it('should return empty object if form fields are invalid or empty ', function() { + var actualFieldDict = emailNotifications.createFieldDict(invalidFormFields); + actualFieldDict.should.be.empty(); + }); + }); + + describe('Method replaceTemplateVal', function() { + }); + + describe('Method send', function() { + }); + + describe('Method parseTemplate', function(){ + }); +}); diff --git a/app/views/500.server.view.pug b/app/views/500.server.view.pug index 688a9af0..9a395042 100644 --- a/app/views/500.server.view.pug +++ b/app/views/500.server.view.pug @@ -5,7 +5,8 @@ block content div.row.valign h3.col-md-12.text-center=__('500_HEADER') div.col-md-4.col-md-offset-4 - if process.env.NODE_ENV == 'development' + if process.env.NODE_ENV == 'development' || process.env.NODE_ENV == 'test' + div.col-md-12.text-center(style="padding-bottom: 50px;") | #{error} else diff --git a/config/express.js b/config/express.js index 1da3f4a1..83790fd5 100755 --- a/config/express.js +++ b/config/express.js @@ -263,18 +263,20 @@ module.exports = function(db) { //Visitor Language Detection app.use(function(req, res, next) { var acceptLanguage = req.headers['accept-language']; - var languages = acceptLanguage.match(/[a-z]{2}(?!-)/g) || []; + if(acceptLanguage){ + var languages = acceptLanguage.match(/[a-z]{2}(?!-)/g) || []; - var supportedLanguage = containsAnySupportedLanguages(languages); - if(!req.user && supportedLanguage !== null){ - var currLanguage = res.cookie('userLang'); + var supportedLanguage = containsAnySupportedLanguages(languages); + if(!req.user && supportedLanguage !== null){ + var currLanguage = res.cookie('userLang'); - if(currLanguage && currLanguage !== supportedLanguage || !currLanguage){ - res.clearCookie('userLang'); - res.cookie('userLang', supportedLanguage, { maxAge: 90000, httpOnly: true }); + if(currLanguage && currLanguage !== supportedLanguage || !currLanguage){ + res.clearCookie('userLang'); + res.cookie('userLang', supportedLanguage, { maxAge: 90000, httpOnly: true }); + } + } else if(req.user && (!req.cookies.hasOwnProperty('userLang') || req.cookies['userLang'] !== req.user.language) ){ + res.cookie('userLang', req.user.language, { maxAge: 90000, httpOnly: true }); } - } else if(req.user && (!req.cookies.hasOwnProperty('userLang') || req.cookies['userLang'] !== req.user.language) ){ - res.cookie('userLang', req.user.language, { maxAge: 90000, httpOnly: true }); } next(); }); @@ -319,17 +321,10 @@ module.exports = function(db) { // Log it client.captureError(err); - - if(process.env.NODE_ENV === 'production'){ - res.status(500).render('500', { - error: 'Internal Server Error' - }); - } else { - // Error page - res.status(500).render('500', { - error: err.stack - }); - } + + res.status(500).render('500', { + error: err.stack + }); }); // Assume 404 since no middleware responded diff --git a/public/modules/forms/admin/directives/configure-form.client.directive.js b/public/modules/forms/admin/directives/configure-form.client.directive.js index 4eff1b0b..4bc7915b 100644 --- a/public/modules/forms/admin/directives/configure-form.client.directive.js +++ b/public/modules/forms/admin/directives/configure-form.client.directive.js @@ -36,8 +36,6 @@ angular.module('forms').directive('configureFormDirective', ['$rootScope', '$fil return field.fieldType === 'email'; }); - console.log($rootScope.emailFields); - $scope.formHasEmailField = ($rootScope.emailFields.length > 0); $scope.go = function(tab){ diff --git a/public/modules/forms/config/forms.client.config.js b/public/modules/forms/config/forms.client.config.js index 2dcc8827..8ff54396 100644 --- a/public/modules/forms/config/forms.client.config.js +++ b/public/modules/forms/config/forms.client.config.js @@ -61,7 +61,7 @@ angular.module('forms').run(['Menus', \ ', onClickField: function(field_id, field_name){ - this.$editor().wrapSelection('insertHTML', '' + field_name + '', true); + this.$editor().wrapSelection('insertHTML', '' + field_name + '', true); }, action: function(){ }