Merge branch '2.20' into emailNotifications
This commit is contained in:
commit
ddd4c2b22c
@ -11,5 +11,9 @@ services:
|
|||||||
addons:
|
addons:
|
||||||
code_climate:
|
code_climate:
|
||||||
repo_token: 6c3a1b81a09b2338d6f30913c1bcad115026689752cbb499a0a25061cda6fbcf
|
repo_token: 6c3a1b81a09b2338d6f30913c1bcad115026689752cbb499a0a25061cda6fbcf
|
||||||
after_script:
|
install:
|
||||||
- grunt coverage
|
- npm install phantomjs
|
||||||
|
- npm install -g grunt
|
||||||
|
- npm install
|
||||||
|
script:
|
||||||
|
- yarn run travis
|
||||||
|
|||||||
@ -12,7 +12,8 @@ var mongoose = require('mongoose'),
|
|||||||
_ = require('lodash'),
|
_ = require('lodash'),
|
||||||
nodemailer = require('nodemailer'),
|
nodemailer = require('nodemailer'),
|
||||||
emailNotifications = require('../libs/send-email-notifications'),
|
emailNotifications = require('../libs/send-email-notifications'),
|
||||||
constants = require('../libs/constants');
|
constants = require('../libs/constants'),
|
||||||
|
helpers = require('./helpers.server.controller');
|
||||||
|
|
||||||
var smtpTransport = nodemailer.createTransport(config.mailer.options);
|
var smtpTransport = nodemailer.createTransport(config.mailer.options);
|
||||||
|
|
||||||
@ -113,16 +114,14 @@ exports.listSubmissions = function(req, res) {
|
|||||||
}
|
}
|
||||||
res.json(_submissions);
|
res.json(_submissions);
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new form
|
* Create a new form
|
||||||
*/
|
*/
|
||||||
exports.create = function(req, res) {
|
exports.create = function(req, res) {
|
||||||
|
|
||||||
if(!req.body.form){
|
if(!req.body.form){
|
||||||
return res.status(401).send({
|
return res.status(400).send({
|
||||||
message: 'Invalid Input'
|
message: 'Invalid Input'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -130,14 +129,15 @@ exports.create = function(req, res) {
|
|||||||
var form = new Form(req.body.form);
|
var form = new Form(req.body.form);
|
||||||
form.admin = req.user._id;
|
form.admin = req.user._id;
|
||||||
|
|
||||||
form.save(function(err) {
|
form.save(function(err, createdForm) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return res.status(500).send({
|
return res.status(500).send({
|
||||||
message: errorHandler.getErrorMessage(err)
|
message: errorHandler.getErrorMessage(err)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.json(form);
|
createdForm = helpers.removeSensitiveModelData('private_form', createdForm);
|
||||||
|
return res.json(createdForm);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -148,16 +148,19 @@ exports.read = function(req, res) {
|
|||||||
if(!req.user || (req.form.admin.id !== req.user.id) ){
|
if(!req.user || (req.form.admin.id !== req.user.id) ){
|
||||||
readForRender(req, res);
|
readForRender(req, res);
|
||||||
} else {
|
} else {
|
||||||
var newForm = req.form.toJSON();
|
if(!req.form){
|
||||||
|
|
||||||
if (req.userId) {
|
|
||||||
if(req.form.admin._id+'' === req.userId+''){
|
|
||||||
return res.json(newForm);
|
|
||||||
}
|
|
||||||
return res.status(404).send({
|
return res.status(404).send({
|
||||||
message: 'Form Does Not Exist'
|
message: 'Form Does Not Exist'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var newForm = req.form.toJSON();
|
||||||
|
|
||||||
|
if(newForm.admin._id === req.user._id){
|
||||||
|
return res.json(newForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
newForm = helpers.removeSensitiveModelData('private_form', newForm);
|
||||||
return res.json(newForm);
|
return res.json(newForm);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -173,9 +176,7 @@ var readForRender = exports.readForRender = function(req, res) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
delete newForm.lastModified;
|
newForm = helpers.removeSensitiveModelData('public_form', newForm);
|
||||||
delete newForm.__v;
|
|
||||||
delete newForm.created;
|
|
||||||
|
|
||||||
if(newForm.startPage && !newForm.startPage.showStart){
|
if(newForm.startPage && !newForm.startPage.showStart){
|
||||||
delete newForm.startPage;
|
delete newForm.startPage;
|
||||||
@ -191,15 +192,12 @@ exports.update = function(req, res) {
|
|||||||
|
|
||||||
var form = req.form;
|
var form = req.form;
|
||||||
var updatedForm = req.body.form;
|
var updatedForm = req.body.form;
|
||||||
if(form.form_fields === undefined){
|
|
||||||
form.form_fields = [];
|
if(!form.analytics){
|
||||||
}
|
|
||||||
|
|
||||||
if(form.analytics === undefined){
|
|
||||||
form.analytics = {
|
form.analytics = {
|
||||||
visitors: [],
|
visitors: [],
|
||||||
gaCode: ''
|
gaCode: ''
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.body.changes) {
|
if (req.body.changes) {
|
||||||
@ -217,11 +215,6 @@ exports.update = function(req, res) {
|
|||||||
delete updatedForm.admin;
|
delete updatedForm.admin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(form.analytics === null){
|
|
||||||
form.analytics.visitors = [];
|
|
||||||
form.analytics.gaCode = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
//Do this so we can create duplicate fields
|
//Do this so we can create duplicate fields
|
||||||
var checkForValidId = new RegExp('^[0-9a-fA-F]{24}$');
|
var checkForValidId = new RegExp('^[0-9a-fA-F]{24}$');
|
||||||
for(var i=0; i < req.body.form.form_fields.length; i++){
|
for(var i=0; i < req.body.form.form_fields.length; i++){
|
||||||
@ -239,6 +232,7 @@ exports.update = function(req, res) {
|
|||||||
message: errorHandler.getErrorMessage(err)
|
message: errorHandler.getErrorMessage(err)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
savedForm = helpers.removeSensitiveModelData('private_form', savedForm);
|
||||||
res.json(savedForm);
|
res.json(savedForm);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -280,6 +274,8 @@ exports.list = function(req, res) {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
for(var i=0; i<forms.length; i++){
|
for(var i=0; i<forms.length; i++){
|
||||||
|
forms[i] = helpers.removeSensitiveModelData('private_form', forms[i]);
|
||||||
|
|
||||||
forms[i].numberOfResponses = 0;
|
forms[i].numberOfResponses = 0;
|
||||||
if(forms[i].submissions){
|
if(forms[i].submissions){
|
||||||
forms[i].numberOfResponses = forms[i].submissions.length;
|
forms[i].numberOfResponses = forms[i].submissions.length;
|
||||||
@ -300,6 +296,7 @@ exports.formByID = function(req, res, next, id) {
|
|||||||
message: 'Form is invalid'
|
message: 'Form is invalid'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Form.findById(id)
|
Form.findById(id)
|
||||||
.populate('admin')
|
.populate('admin')
|
||||||
.exec(function(err, form) {
|
.exec(function(err, form) {
|
||||||
@ -312,12 +309,7 @@ exports.formByID = function(req, res, next, id) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//Remove sensitive information from User object
|
//Remove sensitive information from User object
|
||||||
var _form = form;
|
req.form = helpers.removeSensitiveModelData('private_form', form);
|
||||||
_form.admin.password = null;
|
|
||||||
_form.admin.salt = null;
|
|
||||||
_form.provider = null;
|
|
||||||
|
|
||||||
req.form = _form;
|
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -345,13 +337,7 @@ exports.formByIDFast = function(req, res, next, id) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//Remove sensitive information from User object
|
//Remove sensitive information from User object
|
||||||
var _form = form;
|
req.form = helpers.removeSensitiveModelData('public_form', form);
|
||||||
if(_form.admin){
|
|
||||||
_form.admin.password = null;
|
|
||||||
_form.admin.salt = null;
|
|
||||||
_form.provider = null;
|
|
||||||
}
|
|
||||||
req.form = _form;
|
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
45
app/controllers/helpers.server.controller.js
Normal file
45
app/controllers/helpers.server.controller.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
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[type]);
|
||||||
|
if(object.admin){
|
||||||
|
removeKeysFromDict(object.admin, privateFields.private_user);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'public_form':
|
||||||
|
removeKeysFromDict(object, privateFields[type]);
|
||||||
|
if(object.admin){
|
||||||
|
removeKeysFromDict(object.admin, privateFields.public_user);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if(privateFields.hasOwnProperty(type)){
|
||||||
|
removeKeysFromDict(object, privateFields[type]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -12,7 +12,8 @@ var errorHandler = require('../errors.server.controller'),
|
|||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
i18n = require('i18n'),
|
i18n = require('i18n'),
|
||||||
async = require('async'),
|
async = require('async'),
|
||||||
pug = require('pug');
|
pug = require('pug'),
|
||||||
|
helpers = require('../helpers.server.controller');
|
||||||
|
|
||||||
var nev = require('email-verification')(mongoose);
|
var nev = require('email-verification')(mongoose);
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ config_nev();
|
|||||||
|
|
||||||
exports.validateVerificationToken = function(req, res){
|
exports.validateVerificationToken = function(req, res){
|
||||||
|
|
||||||
const fn = pug.compileFile(__dirname + "/../../views/welcome.email.view.pug");
|
const fn = pug.compileFile(__dirname + '/../../views/welcome.email.view.pug');
|
||||||
var renderedHtml = fn(res.locals);
|
var renderedHtml = fn(res.locals);
|
||||||
|
|
||||||
var emailTemplate = {
|
var emailTemplate = {
|
||||||
@ -83,7 +84,7 @@ exports.validateVerificationToken = function(req, res){
|
|||||||
};
|
};
|
||||||
|
|
||||||
exports.resendVerificationEmail = function(req, res, next){
|
exports.resendVerificationEmail = function(req, res, next){
|
||||||
const fn = pug.compileFile(__dirname + "/../../views/verification.email.view.pug");
|
const fn = pug.compileFile(__dirname + '/../../views/verification.email.view.pug');
|
||||||
var renderedHtml = fn(res.locals);
|
var renderedHtml = fn(res.locals);
|
||||||
|
|
||||||
var emailTemplate = {
|
var emailTemplate = {
|
||||||
@ -117,7 +118,7 @@ exports.signup = function(req, res) {
|
|||||||
var user = new User(req.body);
|
var user = new User(req.body);
|
||||||
|
|
||||||
// Set language to visitor's language
|
// Set language to visitor's language
|
||||||
user.language = req.cookies['userLang'];
|
user.language = req.cookies.userLang;
|
||||||
|
|
||||||
// Add missing user fields
|
// Add missing user fields
|
||||||
user.provider = 'local';
|
user.provider = 'local';
|
||||||
@ -133,7 +134,7 @@ exports.signup = function(req, res) {
|
|||||||
|
|
||||||
// new user created
|
// new user created
|
||||||
if (newTempUser) {
|
if (newTempUser) {
|
||||||
const fn = pug.compileFile(__dirname + "/../../views/verification.email.view.pug");
|
const fn = pug.compileFile(__dirname + '/../../views/verification.email.view.pug');
|
||||||
var renderedHtml = fn(res.locals);
|
var renderedHtml = fn(res.locals);
|
||||||
|
|
||||||
var URL = newTempUser[nev.options.URLFieldName];
|
var URL = newTempUser[nev.options.URLFieldName];
|
||||||
@ -179,6 +180,8 @@ exports.signin = function(req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res.cookie('langCookie', user.language, { maxAge: 90000, httpOnly: true });
|
res.cookie('langCookie', user.language, { maxAge: 90000, httpOnly: true });
|
||||||
|
|
||||||
|
user = helpers.removeSensitiveModelData('private_user', user);
|
||||||
return res.json(user);
|
return res.json(user);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -190,7 +193,7 @@ exports.signin = function(req, res, next) {
|
|||||||
*/
|
*/
|
||||||
exports.signout = function(req, res) {
|
exports.signout = function(req, res) {
|
||||||
if(req.cookies.hasOwnProperty('userLang')){
|
if(req.cookies.hasOwnProperty('userLang')){
|
||||||
res.destroyCookie('userLang');
|
res.clearCookie('userLang');
|
||||||
}
|
}
|
||||||
req.logout();
|
req.logout();
|
||||||
return res.status(200).send('You have successfully logged out.');
|
return res.status(200).send('You have successfully logged out.');
|
||||||
@ -198,16 +201,12 @@ exports.signout = function(req, res) {
|
|||||||
|
|
||||||
/* Generate API Key for User */
|
/* Generate API Key for User */
|
||||||
exports.generateAPIKey = function(req, res) {
|
exports.generateAPIKey = function(req, res) {
|
||||||
if (!req.isAuthenticated()){
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'User is not Authorized'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
User.findById(req.user.id)
|
User.findById(req.user.id)
|
||||||
.exec( function(err, user) {
|
.exec( function(err, user) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return res.status(400).send(err);
|
return res.status(400).send({
|
||||||
|
message: errorHandler.getErrorMessage(err)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
@ -226,12 +225,8 @@ exports.generateAPIKey = function(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var newUser = _user.toObject();
|
var newUser = _user.toObject();
|
||||||
delete newUser.salt;
|
|
||||||
delete newUser.__v;
|
|
||||||
delete newUser.passwordHash;
|
|
||||||
delete newUser.provider;
|
|
||||||
|
|
||||||
return res.json(newUser);
|
return res.json({ id: newUser._id, apiKey: newUser.apiKey });
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,36 +3,7 @@
|
|||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
var _ = require('lodash'),
|
var auth = require('../../../config/passport_helpers');
|
||||||
mongoose = require('mongoose'),
|
|
||||||
User = mongoose.model('User');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User middleware
|
|
||||||
*/
|
|
||||||
exports.userByID = function (req, res, next, id) {
|
|
||||||
if (!mongoose.Types.ObjectId.isValid(id)) {
|
|
||||||
return res.status(400).send({
|
|
||||||
message: 'User is invalid'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
User.findOne({
|
|
||||||
_id: id
|
|
||||||
}).exec(function (err, user) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
} else if (!user) {
|
|
||||||
return res.status(404).send({
|
|
||||||
message: 'User does not exist'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
req.profile = user;
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Require login routing middleware
|
* Require login routing middleware
|
||||||
*/
|
*/
|
||||||
@ -45,22 +16,3 @@ exports.requiresLogin = function(req, res, next) {
|
|||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* User authorizations routing middleware
|
|
||||||
*/
|
|
||||||
exports.hasAuthorization = function(roles) {
|
|
||||||
var _this = this;
|
|
||||||
|
|
||||||
return function(req, res, next) {
|
|
||||||
_this.requiresLogin(req, res, function() {
|
|
||||||
if (_.intersection(req.user.roles, roles).length) {
|
|
||||||
return next();
|
|
||||||
} else {
|
|
||||||
return res.status(403).send({
|
|
||||||
message: 'User is not authorized'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|||||||
@ -81,10 +81,9 @@ exports.forgot = function(req, res) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
function(token, user, done) {
|
function(token, user, done) {
|
||||||
const fn = pug.compileFile(__dirname + "/../../views/templates/reset-password-email.server.view.pug");
|
const fn = pug.compileFile(__dirname + '/../../views/templates/reset-password-email.server.view.pug');
|
||||||
res.locals['url'] = 'http://' + req.headers.host + '/auth/reset/' + token;
|
res.locals.url = 'http://' + req.headers.host + '/auth/reset/' + token;
|
||||||
|
|
||||||
console.log(res.locals);
|
|
||||||
var renderedHtml = fn(res.locals);
|
var renderedHtml = fn(res.locals);
|
||||||
done(null, renderedHtml, user);
|
done(null, renderedHtml, user);
|
||||||
},
|
},
|
||||||
@ -98,10 +97,10 @@ exports.forgot = function(req, res) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var userEmail = user.email;
|
var userEmail = user.email;
|
||||||
var user = userEmail.split('@')[0];
|
var emailUsername = userEmail.split('@')[0];
|
||||||
var domain = userEmail.split('@')[1];
|
var domain = userEmail.split('@')[1];
|
||||||
|
|
||||||
var obfuscatedUser = user.substring(0, 1) + user.substring(1).replace(/./g, '*');
|
var obfuscatedUser = emailUsername.substring(0, 1) + emailUsername.substring(1).replace(/./g, '*');
|
||||||
var domainName = domain.split('.')[0];
|
var domainName = domain.split('.')[0];
|
||||||
var tld = domain.split('.')[1];
|
var tld = domain.split('.')[1];
|
||||||
|
|
||||||
@ -142,9 +141,9 @@ exports.validateResetToken = function(req, res) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return res.redirect('/#!/password/reset/invalid');
|
return res.redirect(400, '/#!/password/reset/invalid');
|
||||||
}
|
}
|
||||||
|
|
||||||
res.redirect('/#!/password/reset/' + req.params.token);
|
res.redirect('/#!/password/reset/' + req.params.token);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -187,13 +186,13 @@ exports.reset = function(req, res, next) {
|
|||||||
done(null, savedUser);
|
done(null, savedUser);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
done('Password reset token is invalid or has expired.', null);
|
done('invalid_reset_token', null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function(user, done) {
|
function(user, done) {
|
||||||
const fn = pug.compileFile(__dirname + "/../../views/templates/reset-password-confirm-email.server.view.pug");
|
const fn = pug.compileFile(__dirname + '/../../views/templates/reset-password-confirm-email.server.view.pug');
|
||||||
var renderedHtml = fn(res.locals);
|
const renderedHtml = fn(res.locals);
|
||||||
done(null, renderedHtml, user);
|
done(null, renderedHtml, user);
|
||||||
},
|
},
|
||||||
// If valid email, send reset email using service
|
// If valid email, send reset email using service
|
||||||
@ -211,12 +210,18 @@ exports.reset = function(req, res, next) {
|
|||||||
}
|
}
|
||||||
], function(err) {
|
], function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
res.status(500).send({
|
if(err === 'invalid_reset_token'){
|
||||||
|
return res.status(400).send({
|
||||||
|
message: 'Password reset token is invalid or has expired.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(500).send({
|
||||||
message: err.message || err
|
message: err.message || err
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.json({
|
res.json({
|
||||||
message: 'Successfully changed your password!'
|
message: 'Successfully changed your password!'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,7 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
var _ = require('lodash'),
|
var _ = require('lodash'),
|
||||||
errorHandler = require('../errors.server.controller.js'),
|
errorHandler = require('../errors.server.controller.js'),
|
||||||
mongoose = require('mongoose');
|
mongoose = require('mongoose'),
|
||||||
|
helpers = require('../helpers.server.controller');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update user details
|
* Update user details
|
||||||
@ -14,47 +15,36 @@ exports.update = function(req, res) {
|
|||||||
// Init Variables
|
// Init Variables
|
||||||
var user = req.user;
|
var user = req.user;
|
||||||
|
|
||||||
// For security measurement we remove the roles from the req.body object
|
// To improve security we remove the roles from the req.body object
|
||||||
delete req.body.roles;
|
delete req.body.roles;
|
||||||
|
|
||||||
if (user) {
|
// Merge existing user
|
||||||
// Merge existing user
|
user = _.extend(user, req.body);
|
||||||
user = _.extend(user, req.body);
|
user.updated = Date.now();
|
||||||
user.updated = Date.now();
|
|
||||||
|
|
||||||
user.save(function(err) {
|
user.save(function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return res.status(500).send({
|
return res.status(500).send({
|
||||||
message: errorHandler.getErrorMessage(err)
|
message: errorHandler.getErrorMessage(err)
|
||||||
});
|
|
||||||
}
|
|
||||||
req.login(user, function(loginErr) {
|
|
||||||
if (err) {
|
|
||||||
res.status(500).send(loginErr);
|
|
||||||
} else {
|
|
||||||
res.json(user);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
req.login(user, function(loginErr) {
|
||||||
|
if (err) {
|
||||||
|
res.status(500).send(loginErr);
|
||||||
|
} else {
|
||||||
|
user = helpers.removeSensitiveModelData('private_user', user);
|
||||||
|
res.json(user);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
res.status(401).send({
|
});
|
||||||
message: 'User is not signed in'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send User
|
* Send User
|
||||||
*/
|
*/
|
||||||
exports.getUser = function(req, res) {
|
exports.getUser = function(req, res) {
|
||||||
var _user = req.user;
|
var user = helpers.removeSensitiveModelData('private_user', req.user);
|
||||||
delete _user.password;
|
|
||||||
delete _user.salt;
|
|
||||||
delete _user.provider;
|
|
||||||
delete _user.__v;
|
|
||||||
|
|
||||||
res.json(req.user || null);
|
return res.json(user);
|
||||||
|
|
||||||
res.end();
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,25 +11,26 @@ module.exports = {
|
|||||||
cc: emailSettings.recipients,
|
cc: emailSettings.recipients,
|
||||||
subject: parsedSubject,
|
subject: parsedSubject,
|
||||||
html: parsedTemplate
|
html: parsedTemplate
|
||||||
}
|
};
|
||||||
|
|
||||||
smtpTransport.sendMail(mailOptions, cb);
|
smtpTransport.sendMail(mailOptions, cb);
|
||||||
},
|
},
|
||||||
|
|
||||||
parseTemplate: function(emailTemplate, emailAttrs, varFormat){
|
parseTemplate: function(emailTemplate, emailAttrs, varFormat){
|
||||||
var resolvedTemplate = emailTemplate;
|
var resolvedTemplate = emailTemplate;
|
||||||
|
var that = this;
|
||||||
Object.keys(emailAttrs).forEach(function (key) {
|
Object.keys(emailAttrs).forEach(function (key) {
|
||||||
resolvedTemplate = replaceTemplateVal(key, emailAttrs[key], resolvedTemplate);
|
resolvedTemplate = that.replaceTemplateVal(key, emailAttrs[key], resolvedTemplate);
|
||||||
});
|
});
|
||||||
return resolvedTemplate;
|
return resolvedTemplate;
|
||||||
},
|
},
|
||||||
|
|
||||||
replaceTemplateVal: function(key, val, template, varFormat){
|
replaceTemplateVal: function(key, val, template, varFormat){
|
||||||
return template.replace( new RegExp(varFormat[0] + key + varFormat[1], 'g'), value )
|
return template.replace( new RegExp(varFormat[0] + key + varFormat[1], 'g'), val);
|
||||||
},
|
},
|
||||||
|
|
||||||
createFieldDict: function(form_fields){
|
createFieldDict: function(form_fields){
|
||||||
var formFieldDict = {}
|
var formFieldDict = {};
|
||||||
form_fields.forEach(function(field){
|
form_fields.forEach(function(field){
|
||||||
if(field.hasOwnProperty('_id') && field.hasOwnProperty('fieldValue')){
|
if(field.hasOwnProperty('_id') && field.hasOwnProperty('fieldValue')){
|
||||||
formFieldDict[field._id] = field.fieldValue;
|
formFieldDict[field._id] = field.fieldValue;
|
||||||
@ -37,4 +38,4 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
return formFieldDict;
|
return formFieldDict;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
@ -2,38 +2,36 @@
|
|||||||
|
|
||||||
// Plugin
|
// Plugin
|
||||||
module.exports = function timestamp (schema, options) {
|
module.exports = function timestamp (schema, options) {
|
||||||
options || (options = {})
|
options = options || (options === {});
|
||||||
|
|
||||||
// Options
|
// Options
|
||||||
var fields = {}
|
var fields = {},
|
||||||
, createdPath = options.createdPath || 'created'
|
createdPath = options.createdPath || 'created',
|
||||||
, modifiedPath = options.modifiedPath || 'modified'
|
modifiedPath = options.modifiedPath || 'modified',
|
||||||
, useVirtual = (options.useVirtual !== undefined)
|
useVirtual = (options.useVirtual !== undefined) ? options.useVirtual : true;
|
||||||
? options.useVirtual
|
|
||||||
: true
|
|
||||||
|
|
||||||
// Add paths to schema if not present
|
// Add paths to schema if not present
|
||||||
if (!schema.paths[createdPath]) {
|
if (!schema.paths[createdPath]) {
|
||||||
fields[modifiedPath] = { type: Date }
|
fields[modifiedPath] = { type: Date };
|
||||||
}
|
}
|
||||||
if (useVirtual) {
|
if (useVirtual) {
|
||||||
// Use the ObjectID for extracting the created time
|
// Use the ObjectID for extracting the created time
|
||||||
schema.virtual(createdPath).get(function () {
|
schema.virtual(createdPath).get(function () {
|
||||||
return new Date(this._id.generationTime * 1000)
|
return new Date(this._id.generationTime * 1000);
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
if (!schema.paths[createdPath]) {
|
if (!schema.paths[createdPath]) {
|
||||||
fields[createdPath] = {
|
fields[createdPath] = {
|
||||||
type: Date
|
type: Date,
|
||||||
, default: Date.now
|
default: Date.now
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
schema.add(fields)
|
schema.add(fields);
|
||||||
|
|
||||||
// Update the modified timestamp on save
|
// Update the modified timestamp on save
|
||||||
schema.pre('save', function (next) {
|
schema.pre('save', function (next) {
|
||||||
this[modifiedPath] = new Date
|
this[modifiedPath] = new Date();
|
||||||
next()
|
next();
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
@ -73,7 +73,6 @@ var VisitorDataSchema = new Schema({
|
|||||||
userAgent: {
|
userAgent: {
|
||||||
type: String
|
type: String
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var formSchemaOptions = {
|
var formSchemaOptions = {
|
||||||
@ -104,12 +103,17 @@ var FormSchema = new Schema({
|
|||||||
visitors: [VisitorDataSchema]
|
visitors: [VisitorDataSchema]
|
||||||
},
|
},
|
||||||
|
|
||||||
form_fields: [FieldSchema],
|
form_fields: {
|
||||||
submissions: [{
|
type: [FieldSchema],
|
||||||
type: Schema.Types.ObjectId,
|
default: []
|
||||||
ref: 'FormSubmission'
|
},
|
||||||
}],
|
submissions: {
|
||||||
|
type: [{
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: 'FormSubmission'
|
||||||
|
}],
|
||||||
|
dfeault: []
|
||||||
|
},
|
||||||
admin: {
|
admin: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: 'User',
|
ref: 'User',
|
||||||
@ -197,6 +201,7 @@ var FormSchema = new Schema({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
|
||||||
isLive: {
|
isLive: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
@ -262,7 +267,7 @@ FormSchema.virtual('analytics.fields').get(function () {
|
|||||||
var visitors = this.analytics.visitors;
|
var visitors = this.analytics.visitors;
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
if(this.form_fields.length === 0) {
|
if(!this.form_fields || this.form_fields.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,26 +337,6 @@ FormSchema.plugin(timeStampPlugin, {
|
|||||||
useVirtual: false
|
useVirtual: false
|
||||||
});
|
});
|
||||||
|
|
||||||
FormSchema.pre('save', function (next) {
|
|
||||||
switch(this.language){
|
|
||||||
case 'spanish':
|
|
||||||
this.language = 'es';
|
|
||||||
break;
|
|
||||||
case 'french':
|
|
||||||
this.language = 'fr';
|
|
||||||
break;
|
|
||||||
case 'italian':
|
|
||||||
this.language = 'it';
|
|
||||||
break;
|
|
||||||
case 'german':
|
|
||||||
this.language = 'de';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|
||||||
function getDeletedIndexes(needle, haystack){
|
function getDeletedIndexes(needle, haystack){
|
||||||
var deletedIndexes = [];
|
var deletedIndexes = [];
|
||||||
|
|
||||||
|
|||||||
@ -55,18 +55,18 @@ FormSubmissionSchema.pre('save', function (next) {
|
|||||||
this.form_fields[i].fieldValue = this.form_fields[i].fieldValue.option_value;
|
this.form_fields[i].fieldValue = this.form_fields[i].fieldValue.option_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete form_fields[i].validFieldTypes;
|
delete this.form_fields[i].validFieldTypes;
|
||||||
delete form_fields[i].disabled;
|
delete this.form_fields[i].disabled;
|
||||||
delete form_fields[i].required;
|
delete this.form_fields[i].required;
|
||||||
delete form_fields[i].isSubmission;
|
delete this.form_fields[i].isSubmission;
|
||||||
delete form_fields[i].title;
|
delete this.form_fields[i].title;
|
||||||
delete form_fields[i].fieldOptions;
|
delete this.form_fields[i].fieldOptions;
|
||||||
delete form_fields[i].ratingOptions;
|
delete this.form_fields[i].ratingOptions;
|
||||||
delete form_fields[i].logicJump;
|
delete this.form_fields[i].logicJump;
|
||||||
delete form_fields[i].description;
|
delete this.form_fields[i].description;
|
||||||
delete form_fields[i].created;
|
delete this.form_fields[i].created;
|
||||||
delete form_fields[i].lastModified;
|
delete this.form_fields[i].lastModified;
|
||||||
delete form_fields[i].deletePreserved;
|
delete this.form_fields[i].deletePreserved;
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,26 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const constants = require('../../libs/constants'),
|
|
||||||
config = require('../../../config/config');
|
|
||||||
|
|
||||||
module.exports = exports = function lastModifiedPlugin (schema, options) {
|
|
||||||
schema.add({
|
|
||||||
language: {
|
|
||||||
type: String,
|
|
||||||
enum: constants.languageTypes,
|
|
||||||
default: config.defaultLanguage,
|
|
||||||
required: options.required || 'Must be a valid language'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
schema.pre('save', function (next) {
|
|
||||||
var currWord = this.language;
|
|
||||||
|
|
||||||
//English is the default backup language
|
|
||||||
this.language = 'en';
|
|
||||||
if(constants.wordToLangCode.has(currWord)){
|
|
||||||
this.language = constants.wordToLangCode[currWord];
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@ -24,20 +24,6 @@ smtpTransport.verify(function(error, success) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* A Validation function for local strategy properties
|
|
||||||
*/
|
|
||||||
var validateLocalStrategyProperty = function(property) {
|
|
||||||
var propHasLength;
|
|
||||||
if (property) {
|
|
||||||
propHasLength = !!property.length;
|
|
||||||
} else {
|
|
||||||
propHasLength = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((this.provider !== 'local' && !this.updated) || propHasLength);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User Schema
|
* User Schema
|
||||||
*/
|
*/
|
||||||
@ -78,8 +64,6 @@ var UserSchema = new Schema({
|
|||||||
type: String,
|
type: String,
|
||||||
default: 'local'
|
default: 'local'
|
||||||
},
|
},
|
||||||
providerData: {},
|
|
||||||
additionalProvidersData: {},
|
|
||||||
roles: {
|
roles: {
|
||||||
type: [{
|
type: [{
|
||||||
type: String,
|
type: String,
|
||||||
@ -116,10 +100,6 @@ var UserSchema = new Schema({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
UserSchema.virtual('displayName').get(function () {
|
|
||||||
return this.firstName + ' ' + this.lastName;
|
|
||||||
});
|
|
||||||
|
|
||||||
UserSchema.plugin(timeStampPlugin, {
|
UserSchema.plugin(timeStampPlugin, {
|
||||||
createdPath: 'created',
|
createdPath: 'created',
|
||||||
modifiedPath: 'lastModified',
|
modifiedPath: 'lastModified',
|
||||||
|
|||||||
@ -31,7 +31,7 @@ module.exports = function(app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.route('/forms/:formIdFast([a-zA-Z0-9]+)')
|
app.route('/forms/:formIdFast([a-zA-Z0-9]+)')
|
||||||
.post(forms.createSubmission)
|
.post(forms.createSubmission);
|
||||||
|
|
||||||
app.route('/forms')
|
app.route('/forms')
|
||||||
.get(auth.isAuthenticatedOrApiKey, forms.list)
|
.get(auth.isAuthenticatedOrApiKey, forms.list)
|
||||||
|
|||||||
@ -12,6 +12,7 @@ module.exports = function(app) {
|
|||||||
var users = require('../../app/controllers/users.server.controller');
|
var users = require('../../app/controllers/users.server.controller');
|
||||||
|
|
||||||
// Setting up the users profile api
|
// Setting up the users profile api
|
||||||
|
app.route('/users/password').post(users.requiresLogin, users.changePassword);
|
||||||
app.route('/users/me').get(auth.isAuthenticatedOrApiKey, users.getUser);
|
app.route('/users/me').get(auth.isAuthenticatedOrApiKey, users.getUser);
|
||||||
app.route('/users').put(auth.isAuthenticatedOrApiKey, users.update);
|
app.route('/users').put(auth.isAuthenticatedOrApiKey, users.update);
|
||||||
|
|
||||||
@ -19,8 +20,7 @@ module.exports = function(app) {
|
|||||||
app.route('/auth/verify/:token').get(users.validateVerificationToken);
|
app.route('/auth/verify/:token').get(users.validateVerificationToken);
|
||||||
app.route('/auth/verify').post(users.resendVerificationEmail);
|
app.route('/auth/verify').post(users.resendVerificationEmail);
|
||||||
|
|
||||||
// Setting up the users password api
|
// Setting up the password reset api
|
||||||
app.route('/users/password').post(users.requiresLogin, users.changePassword);
|
|
||||||
app.route('/auth/forgot').post(users.forgot);
|
app.route('/auth/forgot').post(users.forgot);
|
||||||
app.route('/auth/reset/:token').get(users.validateResetToken);
|
app.route('/auth/reset/:token').get(users.validateResetToken);
|
||||||
app.route('/auth/reset/:token').post(users.reset);
|
app.route('/auth/reset/:token').post(users.reset);
|
||||||
@ -33,7 +33,4 @@ module.exports = function(app) {
|
|||||||
app.route('/auth/signout').get(users.signout);
|
app.route('/auth/signout').get(users.signout);
|
||||||
|
|
||||||
app.route('/auth/genkey').get(users.requiresLogin, users.generateAPIKey);
|
app.route('/auth/genkey').get(users.requiresLogin, users.generateAPIKey);
|
||||||
|
|
||||||
// Finish by binding the user middleware
|
|
||||||
app.param('userId', users.userByID);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,7 +9,8 @@ var should = require('should'),
|
|||||||
User = mongoose.model('User'),
|
User = mongoose.model('User'),
|
||||||
Form = mongoose.model('Form'),
|
Form = mongoose.model('Form'),
|
||||||
Field = mongoose.model('Field'),
|
Field = mongoose.model('Field'),
|
||||||
FormSubmission = mongoose.model('FormSubmission');
|
FormSubmission = mongoose.model('FormSubmission'),
|
||||||
|
async = require('async');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Globals
|
* Globals
|
||||||
@ -68,7 +69,6 @@ describe('Form Routes Unit tests', function() {
|
|||||||
.send({form: myForm})
|
.send({form: myForm})
|
||||||
.expect(401)
|
.expect(401)
|
||||||
.end(function(FormSaveErr, FormSaveRes) {
|
.end(function(FormSaveErr, FormSaveRes) {
|
||||||
console.log(FormSaveRes.text)
|
|
||||||
// Call the assertion callback
|
// Call the assertion callback
|
||||||
done(FormSaveErr);
|
done(FormSaveErr);
|
||||||
});
|
});
|
||||||
@ -83,7 +83,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
|
// Create new Form model instance
|
||||||
var FormObj = new Form(myForm);
|
var FormObj = new Form(myForm);
|
||||||
|
|
||||||
@ -105,6 +105,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) {
|
it(' > should not be able to delete an Form if not signed in', function(done) {
|
||||||
// Set Form user
|
// Set Form user
|
||||||
myForm.admin = user;
|
myForm.admin = user;
|
||||||
@ -146,6 +163,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) {
|
it(' > should not be able to save a Form if no title is provided', function(done) {
|
||||||
// Set Form with a invalid title field
|
// Set Form with a invalid title field
|
||||||
myForm.title = '';
|
myForm.title = '';
|
||||||
@ -165,10 +192,22 @@ describe('Form Routes Unit tests', function() {
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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
|
// Save a new Form
|
||||||
loginSession.post('/forms')
|
loginSession.post('/forms')
|
||||||
@ -182,7 +221,7 @@ describe('Form Routes Unit tests', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update Form title
|
// Update Form title
|
||||||
myForm.title = 'WHY YOU GOTTA BE SO MEAN?';
|
myForm.title = 'WHY YOU GOTTA BE SO FORMULAIC?';
|
||||||
|
|
||||||
// Update an existing Form
|
// Update an existing Form
|
||||||
loginSession.put('/forms/' + FormSaveRes.body._id)
|
loginSession.put('/forms/' + FormSaveRes.body._id)
|
||||||
@ -197,13 +236,12 @@ describe('Form Routes Unit tests', function() {
|
|||||||
|
|
||||||
// Set assertions
|
// Set assertions
|
||||||
(FormUpdateRes.body._id).should.equal(FormSaveRes.body._id);
|
(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
|
// Call the assertion callback
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it(' > should be able to delete a Form if signed in', function(done) {
|
it(' > should be able to delete a Form if signed in', function(done) {
|
||||||
@ -238,10 +276,9 @@ describe('Form Routes Unit tests', function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to save new form while logged in', function(done){
|
it(' > should be able to save new form while logged in', function(done){
|
||||||
// Save a new Form
|
// Save a new Form
|
||||||
authenticatedSession.post('/forms')
|
authenticatedSession.post('/forms')
|
||||||
.send({form: myForm})
|
.send({form: myForm})
|
||||||
@ -271,12 +308,70 @@ describe('Form Routes Unit tests', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(' > should be able to get list of users\' forms sorted by date created while logged in', function(done) {
|
||||||
|
var myForm1 = {
|
||||||
|
title: 'First Form',
|
||||||
|
language: 'en',
|
||||||
|
admin: user.id,
|
||||||
|
form_fields: [
|
||||||
|
new Field({'fieldType':'textfield', 'title':'First Name', 'fieldValue': ''}),
|
||||||
|
new Field({'fieldType':'checkbox', 'title':'nascar', 'fieldValue': ''}),
|
||||||
|
new Field({'fieldType':'checkbox', 'title':'hockey', 'fieldValue': ''})
|
||||||
|
],
|
||||||
|
isLive: true
|
||||||
|
};
|
||||||
|
|
||||||
|
var myForm2 = {
|
||||||
|
title: 'Second Form',
|
||||||
|
language: 'en',
|
||||||
|
admin: user.id,
|
||||||
|
form_fields: [
|
||||||
|
new Field({'fieldType':'textfield', 'title':'Last Name', 'fieldValue': ''}),
|
||||||
|
new Field({'fieldType':'checkbox', 'title':'formula one', 'fieldValue': ''}),
|
||||||
|
new Field({'fieldType':'checkbox', 'title':'football', 'fieldValue': ''})
|
||||||
|
],
|
||||||
|
isLive: true
|
||||||
|
};
|
||||||
|
|
||||||
|
var FormObj1 = new Form(myForm1);
|
||||||
|
var FormObj2 = new Form(myForm2);
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function(callback) {
|
||||||
|
FormObj1.save(function(err){
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
FormObj2.save(function(err){
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
loginSession.get('/forms')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
res.body.length.should.equal(2);
|
||||||
|
res.body[0].title.should.equal('Second Form');
|
||||||
|
res.body[1].title.should.equal('First Form');
|
||||||
|
|
||||||
|
// Call the assertion callback
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], function (err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
afterEach('should be able to signout user', function(done){
|
afterEach('should be able to signout user', function(done){
|
||||||
authenticatedSession.get('/auth/signout')
|
authenticatedSession.get('/auth/signout')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(signoutErr, signoutRes) {
|
.end(function(signoutErr, signoutRes) {
|
||||||
// Handle signout error
|
// Handle signout error
|
||||||
if (signoutErr) return done(signoutErr);
|
if (signoutErr) {
|
||||||
|
return done(signoutErr);
|
||||||
|
}
|
||||||
authenticatedSession.destroy();
|
authenticatedSession.destroy();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -17,7 +17,6 @@ var exampleDemo = {
|
|||||||
address: '880-9650 Velit. St.',
|
address: '880-9650 Velit. St.',
|
||||||
city: '',
|
city: '',
|
||||||
dateOfBirth: '10',
|
dateOfBirth: '10',
|
||||||
displayName: 'Test User',
|
|
||||||
email: 'polydaic@gmail.com',
|
email: 'polydaic@gmail.com',
|
||||||
firstName: 'Test User',
|
firstName: 'Test User',
|
||||||
hin: '',
|
hin: '',
|
||||||
@ -83,7 +82,7 @@ describe('FormSubmission Model Unit Tests:', function() {
|
|||||||
firstName: 'Full',
|
firstName: 'Full',
|
||||||
lastName: 'Name',
|
lastName: 'Name',
|
||||||
email: 'test1@test.com',
|
email: 'test1@test.com',
|
||||||
username: 'test1'+Date.now(),
|
username: 'test1',
|
||||||
password: 'password',
|
password: 'password',
|
||||||
provider: 'local'
|
provider: 'local'
|
||||||
});
|
});
|
||||||
@ -198,6 +197,7 @@ describe('FormSubmission Model Unit Tests:', function() {
|
|||||||
|
|
||||||
it('should preserve deleted form_fields that have submissions without any problems', function(done) {
|
it('should preserve deleted form_fields that have submissions without any problems', function(done) {
|
||||||
|
|
||||||
|
var fieldPropertiesToOmit = ['deletePreserved', 'globalId', 'lastModified', 'created', '_id', 'submissionId', 'isSubmission', 'validFieldTypes', 'title'];
|
||||||
var old_fields = myForm.toObject().form_fields;
|
var old_fields = myForm.toObject().form_fields;
|
||||||
var new_form_fields = _.clone(myForm.toObject().form_fields);
|
var new_form_fields = _.clone(myForm.toObject().form_fields);
|
||||||
new_form_fields.splice(0, 1);
|
new_form_fields.splice(0, 1);
|
||||||
@ -209,8 +209,8 @@ describe('FormSubmission Model Unit Tests:', function() {
|
|||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist(_form.form_fields);
|
should.exist(_form.form_fields);
|
||||||
|
|
||||||
var actual_fields = _.deepOmit(_form.toObject().form_fields, ['deletePreserved', 'globalId', 'lastModified', 'created', '_id', 'submissionId', 'isSubmission', 'validFieldTypes', 'title']);
|
var actual_fields = _.deepOmit(_form.toObject().form_fields, fieldPropertiesToOmit);
|
||||||
old_fields = _.deepOmit(old_fields, ['deletePreserved', 'globalId', 'lastModified', 'created', '_id', 'submissionId', 'isSubmission', 'validFieldTypes', 'title']);
|
old_fields = _.deepOmit(old_fields, fieldPropertiesToOmit);
|
||||||
|
|
||||||
should.deepEqual(actual_fields, old_fields, 'old form_fields not equal to newly saved form_fields');
|
should.deepEqual(actual_fields, old_fields, 'old form_fields not equal to newly saved form_fields');
|
||||||
done();
|
done();
|
||||||
|
|||||||
@ -21,8 +21,7 @@ var credentials, user;
|
|||||||
* Form routes tests
|
* Form routes tests
|
||||||
*/
|
*/
|
||||||
describe('Form Submission Routes Unit tests', function() {
|
describe('Form Submission Routes Unit tests', function() {
|
||||||
var FormObj, _Submission, submissionSession, _SubmissionBody
|
var FormObj, _Submission, submissionSession, _SubmissionBody;
|
||||||
|
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
|
|
||||||
@ -237,6 +236,4 @@ describe('Form Submission Routes Unit tests', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -24,7 +24,7 @@ var invalidFormFields = [
|
|||||||
{fieldType:'textfield', title:'First Name', fieldValue: 'John Smith', deletePreserved: false},
|
{fieldType:'textfield', title:'First Name', fieldValue: 'John Smith', deletePreserved: false},
|
||||||
{fieldType:'link', title:'Your Website', deletePreserved: false, _id:'5c9e22028e907634f45f59a6'},
|
{fieldType:'link', title:'Your Website', deletePreserved: false, _id:'5c9e22028e907634f45f59a6'},
|
||||||
{fieldType:'number', title:'Your Age'}
|
{fieldType:'number', title:'Your Age'}
|
||||||
]
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests
|
* Unit tests
|
||||||
|
|||||||
@ -1,70 +1,72 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
var util = require('util')
|
var util = require('util'),
|
||||||
, assert = require('assert')
|
assert = require('assert'),
|
||||||
, mongoose = require('mongoose')
|
mongoose = require('mongoose'),
|
||||||
, timestamp = require('../../libs/timestamp.server.plugin')
|
timestamp = require('../../libs/timestamp.server.plugin'),
|
||||||
, Schema = mongoose.Schema
|
Schema = mongoose.Schema,
|
||||||
, ObjectId = Schema.ObjectId
|
ObjectId = Schema.ObjectId;
|
||||||
|
|
||||||
// Run tests
|
// Run tests
|
||||||
describe('Timestamp', function () {
|
describe('Timestamp', function () {
|
||||||
describe('#default()', function () {
|
describe('#default()', function () {
|
||||||
var FooSchema = new Schema()
|
var FooSchema = new Schema();
|
||||||
FooSchema.plugin(timestamp)
|
FooSchema.plugin(timestamp);
|
||||||
var FooModel = mongoose.model('timeFoo', FooSchema)
|
var FooModel = mongoose.model('timeFoo', FooSchema),
|
||||||
, bar = new FooModel()
|
bar = new FooModel();
|
||||||
|
|
||||||
before(function () {
|
before(function () {
|
||||||
FooModel.remove(function (err) {
|
FooModel.remove(function (err) {
|
||||||
assert.strictEqual(err, null)
|
assert.strictEqual(err, null);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should have custom properties', function (done) {
|
it('should have custom properties', function (done) {
|
||||||
assert.strictEqual(typeof FooSchema.virtuals.created, 'object')
|
assert.strictEqual(typeof FooSchema.virtuals.created, 'object');
|
||||||
assert.strictEqual(typeof FooSchema.paths.modified, 'object')
|
assert.strictEqual(typeof FooSchema.paths.modified, 'object');
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should create the default attributes', function (done) {
|
it('should create the default attributes', function (done) {
|
||||||
bar.save(function (err, doc) {
|
bar.save(function (err, doc) {
|
||||||
assert.strictEqual(err, null)
|
assert.strictEqual(err, null);
|
||||||
assert.strictEqual(util.isDate(doc.created), true)
|
assert.strictEqual(util.isDate(doc.created), true);
|
||||||
assert.strictEqual(util.isDate(doc.modified), true)
|
assert.strictEqual(util.isDate(doc.modified), true);
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
describe('#custom()', function () {
|
describe('#custom()', function () {
|
||||||
var FooSchema = new Schema()
|
var FooSchema = new Schema();
|
||||||
FooSchema.plugin(timestamp, {
|
FooSchema.plugin(timestamp, {
|
||||||
createdPath: 'oh'
|
createdPath: 'oh',
|
||||||
, modifiedPath: 'hai'
|
modifiedPath: 'hai',
|
||||||
, useVirtual: false
|
useVirtual: false
|
||||||
})
|
});
|
||||||
var BarModel = mongoose.model('timeBar', FooSchema)
|
var BarModel = mongoose.model('timeBar', FooSchema),
|
||||||
, bar = new BarModel()
|
bar = new BarModel();
|
||||||
|
|
||||||
before(function () {
|
before(function () {
|
||||||
BarModel.remove(function (err) {
|
BarModel.remove(function (err) {
|
||||||
assert.strictEqual(err, null)
|
assert.strictEqual(err, null);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should have custom properties', function (done) {
|
it('should have custom properties', function (done) {
|
||||||
assert.strictEqual(typeof FooSchema.paths.oh, 'object')
|
assert.strictEqual(typeof FooSchema.paths.oh, 'object');
|
||||||
assert.strictEqual(typeof FooSchema.paths.hai, 'object')
|
assert.strictEqual(typeof FooSchema.paths.hai, 'object');
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should create custom attributes', function (done) {
|
it('should create custom attributes', function (done) {
|
||||||
bar.save(function (err, doc) {
|
bar.save(function (err, doc) {
|
||||||
assert.strictEqual(err, null)
|
assert.strictEqual(err, null);
|
||||||
assert.strictEqual(util.isDate(doc.oh), true)
|
assert.strictEqual(util.isDate(doc.oh), true);
|
||||||
assert.strictEqual(util.isDate(doc.hai), true)
|
assert.strictEqual(util.isDate(doc.hai), true);
|
||||||
done()
|
done();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
@ -6,24 +6,23 @@ var should = require('should'),
|
|||||||
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),
|
||||||
|
async = require('async');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Globals
|
* Globals
|
||||||
*/
|
*/
|
||||||
var credentials, _User, activateToken, userSession;
|
var credentials, _User, userSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Form routes tests
|
* Form routes tests
|
||||||
*/
|
*/
|
||||||
describe('User CRUD tests', function() {
|
describe('User CRUD tests', function() {
|
||||||
this.timeout(30000);
|
before(function() {
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
// Create user credentials
|
// Create user credentials
|
||||||
credentials = {
|
credentials = {
|
||||||
email: 'test732@test.com',
|
email: 'test099@test.com',
|
||||||
username: 'test732',
|
username: 'test099',
|
||||||
password: 'password3223'
|
password: 'password3223'
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -31,77 +30,424 @@ describe('User CRUD tests', function() {
|
|||||||
_User = {
|
_User = {
|
||||||
email: credentials.email,
|
email: credentials.email,
|
||||||
username: credentials.username,
|
username: credentials.username,
|
||||||
password: credentials.password
|
password: credentials.password,
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Smith'
|
||||||
};
|
};
|
||||||
|
|
||||||
//Initialize Session
|
//Initialize Session
|
||||||
userSession = Session(app);
|
userSession = Session(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(' > Create, Verify and Activate a User > ', function() {
|
describe(' > Create, Verify and Activate a User > ', function() {
|
||||||
|
this.timeout(10000);
|
||||||
it('should be able to create a temporary (non-activated) User', function(done) {
|
it('should be able to create and activate a User', function(done) {
|
||||||
userSession.post('/auth/signup')
|
async.waterfall([
|
||||||
.send(_User)
|
function(callback) {
|
||||||
.expect(200)
|
userSession.post('/auth/signup')
|
||||||
.end(function(FormSaveErr) {
|
.send(_User)
|
||||||
// Handle error
|
.expect(200)
|
||||||
should.not.exist(FormSaveErr);
|
.end(function(err) {
|
||||||
|
callback(err);
|
||||||
tmpUser.findOne({username: _User.username}, function (err, user) {
|
});
|
||||||
should.not.exist(err);
|
},
|
||||||
|
function(callback) {
|
||||||
|
tmpUser.findOne({username: _User.username})
|
||||||
|
.lean()
|
||||||
|
.exec(function (err, user) {
|
||||||
should.exist(user);
|
should.exist(user);
|
||||||
|
|
||||||
_User.username.should.equal(user.username);
|
_User.username.should.equal(user.username);
|
||||||
_User.firstName.should.equal(user.firstName);
|
_User.firstName.should.equal(user.firstName);
|
||||||
_User.lastName.should.equal(user.lastName);
|
_User.lastName.should.equal(user.lastName);
|
||||||
activateToken = user.GENERATED_VERIFYING_URL;
|
callback(err, user.GENERATED_VERIFYING_URL);
|
||||||
|
|
||||||
userSession.get('/auth/verify/'+activateToken)
|
|
||||||
.expect(200)
|
|
||||||
.end(function(VerifyErr, VerifyRes) {
|
|
||||||
// Handle error
|
|
||||||
if (VerifyErr) {
|
|
||||||
return done(VerifyErr);
|
|
||||||
}
|
|
||||||
|
|
||||||
(VerifyRes.text).should.equal('User successfully verified');
|
|
||||||
|
|
||||||
userSession.post('/auth/signin')
|
|
||||||
.send(credentials)
|
|
||||||
.expect('Content-Type', /json/)
|
|
||||||
.expect(200)
|
|
||||||
.end(function(signinErr, signinRes) {
|
|
||||||
// Handle signin error
|
|
||||||
if (signinErr) {
|
|
||||||
return done(signinErr);
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = signinRes.body;
|
|
||||||
(user.username).should.equal(credentials.username);
|
|
||||||
|
|
||||||
userSession.get('/auth/signout')
|
|
||||||
.expect(200)
|
|
||||||
.end(function(signoutErr, signoutRes) {
|
|
||||||
|
|
||||||
// Handle signout error
|
|
||||||
if (signoutErr) {
|
|
||||||
return done(signoutErr);
|
|
||||||
}
|
|
||||||
|
|
||||||
(signoutRes.text).should.equal('You have successfully logged out.');
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
|
function(activateToken, callback) {
|
||||||
|
userSession.get('/auth/verify/' + activateToken)
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
(res.text).should.equal('User successfully verified');
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
userSession.post('/auth/signin')
|
||||||
|
.send(credentials)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
(res.body.username).should.equal(credentials.username);
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
userSession.get('/auth/signout')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
(res.text).should.equal('You have successfully logged out.');
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
User.findOne({ username: _User.username })
|
||||||
|
.lean()
|
||||||
|
.exec(function(err, user){
|
||||||
|
should.exist(user);
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], function (err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
after(function(done){
|
||||||
|
User.remove().exec(done);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function(done) {
|
describe(' > Reset Password > ', function(){
|
||||||
|
this.timeout(10000);
|
||||||
|
beforeEach(function(done){
|
||||||
|
var UserObj = new User(_User);
|
||||||
|
UserObj.save(function(err){
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to reset password of a created User with a valid passwordResetToken', function(done) {
|
||||||
|
var changedPassword = 'password1234';
|
||||||
|
var resetPasswordToken;
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function(callback) {
|
||||||
|
userSession.post('/auth/forgot')
|
||||||
|
.send({ username: _User.username })
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
User.findOne({ username: _User.username })
|
||||||
|
.lean()
|
||||||
|
.exec(function(err, user){
|
||||||
|
if(err){
|
||||||
|
callback(err);
|
||||||
|
}
|
||||||
|
callback(null, user.resetPasswordToken);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(resetPasswordToken, callback) {
|
||||||
|
userSession.get('/auth/reset/' + resetPasswordToken)
|
||||||
|
.expect(302)
|
||||||
|
.end(function(err) {
|
||||||
|
callback(err, resetPasswordToken);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(resetPasswordToken, callback) {
|
||||||
|
userSession.post('/auth/reset/' + resetPasswordToken)
|
||||||
|
.send({
|
||||||
|
newPassword: changedPassword,
|
||||||
|
verifyPassword: changedPassword
|
||||||
|
})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
callback(err, resetPasswordToken);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(resetPasswordToken, callback) {
|
||||||
|
User.findOne({ username: _User.username })
|
||||||
|
.exec(function(err, user){
|
||||||
|
should.exist(user);
|
||||||
|
user.authenticate(changedPassword).should.be.true();
|
||||||
|
should.not.exist(user.resetPasswordToken);
|
||||||
|
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], function (err, result) {
|
||||||
|
credentials.password = changedPassword;
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be not able to reset password of a created User with a invalid passwordResetToken', function(done) {
|
||||||
|
var changedPassword = 'password4321';
|
||||||
|
var resetPasswordToken = 'thisIsNotAValidToken';
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function(callback) {
|
||||||
|
userSession.post('/auth/forgot')
|
||||||
|
.send({ username: credentials.username })
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
userSession.get('/auth/reset/' + resetPasswordToken)
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
userSession.post('/auth/reset/' + resetPasswordToken)
|
||||||
|
.send({
|
||||||
|
newPassword: changedPassword,
|
||||||
|
verifyPassword: changedPassword
|
||||||
|
})
|
||||||
|
.expect(400)
|
||||||
|
.end(function(err, res) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
User.findOne({ username: _User.username })
|
||||||
|
.exec(function(err, user){
|
||||||
|
should.exist(user);
|
||||||
|
user.authenticate(changedPassword).should.be.false();
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], function (err, result) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function(done){
|
||||||
|
User.remove({ username: credentials.username }).exec(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe(' > User Profile Changes > ', function(){
|
||||||
|
var profileSession = new Session(app);
|
||||||
|
|
||||||
|
this.timeout(10000);
|
||||||
|
beforeEach(function(done){
|
||||||
|
var UserObj = new User(_User);
|
||||||
|
UserObj.save(function(err, user){
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to change password when logged in', function(done) {
|
||||||
|
var changedPassword = 'aVeryBadPassword';
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function(callback) {
|
||||||
|
userSession.post('/auth/signin')
|
||||||
|
.send({
|
||||||
|
username: _User.username,
|
||||||
|
password: _User.password
|
||||||
|
})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
userSession.post('/users/password')
|
||||||
|
.send({
|
||||||
|
currentPassword: _User.password,
|
||||||
|
newPassword: changedPassword,
|
||||||
|
verifyPassword: changedPassword
|
||||||
|
})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
User.findOne({ username: _User.username })
|
||||||
|
.exec(function(err, user){
|
||||||
|
user.authenticate(changedPassword).should.be.true();
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], function (err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to update user when logged in', function(done) {
|
||||||
|
var newUser = {};
|
||||||
|
newUser.firstName = 'goodnight';
|
||||||
|
newUser.lastName = 'everyone';
|
||||||
|
|
||||||
|
newUser.email = 'grcg@gcrc.com';
|
||||||
|
newUser.username = 'grcg';
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function(callback) {
|
||||||
|
userSession.post('/auth/signin')
|
||||||
|
.send({
|
||||||
|
username: _User.username,
|
||||||
|
password: _User.password
|
||||||
|
})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
userSession.put('/users')
|
||||||
|
.send(newUser)
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
User.findOne({ username: newUser.username })
|
||||||
|
.exec(function(err, user){
|
||||||
|
user.firstName.should.equal(newUser.firstName);
|
||||||
|
user.lastName.should.equal(newUser.lastName);
|
||||||
|
user.email.should.equal(newUser.email);
|
||||||
|
user.username.should.equal(newUser.username);
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], function (err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to fetch user when logged in', function(done) {
|
||||||
|
async.waterfall([
|
||||||
|
function(callback) {
|
||||||
|
userSession.post('/auth/signin')
|
||||||
|
.send({
|
||||||
|
username: _User.username,
|
||||||
|
password: _User.password
|
||||||
|
})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
userSession.get('/users/me')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
var user = res.body;
|
||||||
|
user.firstName.should.equal(_User.firstName);
|
||||||
|
user.lastName.should.equal(_User.lastName);
|
||||||
|
user.email.should.equal(_User.email);
|
||||||
|
user.username.should.equal(_User.username);
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], function (err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function(done){
|
||||||
|
userSession.get('/auth/signout')
|
||||||
|
.end(function(err, res) {
|
||||||
|
User.remove().exec(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe(' > User API > ', function(){
|
||||||
|
var apiKey;
|
||||||
|
|
||||||
|
this.timeout(10000);
|
||||||
|
before(function(done){
|
||||||
|
var UserObj = new User(_User);
|
||||||
|
UserObj.save(function(err, user){
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to request API Key', function(done) {
|
||||||
|
async.waterfall([
|
||||||
|
function(callback) {
|
||||||
|
userSession.post('/auth/signin')
|
||||||
|
.send({
|
||||||
|
username: _User.username,
|
||||||
|
password: _User.password
|
||||||
|
})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
userSession.get('/auth/genkey')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
apiKey = res.body.apiKey;
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
userSession.get('/auth/signout')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
userSession.get('/users/me?apikey=' + apiKey)
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
var user = res.body;
|
||||||
|
|
||||||
|
user.firstName.should.equal(_User.firstName);
|
||||||
|
user.lastName.should.equal(_User.lastName);
|
||||||
|
user.email.should.equal(_User.email);
|
||||||
|
user.username.should.equal(_User.username);
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
], function (err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to update user with API key', function(done) {
|
||||||
|
var newUser = {};
|
||||||
|
newUser.firstName = 'goodnight';
|
||||||
|
newUser.lastName = 'everyone';
|
||||||
|
|
||||||
|
newUser.email = 'grcg@gcrc.com';
|
||||||
|
newUser.username = 'grcg';
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function(callback) {
|
||||||
|
userSession.put('/users?apikey=' + apiKey)
|
||||||
|
.send(newUser)
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
User.findOne({ username: newUser.username })
|
||||||
|
.exec(function(err, user){
|
||||||
|
user.firstName.should.equal(newUser.firstName);
|
||||||
|
user.lastName.should.equal(newUser.lastName);
|
||||||
|
user.email.should.equal(newUser.email);
|
||||||
|
user.username.should.equal(newUser.username);
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], function (err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
after(function(done){
|
||||||
|
User.remove().exec(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
after(function(done) {
|
||||||
User.remove().exec(function () {
|
User.remove().exec(function () {
|
||||||
tmpUser.remove().exec(function(){
|
tmpUser.remove().exec(function(){
|
||||||
userSession.destroy();
|
userSession.destroy();
|
||||||
|
|||||||
@ -6,7 +6,6 @@ block content
|
|||||||
h3.col-md-12.text-center=__('500_HEADER')
|
h3.col-md-12.text-center=__('500_HEADER')
|
||||||
div.col-md-4.col-md-offset-4
|
div.col-md-4.col-md-offset-4
|
||||||
if process.env.NODE_ENV == 'development' || process.env.NODE_ENV == 'test'
|
if process.env.NODE_ENV == 'development' || process.env.NODE_ENV == 'test'
|
||||||
|
|
||||||
div.col-md-12.text-center(style="padding-bottom: 50px;")
|
div.col-md-12.text-center(style="padding-bottom: 50px;")
|
||||||
| #{error}
|
| #{error}
|
||||||
else
|
else
|
||||||
|
|||||||
60
config/env/secure.js
vendored
60
config/env/secure.js
vendored
@ -1,60 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
baseUrl: 'https://forms.polydaic.com',
|
|
||||||
port: 8443,
|
|
||||||
db: {
|
|
||||||
uri: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || process.env.MONGODB_URI || 'mongodb://127.0.0.1/mean',
|
|
||||||
options: {
|
|
||||||
user: '',
|
|
||||||
pass: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
log: {
|
|
||||||
// Can specify one of 'combined', 'common', 'dev', 'short', 'tiny'
|
|
||||||
format: 'combined',
|
|
||||||
// Stream defaults to process.stdout
|
|
||||||
// Uncomment to enable logging to a log on the file system
|
|
||||||
options: {
|
|
||||||
stream: 'access.log'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
sessionCookie: {
|
|
||||||
path: '/',
|
|
||||||
httpOnly: false,
|
|
||||||
// If secure is set to true then it will cause the cookie to be set
|
|
||||||
// only when SSL-enabled (HTTPS) is used, and otherwise it won't
|
|
||||||
// set a cookie. 'true' is recommended yet it requires the above
|
|
||||||
// mentioned pre-requisite.
|
|
||||||
secure: true,
|
|
||||||
// Only set the maxAge to null if the cookie shouldn't be expired
|
|
||||||
// at all. The cookie will expunge when the browser is closed.
|
|
||||||
maxAge: 7200,
|
|
||||||
// To set the cookie in a specific domain uncomment the following
|
|
||||||
// setting:
|
|
||||||
domain: process.env.BASE_URL || 'localhost:3000'
|
|
||||||
},
|
|
||||||
assets: {
|
|
||||||
css: 'public/dist/application.min.css',
|
|
||||||
js: 'public/dist/application.min.js'
|
|
||||||
},
|
|
||||||
mailer: {
|
|
||||||
from: process.env.MAILER_FROM || '',
|
|
||||||
options: process.env.MAILER_SMTP_HOST ? { //Uses custom SMTP if MAILER_SMTP_HOST is set
|
|
||||||
host: process.env.MAILER_SMTP_HOST || '',
|
|
||||||
port: process.env.MAILER_SMTP_PORT || 587,
|
|
||||||
secure: process.env.MAILER_SMTP_SECURE || true,
|
|
||||||
auth: {
|
|
||||||
user: process.env.MAILER_EMAIL_ID || '',
|
|
||||||
pass: process.env.MAILER_PASSWORD || ''
|
|
||||||
}
|
|
||||||
} : {
|
|
||||||
service: process.env.MAILER_SERVICE_PROVIDER || '',
|
|
||||||
auth: {
|
|
||||||
user: process.env.MAILER_EMAIL_ID || '',
|
|
||||||
pass: process.env.MAILER_PASSWORD || ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -39,8 +39,9 @@ var configureSocketIO = function (app, db) {
|
|||||||
var supportedLanguages = ['en', 'de', 'fr', 'it', 'es'];
|
var supportedLanguages = ['en', 'de', 'fr', 'it', 'es'];
|
||||||
|
|
||||||
function containsAnySupportedLanguages(preferredLanguages){
|
function containsAnySupportedLanguages(preferredLanguages){
|
||||||
for (var i = 0; i < preferredLanguages.length; i++) {
|
var i, currIndex;
|
||||||
var currIndex = supportedLanguages.indexOf(preferredLanguages[i]);
|
for (i = 0; i < preferredLanguages.length; i++) {
|
||||||
|
currIndex = supportedLanguages.indexOf(preferredLanguages[i]);
|
||||||
if (currIndex > -1) {
|
if (currIndex > -1) {
|
||||||
return supportedLanguages[currIndex];
|
return supportedLanguages[currIndex];
|
||||||
}
|
}
|
||||||
@ -148,8 +149,6 @@ module.exports = function(db) {
|
|||||||
// reassign url
|
// reassign url
|
||||||
req.url = subdomainPath;
|
req.url = subdomainPath;
|
||||||
|
|
||||||
req.userId = user._id;
|
|
||||||
|
|
||||||
// Q.E.D.
|
// Q.E.D.
|
||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
@ -200,7 +199,7 @@ module.exports = function(db) {
|
|||||||
app.use(morgan(logger.getLogFormat(), logger.getMorganOptions()));
|
app.use(morgan(logger.getLogFormat(), logger.getMorganOptions()));
|
||||||
|
|
||||||
// Environment dependent middleware
|
// Environment dependent middleware
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
||||||
// Disable views cache
|
// Disable views cache
|
||||||
app.set('view cache', false);
|
app.set('view cache', false);
|
||||||
} else if (process.env.NODE_ENV === 'production') {
|
} else if (process.env.NODE_ENV === 'production') {
|
||||||
@ -228,7 +227,6 @@ module.exports = function(db) {
|
|||||||
|
|
||||||
// Setting the app router and static folder
|
// Setting the app router and static folder
|
||||||
app.use('/static', express.static(path.resolve('./public')));
|
app.use('/static', express.static(path.resolve('./public')));
|
||||||
app.use('/uploads', express.static(path.resolve('./uploads')));
|
|
||||||
|
|
||||||
// CookieParser should be above session
|
// CookieParser should be above session
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
@ -263,18 +261,20 @@ module.exports = function(db) {
|
|||||||
//Visitor Language Detection
|
//Visitor Language Detection
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
var acceptLanguage = req.headers['accept-language'];
|
var acceptLanguage = req.headers['accept-language'];
|
||||||
|
|
||||||
|
var languages, supportedLanguage;
|
||||||
|
|
||||||
if(acceptLanguage){
|
if(acceptLanguage){
|
||||||
var languages = acceptLanguage.match(/[a-z]{2}(?!-)/g) || [];
|
languages = acceptLanguage.match(/[a-z]{2}(?!-)/g) || [];
|
||||||
|
supportedLanguage = containsAnySupportedLanguages(languages);
|
||||||
|
}
|
||||||
|
|
||||||
var supportedLanguage = containsAnySupportedLanguages(languages);
|
if(!req.user && supportedLanguage !== null){
|
||||||
if(!req.user && supportedLanguage !== null){
|
var currLanguage = res.cookie('userLang');
|
||||||
var currLanguage = res.cookie('userLang');
|
if(currLanguage && currLanguage !== supportedLanguage || !currLanguage){
|
||||||
|
res.clearCookie('userLang');
|
||||||
if(currLanguage && currLanguage !== supportedLanguage || !currLanguage){
|
res.cookie('userLang', supportedLanguage, { maxAge: 90000, httpOnly: true });
|
||||||
res.clearCookie('userLang');
|
} else if(req.user && (!req.cookies.hasOwnProperty('userLang') || req.cookies.userLang !== req.user.language) ){
|
||||||
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 });
|
res.cookie('userLang', req.user.language, { maxAge: 90000, httpOnly: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,7 +290,7 @@ module.exports = function(db) {
|
|||||||
app.use(function (req, res, next) {
|
app.use(function (req, res, next) {
|
||||||
|
|
||||||
// Website you wish to allow to connect
|
// Website you wish to allow to connect
|
||||||
res.setHeader('Access-Control-Allow-Origin', 'https://sentry.polydaic.com');
|
res.setHeader('Access-Control-Allow-Origin', 'https://sentry.io');
|
||||||
|
|
||||||
// Request methods you wish to allow
|
// Request methods you wish to allow
|
||||||
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
|
||||||
@ -321,7 +321,8 @@ module.exports = function(db) {
|
|||||||
|
|
||||||
// Log it
|
// Log it
|
||||||
client.captureError(err);
|
client.captureError(err);
|
||||||
|
|
||||||
|
// Error page
|
||||||
res.status(500).render('500', {
|
res.status(500).render('500', {
|
||||||
error: err.stack
|
error: err.stack
|
||||||
});
|
});
|
||||||
@ -336,22 +337,6 @@ module.exports = function(db) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'secure') {
|
|
||||||
// Load SSL key and certificate
|
|
||||||
var privateKey = fs.readFileSync('./config/sslcerts/key.pem', 'utf8');
|
|
||||||
var certificate = fs.readFileSync('./config/sslcerts/cert.pem', 'utf8');
|
|
||||||
|
|
||||||
// Create HTTPS Server
|
|
||||||
var httpsServer = https.createServer({
|
|
||||||
key: privateKey,
|
|
||||||
cert: certificate
|
|
||||||
}, app);
|
|
||||||
|
|
||||||
// Return HTTPS server instance
|
|
||||||
return httpsServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
app = configureSocketIO(app, db);
|
app = configureSocketIO(app, db);
|
||||||
|
|
||||||
// Return Express server instance
|
// Return Express server instance
|
||||||
|
|||||||
@ -63,7 +63,6 @@ logger.setupFileLogger = function setupFileLogger() {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,7 +75,7 @@ logger.getLogOptions = function getLogOptions() {
|
|||||||
var _config = _.clone(config, true);
|
var _config = _.clone(config, true);
|
||||||
var configFileLogger = _config.log.fileLogger;
|
var configFileLogger = _config.log.fileLogger;
|
||||||
|
|
||||||
if (!_.has(_config, 'log.fileLogger.directoryPath') || !_.has(_config, 'log.fileLogger.fileName')) {
|
if (process.env.NODE_ENV !== 'test' && !_.has(_config, 'log.fileLogger.directoryPath') || !_.has(_config, 'log.fileLogger.fileName')) {
|
||||||
console.log('unable to find logging file configuration');
|
console.log('unable to find logging file configuration');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -97,7 +96,6 @@ logger.getLogOptions = function getLogOptions() {
|
|||||||
handleExceptions: true,
|
handleExceptions: true,
|
||||||
humanReadableUnhandledException: true
|
humanReadableUnhandledException: true
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -6,14 +6,24 @@ module.exports.isAuthenticatedOrApiKey = function isAuthenticated(req, res, next
|
|||||||
if (req.isAuthenticated()) {
|
if (req.isAuthenticated()) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try authenticate with API KEY
|
// Try authenticate with API KEY
|
||||||
if (req.headers.apikey || req.query.apikey || req.body.apikey) {
|
if (req.headers.apikey || req.query.apikey || req.body.apikey) {
|
||||||
passport.authenticate('localapikey', function (err, user, info) {
|
if(!req.body.apikey && req.headers.apikey){
|
||||||
if (err)
|
req.body.apikey = req.headers.apikey;
|
||||||
return res.sendStatus(500);
|
} else if(!req.query.apikey && req.headers.apikey){
|
||||||
|
req.query.apikey = req.headers.apikey;
|
||||||
|
}
|
||||||
|
|
||||||
if (!user)
|
passport.authenticate('localapikey', function (err, user, info) {
|
||||||
|
if (err) {
|
||||||
|
return res.status(500).send('Internal Server Error with API. Sorry about that!');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
console.log('no user for apikey');
|
||||||
return res.status(401).send(info.message || '');
|
return res.status(401).send(info.message || '');
|
||||||
|
}
|
||||||
|
|
||||||
req.login(user, function(loginErr) {
|
req.login(user, function(loginErr) {
|
||||||
if (loginErr) return res.sendStatus(500);
|
if (loginErr) return res.sendStatus(500);
|
||||||
@ -28,23 +38,3 @@ module.exports.isAuthenticatedOrApiKey = function isAuthenticated(req, res, next
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports.hasRole = function hasRole(roleRequired) {
|
|
||||||
if (!roleRequired) {
|
|
||||||
throw new Error('Required role needs to be set');
|
|
||||||
}
|
|
||||||
|
|
||||||
return function(req, res, next) {
|
|
||||||
return module.exports.isAuthenticated(req, res, function() {
|
|
||||||
if (req.user && req.user.roles && req.user.roles.indexOf(roleRequired) !== -1){
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
return res.sendStatus(403);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.hasAdminRole = function hasAdminRole() {
|
|
||||||
return module.exports.hasRole('admin');
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|||||||
@ -11,13 +11,15 @@ module.exports = function() {
|
|||||||
return User.findOne({
|
return User.findOne({
|
||||||
'apiKey': apiKey
|
'apiKey': apiKey
|
||||||
}, function(err, user) {
|
}, function(err, user) {
|
||||||
if (err)
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
|
}
|
||||||
|
|
||||||
if (!user)
|
if (!user){
|
||||||
return done(null, false, {
|
return done(null, false, {
|
||||||
message: 'Unknown API Key'
|
message: 'Unknown API Key'
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return done(null, user);
|
return done(null, user);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -14,8 +14,6 @@ module.exports = function () {
|
|||||||
passwordField: 'password'
|
passwordField: 'password'
|
||||||
},
|
},
|
||||||
function (username, password, done) {
|
function (username, password, done) {
|
||||||
console.log('\n\n\n\n\nusername: '+username);
|
|
||||||
console.log('password: '+password)
|
|
||||||
User.findOne({
|
User.findOne({
|
||||||
$or: [
|
$or: [
|
||||||
{'username': username.toLowerCase()},
|
{'username': username.toLowerCase()},
|
||||||
|
|||||||
68
gruntfile.js
68
gruntfile.js
@ -204,63 +204,23 @@ module.exports = function(grunt) {
|
|||||||
singleRun: true
|
singleRun: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
protractor: {
|
|
||||||
options: {
|
|
||||||
configFile: 'protractor.conf.js',
|
|
||||||
keepAlive: true,
|
|
||||||
noColor: false
|
|
||||||
},
|
|
||||||
e2e: {
|
|
||||||
options: {
|
|
||||||
args: {} // Target-specific arguments
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mocha_istanbul: {
|
mocha_istanbul: {
|
||||||
coverage: {
|
|
||||||
src: watchFiles.allTests, // a folder works nicely
|
|
||||||
options: {
|
|
||||||
mask: '*.test.js',
|
|
||||||
require: ['server.js']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
coverageClient: {
|
|
||||||
src: watchFiles.clientTests, // specifying file patterns works as well
|
|
||||||
options: {
|
|
||||||
coverageFolder: 'coverageClient',
|
|
||||||
mask: '*.test.js',
|
|
||||||
require: ['server.js']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
coverageServer: {
|
coverageServer: {
|
||||||
src: watchFiles.serverTests,
|
src: watchFiles.serverTests,
|
||||||
options: {
|
options: {
|
||||||
coverageFolder: 'coverageServer',
|
coverageFolder: 'coverageServer',
|
||||||
mask: '*.test.js',
|
mask: '*.test.js',
|
||||||
require: ['server.js']
|
require: ['server.js'],
|
||||||
}
|
reportFormats: ['html','lcovonly']
|
||||||
},
|
|
||||||
coveralls: {
|
|
||||||
src: watchFiles.allTests, // multiple folders also works
|
|
||||||
options: {
|
|
||||||
require: ['server.js'],
|
|
||||||
coverage: true, // this will make the grunt.event.on('coverage') event listener to be triggered
|
|
||||||
root: './lib', // define where the cover task should consider the root of libraries that are covered by tests
|
|
||||||
reportFormats: ['cobertura','lcovonly']
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
istanbul_check_coverage: {
|
lcovMerge: {
|
||||||
default: {
|
options: {
|
||||||
options: {
|
emitters: ['event'],
|
||||||
coverageFolder: 'coverage*', // will check both coverage folders and merge the coverage results
|
},
|
||||||
check: {
|
src: ['./coverageServer/*.info', './coverageClient/lcov-report/*.info']
|
||||||
lines: 80,
|
},
|
||||||
statements: 80
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
html2js: {
|
html2js: {
|
||||||
options: {
|
options: {
|
||||||
base: 'public',
|
base: 'public',
|
||||||
@ -287,7 +247,7 @@ module.exports = function(grunt) {
|
|||||||
options: {
|
options: {
|
||||||
module: 'TellForm.templates'
|
module: 'TellForm.templates'
|
||||||
},
|
},
|
||||||
src: ['public/modules/**/views/**.html', 'public/modules/**/views/**/*.html', 'public/form_modules/forms/base/**/*.html', '!public/modules/forms/base/**/*.html'],
|
src: ['public/modules/**/views/**.html', 'public/modules/**/views/**/*.html', 'public/form_modules/forms/base/**/*.html'],
|
||||||
dest: 'public/dist/populate_template_cache.js'
|
dest: 'public/dist/populate_template_cache.js'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -323,9 +283,7 @@ module.exports = function(grunt) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Code coverage tasks.
|
// Code coverage tasks.
|
||||||
grunt.registerTask('coveralls', ['env:test','mocha_istanbul:coveralls']);
|
grunt.registerTask('coveralls', ['test:client', 'karma:unit', 'mocha_istanbul:coverageServer', 'lcovMerge']);
|
||||||
grunt.registerTask('coverage', ['env:test', 'mocha_istanbul:coverage']);
|
|
||||||
grunt.registerTask('coverage:client', ['env:test', 'mocha_istanbul:coverageClient']);
|
|
||||||
grunt.registerTask('coverage:server', ['env:test', 'mocha_istanbul:coverageServer']);
|
grunt.registerTask('coverage:server', ['env:test', 'mocha_istanbul:coverageServer']);
|
||||||
|
|
||||||
// Default task(s).
|
// Default task(s).
|
||||||
@ -339,7 +297,7 @@ module.exports = function(grunt) {
|
|||||||
grunt.registerTask('secure', ['env:secure', 'lint', 'html2js:main', 'html2js:forms', 'concurrent:default']);
|
grunt.registerTask('secure', ['env:secure', 'lint', 'html2js:main', 'html2js:forms', 'concurrent:default']);
|
||||||
|
|
||||||
// Lint task(s).
|
// Lint task(s).
|
||||||
grunt.registerTask('lint', ['jshint', 'csslint', 'i18nlint:client', 'i18nlint:server']);
|
grunt.registerTask('lint', ['jshint', 'csslint']);
|
||||||
grunt.registerTask('lint:tests', ['jshint:allTests']);
|
grunt.registerTask('lint:tests', ['jshint:allTests']);
|
||||||
|
|
||||||
// Build task(s).
|
// Build task(s).
|
||||||
@ -349,9 +307,11 @@ module.exports = function(grunt) {
|
|||||||
grunt.registerTask('setup', ['execute']);
|
grunt.registerTask('setup', ['execute']);
|
||||||
|
|
||||||
// Test task(s).
|
// Test task(s).
|
||||||
grunt.registerTask('test', ['lint:tests', 'test:server', 'test:client']);
|
grunt.registerTask('test', ['test:server', 'test:client']);
|
||||||
grunt.registerTask('test:server', ['lint:tests', 'env:test', 'mochaTest']);
|
grunt.registerTask('test:server', ['lint:tests', 'env:test', 'mochaTest']);
|
||||||
grunt.registerTask('test:client', ['lint:tests', 'html2js:main', 'html2js:forms', 'env:test', 'karma:unit']);
|
grunt.registerTask('test:client', ['lint:tests', 'html2js:main', 'html2js:forms', 'env:test', 'karma:unit']);
|
||||||
|
grunt.registerTask('test:travis', ['coverage:server', 'test:client', 'lcovMerge']);
|
||||||
|
|
||||||
|
|
||||||
grunt.registerTask('testdebug', ['env:test', 'karma:debug']);
|
grunt.registerTask('testdebug', ['env:test', 'karma:debug']);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -29,11 +29,20 @@ module.exports = function(config) {
|
|||||||
'public/modules/**/views/**/*.html': ['ng-html2js'],
|
'public/modules/**/views/**/*.html': ['ng-html2js'],
|
||||||
'public/modules/**/views/*.html': ['ng-html2js'],
|
'public/modules/**/views/*.html': ['ng-html2js'],
|
||||||
'public/form_modules/forms/base/views/**/*.html': ['ng-html2js'],
|
'public/form_modules/forms/base/views/**/*.html': ['ng-html2js'],
|
||||||
'public/form_modules/forms/base/views/*.html': ['ng-html2js']
|
'public/form_modules/forms/base/views/*.html': ['ng-html2js'],
|
||||||
//'public/modules/*/*.js': ['coverage'],
|
'public/modules/*/*.js': ['coverage'],
|
||||||
//'public/modules/*/*[!tests]*/*.js': ['coverage'],
|
'public/modules/*/*[!tests]*/*.js': ['coverage']
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// configure coverage reporter
|
||||||
|
coverageReporter: {
|
||||||
|
reporters: [
|
||||||
|
{ type: 'html', subdir: 'report-html' },
|
||||||
|
{ type: 'lcov', subdir: 'report-lcov' },
|
||||||
|
],
|
||||||
|
dir : 'coverageClient/'
|
||||||
|
},
|
||||||
|
|
||||||
ngHtml2JsPreprocessor: {
|
ngHtml2JsPreprocessor: {
|
||||||
stripPrefix: 'public/',
|
stripPrefix: 'public/',
|
||||||
prependPrefix: 'static/',
|
prependPrefix: 'static/',
|
||||||
|
|||||||
10
package.json
10
package.json
@ -21,12 +21,13 @@
|
|||||||
"generate": "all-contributors generate",
|
"generate": "all-contributors generate",
|
||||||
"start": "grunt",
|
"start": "grunt",
|
||||||
"test": "grunt test",
|
"test": "grunt test",
|
||||||
|
"travis": "grunt test:travis",
|
||||||
"postinstall": "bower install --config.interactive=false; grunt build;",
|
"postinstall": "bower install --config.interactive=false; grunt build;",
|
||||||
"init": "node scripts/setup.js"
|
"init": "node scripts/setup.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "^1.4.2",
|
"async": "^1.4.2",
|
||||||
"bcrypt": "^0.8.7",
|
"bcrypt": "~1.0.3",
|
||||||
"body-parser": "~1.14.1",
|
"body-parser": "~1.14.1",
|
||||||
"bower": "~1.6.5",
|
"bower": "~1.6.5",
|
||||||
"chalk": "^1.1.3",
|
"chalk": "^1.1.3",
|
||||||
@ -72,7 +73,6 @@
|
|||||||
"request": "^2.83.0",
|
"request": "^2.83.0",
|
||||||
"socket.io": "^1.4.6",
|
"socket.io": "^1.4.6",
|
||||||
"socket.io-redis": "^1.0.0",
|
"socket.io-redis": "^1.0.0",
|
||||||
"swig": "~1.4.1",
|
|
||||||
"uuid-token-generator": "^0.5.0",
|
"uuid-token-generator": "^0.5.0",
|
||||||
"wildcard-subdomains": "github:tellform/wildcard-subdomains",
|
"wildcard-subdomains": "github:tellform/wildcard-subdomains",
|
||||||
"winston": "^2.3.1",
|
"winston": "^2.3.1",
|
||||||
@ -91,8 +91,8 @@
|
|||||||
"grunt-contrib-uglify": "^0.11.1",
|
"grunt-contrib-uglify": "^0.11.1",
|
||||||
"grunt-contrib-watch": "~0.6.1",
|
"grunt-contrib-watch": "~0.6.1",
|
||||||
"grunt-execute": "^0.2.2",
|
"grunt-execute": "^0.2.2",
|
||||||
"grunt-i18nlint": "github:jwarby/grunt-i18nlint",
|
|
||||||
"grunt-karma": "~0.12.1",
|
"grunt-karma": "~0.12.1",
|
||||||
|
"grunt-lcov-merge": "^1.2.3",
|
||||||
"grunt-mocha-istanbul": "^3.0.1",
|
"grunt-mocha-istanbul": "^3.0.1",
|
||||||
"grunt-mocha-test": "~0.12.1",
|
"grunt-mocha-test": "~0.12.1",
|
||||||
"grunt-newer": "~1.1.1",
|
"grunt-newer": "~1.1.1",
|
||||||
@ -100,7 +100,7 @@
|
|||||||
"grunt-usemin": "^3.1.1",
|
"grunt-usemin": "^3.1.1",
|
||||||
"grunt-wiredep": "^3.0.1",
|
"grunt-wiredep": "^3.0.1",
|
||||||
"istanbul": "^0.4.0",
|
"istanbul": "^0.4.0",
|
||||||
"jasmine-core": "^2.4.1",
|
"jasmine-core": "^2.6",
|
||||||
"karma": "~0.13.14",
|
"karma": "~0.13.14",
|
||||||
"karma-chrome-launcher": "~0.2.1",
|
"karma-chrome-launcher": "~0.2.1",
|
||||||
"karma-coverage": "~0.5.3",
|
"karma-coverage": "~0.5.3",
|
||||||
@ -113,7 +113,7 @@
|
|||||||
"mocha": "^3.1.2",
|
"mocha": "^3.1.2",
|
||||||
"mocha-lcov-reporter": "^1.0.0",
|
"mocha-lcov-reporter": "^1.0.0",
|
||||||
"nightwatch": "^0.9.8",
|
"nightwatch": "^0.9.8",
|
||||||
"phantomjs": "^1.9.18",
|
"phantomjs-prebuilt": "^2.1.15",
|
||||||
"selenium-server": "^3.0.1",
|
"selenium-server": "^3.0.1",
|
||||||
"should": "~7.1.1",
|
"should": "~7.1.1",
|
||||||
"supertest": "~1.2.0",
|
"supertest": "~1.2.0",
|
||||||
|
|||||||
4456
public/dist/application.js
vendored
4456
public/dist/application.js
vendored
File diff suppressed because one or more lines are too long
4
public/dist/application.min.css
vendored
4
public/dist/application.min.css
vendored
File diff suppressed because one or more lines are too long
7
public/dist/application.min.js
vendored
7
public/dist/application.min.js
vendored
File diff suppressed because one or more lines are too long
30
public/dist/vendor.min.js
vendored
30
public/dist/vendor.min.js
vendored
File diff suppressed because one or more lines are too long
@ -6,9 +6,38 @@
|
|||||||
var scope,
|
var scope,
|
||||||
HeaderController;
|
HeaderController;
|
||||||
|
|
||||||
|
var sampleUser = {
|
||||||
|
firstName: 'Full',
|
||||||
|
lastName: 'Name',
|
||||||
|
email: 'test@test.com',
|
||||||
|
username: 'test@test.com',
|
||||||
|
language: 'en',
|
||||||
|
password: 'password',
|
||||||
|
provider: 'local',
|
||||||
|
roles: ['user'],
|
||||||
|
_id: 'ed873933b1f1dea0ce12fab9'
|
||||||
|
};
|
||||||
|
|
||||||
// Load the main application module
|
// Load the main application module
|
||||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||||
|
|
||||||
|
//Mock Authentication Service
|
||||||
|
beforeEach(module(function($provide) {
|
||||||
|
$provide.service('Auth', function() {
|
||||||
|
return {
|
||||||
|
ensureHasCurrentUser: function() {
|
||||||
|
return sampleUser;
|
||||||
|
},
|
||||||
|
isAuthenticated: function() {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
getUserState: function() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
beforeEach(inject(function($controller, $rootScope) {
|
beforeEach(inject(function($controller, $rootScope) {
|
||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
|
|
||||||
|
|||||||
@ -161,7 +161,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
|
|||||||
MULTIPLE_CHOICE: 'Multiple Choice',
|
MULTIPLE_CHOICE: 'Multiple Choice',
|
||||||
DROPDOWN: 'Dropdown',
|
DROPDOWN: 'Dropdown',
|
||||||
DATE: 'Date',
|
DATE: 'Date',
|
||||||
PARAGRAPH_T: 'Paragraph',
|
PARAGRAPH_FIELD: 'Paragraph',
|
||||||
YES_NO: 'Yes/No',
|
YES_NO: 'Yes/No',
|
||||||
LEGAL: 'Legal',
|
LEGAL: 'Legal',
|
||||||
RATING: 'Rating',
|
RATING: 'Rating',
|
||||||
|
|||||||
@ -157,7 +157,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
|
|||||||
MULTIPLE_CHOICE: 'Choix multiple',
|
MULTIPLE_CHOICE: 'Choix multiple',
|
||||||
DROPDOWN: 'Menu Déroulant',
|
DROPDOWN: 'Menu Déroulant',
|
||||||
DATE: 'Date',
|
DATE: 'Date',
|
||||||
PARAGRAPH_T: "Paragraphe",
|
PARAGRAPH_FIELD: "Paragraphe",
|
||||||
OUI_NON: 'Oui / Non',
|
OUI_NON: 'Oui / Non',
|
||||||
LEGAL: 'Légal',
|
LEGAL: 'Légal',
|
||||||
RATING: "Évaluation",
|
RATING: "Évaluation",
|
||||||
|
|||||||
@ -89,7 +89,6 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
|
|||||||
ADD_OPTION: 'Option hinzufügen',
|
ADD_OPTION: 'Option hinzufügen',
|
||||||
NUM_OF_STEPS: 'Anzahl der Schritte',
|
NUM_OF_STEPS: 'Anzahl der Schritte',
|
||||||
CLICK_FIELDS_FOOTER: 'Klicken Sie auf Felder, um sie hier hinzuzufügen',
|
CLICK_FIELDS_FOOTER: 'Klicken Sie auf Felder, um sie hier hinzuzufügen',
|
||||||
FORM: 'Formular',
|
|
||||||
IF_THIS_FIELD: 'Wenn dieses Feld',
|
IF_THIS_FIELD: 'Wenn dieses Feld',
|
||||||
IS_EQUAL_TO: 'ist gleich',
|
IS_EQUAL_TO: 'ist gleich',
|
||||||
IS_NOT_EQUAL_TO: 'ist nicht gleich',
|
IS_NOT_EQUAL_TO: 'ist nicht gleich',
|
||||||
@ -157,7 +156,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
|
|||||||
MULTIPLE_CHOICE: 'Mehrfachauswahl',
|
MULTIPLE_CHOICE: 'Mehrfachauswahl',
|
||||||
DROPDOWN: 'Dropdown-Liste',
|
DROPDOWN: 'Dropdown-Liste',
|
||||||
DATE: 'Datum',
|
DATE: 'Datum',
|
||||||
PARAGRAPH_T: "Absatz",
|
PARAGRAPH_FIELD: "Absatz",
|
||||||
YES_NO: 'Ja / Nein',
|
YES_NO: 'Ja / Nein',
|
||||||
LEGAL: "Rechtliche",
|
LEGAL: "Rechtliche",
|
||||||
RATING: 'Bewertung',
|
RATING: 'Bewertung',
|
||||||
|
|||||||
@ -157,7 +157,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
|
|||||||
MULTIPLE_CHOICE: 'Scelta multipla',
|
MULTIPLE_CHOICE: 'Scelta multipla',
|
||||||
DROPDOWN: 'Dropdown',
|
DROPDOWN: 'Dropdown',
|
||||||
DATE: 'Data',
|
DATE: 'Data',
|
||||||
PARAGRAPH_T: 'Paragrafo',
|
PARAGRAPH_FIELD: 'Paragrafo',
|
||||||
YES_NO: 'Sì / no',
|
YES_NO: 'Sì / no',
|
||||||
LEGAL: 'Legale',
|
LEGAL: 'Legale',
|
||||||
RATING: 'Valutazione',
|
RATING: 'Valutazione',
|
||||||
|
|||||||
@ -158,7 +158,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
|
|||||||
MULTIPLE_CHOICE: 'Opciones múltiples',
|
MULTIPLE_CHOICE: 'Opciones múltiples',
|
||||||
DROPDOWN: 'Desplegable',
|
DROPDOWN: 'Desplegable',
|
||||||
DATE: 'Fecha',
|
DATE: 'Fecha',
|
||||||
PARAGRAPH_T: 'Párrafo',
|
PARAGRAPH_FIELD: 'Párrafo',
|
||||||
YES_NO: 'Si/No',
|
YES_NO: 'Si/No',
|
||||||
LEGAL: 'Legal',
|
LEGAL: 'Legal',
|
||||||
RATING: 'Puntaje',
|
RATING: 'Puntaje',
|
||||||
|
|||||||
@ -10,13 +10,33 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
|||||||
myform: '='
|
myform: '='
|
||||||
},
|
},
|
||||||
controller: function($scope){
|
controller: function($scope){
|
||||||
|
|
||||||
$scope.table = {
|
$scope.table = {
|
||||||
masterChecker: false,
|
masterChecker: false,
|
||||||
rows: []
|
rows: []
|
||||||
};
|
};
|
||||||
|
|
||||||
var getSubmissions = function(){
|
$scope.deletionInProgress = false;
|
||||||
|
$scope.waitingForDeletion = false;
|
||||||
|
|
||||||
|
//Waits until deletionInProgress is false before running getSubmissions
|
||||||
|
$scope.$watch("deletionInProgress",function(newVal, oldVal){
|
||||||
|
if(newVal === oldVal) return;
|
||||||
|
|
||||||
|
if(newVal === false && $scope.waitingForDeletion) {
|
||||||
|
$scope.getSubmissions();
|
||||||
|
$scope.waitingForDeletion = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.handleSubmissionsRefresh = function(){
|
||||||
|
if(!$scope.deletionInProgress) {
|
||||||
|
$scope.getSubmissions();
|
||||||
|
} else {
|
||||||
|
$scope.waitingForDeletion = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.getSubmissions = function(cb){
|
||||||
$http({
|
$http({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/forms/'+$scope.myform._id+'/submissions'
|
url: '/forms/'+$scope.myform._id+'/submissions'
|
||||||
@ -36,10 +56,19 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
|||||||
}
|
}
|
||||||
|
|
||||||
$scope.table.rows = submissions;
|
$scope.table.rows = submissions;
|
||||||
});
|
|
||||||
|
if(cb && typeof cb === 'function'){
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
}, function errorCallback(err){
|
||||||
|
console.error(err);
|
||||||
|
if(cb && typeof cb === 'function'){
|
||||||
|
cb(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var getVisitors = function(){
|
$scope.getVisitors = function(){
|
||||||
$http({
|
$http({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/forms/'+$scope.myform._id+'/visitors'
|
url: '/forms/'+$scope.myform._id+'/visitors'
|
||||||
@ -52,8 +81,23 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
getSubmissions();
|
$scope.handleSubmissionsRefresh();
|
||||||
getVisitors();
|
$scope.getVisitors();
|
||||||
|
|
||||||
|
//Fetch submissions and visitor data every 1.67 min
|
||||||
|
var updateSubmissions = $interval($scope.handleSubmissionsRefresh, 100000);
|
||||||
|
var updateVisitors = $interval($scope.getVisitors, 1000000);
|
||||||
|
|
||||||
|
//Prevent $intervals from running after directive is destroyed
|
||||||
|
$scope.$on('$destroy', function() {
|
||||||
|
if (updateSubmissions) {
|
||||||
|
$interval.cancel($scope.updateSubmissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateVisitors) {
|
||||||
|
$interval.cancel($scope.updateVisitors);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Analytics Functions
|
** Analytics Functions
|
||||||
@ -72,14 +116,48 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
|||||||
return (totalTime/numSubmissions).toFixed(0);
|
return (totalTime/numSubmissions).toFixed(0);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
var updateFields = $interval(getSubmissions, 100000);
|
$scope.DeviceStatistics = (function(){
|
||||||
var updateFields = $interval(getVisitors, 1000000);
|
var newStatItem = function(){
|
||||||
|
return {
|
||||||
|
visits: 0,
|
||||||
|
responses: 0,
|
||||||
|
completion: 0,
|
||||||
|
average_time: 0,
|
||||||
|
total_time: 0
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
$scope.$on('$destroy', function() {
|
var stats = {
|
||||||
if (updateFields) {
|
desktop: newStatItem(),
|
||||||
$interval.cancel($scope.updateFields);
|
tablet: newStatItem(),
|
||||||
|
phone: newStatItem(),
|
||||||
|
other: newStatItem()
|
||||||
|
};
|
||||||
|
|
||||||
|
if($scope.myform.analytics && $scope.myform.analytics.visitors) {
|
||||||
|
var visitors = $scope.myform.analytics.visitors;
|
||||||
|
for (var i = 0; i < visitors.length; i++) {
|
||||||
|
var visitor = visitors[i];
|
||||||
|
var deviceType = visitor.deviceType;
|
||||||
|
|
||||||
|
stats[deviceType].visits++;
|
||||||
|
|
||||||
|
if (visitor.isSubmitted) {
|
||||||
|
stats[deviceType].total_time = stats[deviceType].total_time + visitor.timeElapsed;
|
||||||
|
stats[deviceType].responses++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stats[deviceType].visits) {
|
||||||
|
stats[deviceType].completion = 100*(stats[deviceType].responses / stats[deviceType].visits).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stats[deviceType].responses){
|
||||||
|
stats[deviceType].average_time = (stats[deviceType].total_time / stats[deviceType].responses).toFixed(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
return stats;
|
||||||
|
})();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Table Functions
|
** Table Functions
|
||||||
@ -109,25 +187,24 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
|||||||
//Delete selected submissions of Form
|
//Delete selected submissions of Form
|
||||||
$scope.deleteSelectedSubmissions = function(){
|
$scope.deleteSelectedSubmissions = function(){
|
||||||
|
|
||||||
|
$scope.deletionInProgress = true;
|
||||||
var delete_ids = _.chain($scope.table.rows).filter(function(row){
|
var delete_ids = _.chain($scope.table.rows).filter(function(row){
|
||||||
return !!row.selected;
|
return !!row.selected;
|
||||||
}).pluck('_id').value();
|
}).pluck('_id').value();
|
||||||
|
|
||||||
$http({ url: '/forms/'+$scope.myform._id+'/submissions',
|
return $http({ url: '/forms/'+$scope.myform._id+'/submissions',
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
data: {deleted_submissions: delete_ids},
|
data: {deleted_submissions: delete_ids},
|
||||||
headers: {'Content-Type': 'application/json;charset=utf-8'}
|
headers: {'Content-Type': 'application/json;charset=utf-8'}
|
||||||
}).success(function(data, status){
|
}).success(function(data, status){
|
||||||
|
$scope.deletionInProgress = true;
|
||||||
//Remove deleted ids from table
|
//Remove deleted ids from table
|
||||||
var tmpArray = [];
|
$scope.table.rows = $scope.table.rows.filter(function(field){
|
||||||
for(var i=0; i<$scope.table.rows.length; i++){
|
return !field.selected;
|
||||||
if(!$scope.table.rows[i].selected){
|
});
|
||||||
tmpArray.push($scope.table.rows[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$scope.table.rows = tmpArray;
|
|
||||||
})
|
})
|
||||||
.error(function(err){
|
.error(function(err){
|
||||||
|
$scope.deletionInProgress = true;
|
||||||
console.error(err);
|
console.error(err);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -28,7 +28,7 @@ angular.module('forms').service('FormFields', [ '$rootScope', '$translate', '$wi
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'textarea',
|
name : 'textarea',
|
||||||
value : $translate.instant('PARAGRAPH'),
|
value : $translate.instant('PARAGRAPH_FIELD'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'yes_no',
|
name : 'yes_no',
|
||||||
|
|||||||
@ -57,22 +57,7 @@
|
|||||||
_id: '525a8422f6d0f87f0e407a33'
|
_id: '525a8422f6d0f87f0e407a33'
|
||||||
};
|
};
|
||||||
|
|
||||||
var newFakeModal = function(){
|
//Mock myForm Service
|
||||||
var result = {
|
|
||||||
opened: true,
|
|
||||||
close: function( item ) {
|
|
||||||
//The user clicked OK on the modal dialog, call the stored confirm callback with the selected item
|
|
||||||
this.opened = false;
|
|
||||||
},
|
|
||||||
dismiss: function( type ) {
|
|
||||||
//The user clicked cancel on the modal dialog, call the stored cancel callback
|
|
||||||
this.opened = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
//Mock Users Service
|
|
||||||
beforeEach(module(function($provide) {
|
beforeEach(module(function($provide) {
|
||||||
$provide.service('myForm', function($q) {
|
$provide.service('myForm', function($q) {
|
||||||
return sampleForm;
|
return sampleForm;
|
||||||
@ -159,6 +144,27 @@
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
var newFakeModal = function(){
|
||||||
|
var modal = {
|
||||||
|
opened: true,
|
||||||
|
close: function( item ) {
|
||||||
|
//The user clicked OK on the modal dialog, call the stored confirm callback with the selected item
|
||||||
|
this.opened = false;
|
||||||
|
},
|
||||||
|
dismiss: function( type ) {
|
||||||
|
//The user clicked cancel on the modal dialog, call the stored cancel callback
|
||||||
|
this.opened = false;
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
then: function (cb) {
|
||||||
|
if(cb && typeof cb === 'function'){
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return modal;
|
||||||
|
};
|
||||||
|
|
||||||
//Mock $uibModal
|
//Mock $uibModal
|
||||||
beforeEach(inject(function($uibModal) {
|
beforeEach(inject(function($uibModal) {
|
||||||
@ -199,7 +205,7 @@
|
|||||||
expect(scope.myform).toEqualData(sampleForm);
|
expect(scope.myform).toEqualData(sampleForm);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('$scope.removeCurrentForm() with valid form data should send a DELETE request with the id of form', function() {
|
it('$scope.removeCurrentForm() with valid form data should send a DELETE request with the id of form', inject(function($uibModal) {
|
||||||
var controller = createAdminFormController();
|
var controller = createAdminFormController();
|
||||||
|
|
||||||
//Set $state transition
|
//Set $state transition
|
||||||
@ -214,7 +220,7 @@
|
|||||||
|
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
$state.ensureAllTransitionsHappened();
|
$state.ensureAllTransitionsHappened();
|
||||||
});
|
}));
|
||||||
|
|
||||||
it('$scope.update() should send a PUT request with the id of form', function() {
|
it('$scope.update() should send a PUT request with the id of form', function() {
|
||||||
var controller = createAdminFormController();
|
var controller = createAdminFormController();
|
||||||
|
|||||||
@ -86,7 +86,6 @@
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
// The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
|
// The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
|
||||||
// This allows us to inject a service but then attach it to a variable
|
// This allows us to inject a service but then attach it to a variable
|
||||||
// with the same name as the service.
|
// with the same name as the service.
|
||||||
@ -106,25 +105,13 @@
|
|||||||
|
|
||||||
// Initialize the Forms controller.
|
// Initialize the Forms controller.
|
||||||
createListFormsController = function(){
|
createListFormsController = function(){
|
||||||
return $controller('ListFormsController', { $scope: scope });
|
return $controller('ListFormsController', {
|
||||||
|
$scope: scope,
|
||||||
|
myForms: sampleFormList
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('$scope.findAll() should query all User\'s Forms', inject(function() {
|
|
||||||
|
|
||||||
var controller = createListFormsController();
|
|
||||||
|
|
||||||
// Set GET response
|
|
||||||
$httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList);
|
|
||||||
|
|
||||||
// Run controller functionality
|
|
||||||
scope.findAll();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
// Test scope value
|
|
||||||
expect( scope.myforms ).toEqualData(sampleFormList);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('$scope.duplicateForm() should duplicate a Form', inject(function() {
|
it('$scope.duplicateForm() should duplicate a Form', inject(function() {
|
||||||
|
|
||||||
var dupSampleForm = sampleFormList[2],
|
var dupSampleForm = sampleFormList[2],
|
||||||
@ -135,12 +122,6 @@
|
|||||||
|
|
||||||
var controller = createListFormsController();
|
var controller = createListFormsController();
|
||||||
|
|
||||||
// Set GET response
|
|
||||||
$httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList);
|
|
||||||
// Run controller functionality
|
|
||||||
scope.findAll();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
// Set GET response
|
// Set GET response
|
||||||
$httpBackend.expect('POST', '/forms').respond(200, dupSampleForm);
|
$httpBackend.expect('POST', '/forms').respond(200, dupSampleForm);
|
||||||
// Run controller functionality
|
// Run controller functionality
|
||||||
@ -164,13 +145,6 @@
|
|||||||
|
|
||||||
var controller = createListFormsController();
|
var controller = createListFormsController();
|
||||||
|
|
||||||
// Set GET response
|
|
||||||
$httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList);
|
|
||||||
|
|
||||||
// Run controller functionality
|
|
||||||
scope.findAll();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
// Set GET response
|
// Set GET response
|
||||||
$httpBackend.expect('DELETE', /^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, delSampleForm);
|
$httpBackend.expect('DELETE', /^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, delSampleForm);
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
// Forms Controller Spec
|
// Forms Controller Spec
|
||||||
describe('EditSubmissions Directive-Controller Tests', function() {
|
describe('EditFormSubmissions Directive-Controller Tests', function() {
|
||||||
// Initialize global variables
|
// Initialize global variables
|
||||||
var el, scope, controller, $httpBackend;
|
var el, scope, controller, $httpBackend;
|
||||||
|
|
||||||
@ -10,13 +10,25 @@
|
|||||||
firstName: 'Full',
|
firstName: 'Full',
|
||||||
lastName: 'Name',
|
lastName: 'Name',
|
||||||
email: 'test@test.com',
|
email: 'test@test.com',
|
||||||
username: 'test@test.com',
|
username: 'test1234',
|
||||||
password: 'password',
|
password: 'password',
|
||||||
provider: 'local',
|
provider: 'local',
|
||||||
roles: ['user'],
|
roles: ['user'],
|
||||||
_id: 'ed873933b1f1dea0ce12fab9'
|
_id: 'ed873933b1f1dea0ce12fab9'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var sampleVisitors = [{
|
||||||
|
socketId: '33b1f1dea0ce12fab9ed8739',
|
||||||
|
referrer: 'https://tellform.com/examples',
|
||||||
|
lastActiveField: 'ed873933b0ce121f1deafab9',
|
||||||
|
timeElapsed: 100000,
|
||||||
|
isSubmitted: true,
|
||||||
|
language: 'en',
|
||||||
|
ipAddr: '192.168.1.1',
|
||||||
|
deviceType: 'desktop',
|
||||||
|
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4'
|
||||||
|
}]
|
||||||
|
|
||||||
var sampleForm = {
|
var sampleForm = {
|
||||||
title: 'Form Title',
|
title: 'Form Title',
|
||||||
admin: 'ed873933b1f1dea0ce12fab9',
|
admin: 'ed873933b1f1dea0ce12fab9',
|
||||||
@ -27,7 +39,18 @@
|
|||||||
{fieldType:'checkbox', title:'hockey', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed8317393deab0ce121ffab9'}
|
{fieldType:'checkbox', title:'hockey', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed8317393deab0ce121ffab9'}
|
||||||
],
|
],
|
||||||
analytics: {
|
analytics: {
|
||||||
visitors: []
|
visitors: sampleVisitors,
|
||||||
|
conversionRate: 80.5,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
dropoffViews: 0,
|
||||||
|
responses: 1,
|
||||||
|
totalViews: 1,
|
||||||
|
continueRate: 100,
|
||||||
|
dropoffRate: 0,
|
||||||
|
field: {fieldType:'textfield', title:'First Name', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed873933b0ce121f1deafab9'}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
submissions: [],
|
submissions: [],
|
||||||
startPage: {
|
startPage: {
|
||||||
@ -61,7 +84,8 @@
|
|||||||
],
|
],
|
||||||
admin: sampleUser,
|
admin: sampleUser,
|
||||||
form: sampleForm,
|
form: sampleForm,
|
||||||
timeElapsed: 10.33
|
timeElapsed: 10.33,
|
||||||
|
selected: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
form_fields: [
|
form_fields: [
|
||||||
@ -71,7 +95,8 @@
|
|||||||
],
|
],
|
||||||
admin: sampleUser,
|
admin: sampleUser,
|
||||||
form: sampleForm,
|
form: sampleForm,
|
||||||
timeElapsed: 2.33
|
timeElapsed: 2.33,
|
||||||
|
selected: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
form_fields: [
|
form_fields: [
|
||||||
@ -81,7 +106,8 @@
|
|||||||
],
|
],
|
||||||
admin: sampleUser,
|
admin: sampleUser,
|
||||||
form: sampleForm,
|
form: sampleForm,
|
||||||
timeElapsed: 11.11
|
timeElapsed: 11.11,
|
||||||
|
selected: false
|
||||||
}];
|
}];
|
||||||
|
|
||||||
// The $resource service augments the response object with methods for updating and deleting the resource.
|
// The $resource service augments the response object with methods for updating and deleting the resource.
|
||||||
@ -118,10 +144,12 @@
|
|||||||
$httpBackend.whenGET(/^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm);
|
$httpBackend.whenGET(/^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm);
|
||||||
$httpBackend.whenGET('/forms').respond(200, sampleForm);
|
$httpBackend.whenGET('/forms').respond(200, sampleForm);
|
||||||
$httpBackend.whenGET(/^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm);
|
$httpBackend.whenGET(/^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm);
|
||||||
//Instantiate directive.
|
$httpBackend.whenGET(/^(\/forms\/)([0-9a-fA-F]{24})\/submissions$/).respond(200, sampleSubmissions);
|
||||||
|
$httpBackend.whenGET(/^(\/forms\/)([0-9a-fA-F]{24})\/visitors$/).respond(200, sampleVisitors);
|
||||||
|
|
||||||
|
//Instantiate directive.
|
||||||
var tmp_scope = $rootScope.$new();
|
var tmp_scope = $rootScope.$new();
|
||||||
tmp_scope.myform = sampleForm;
|
tmp_scope.myform = sampleForm;
|
||||||
tmp_scope.myform.submissions = sampleSubmissions;
|
|
||||||
tmp_scope.user = sampleUser;
|
tmp_scope.user = sampleUser;
|
||||||
|
|
||||||
//gotacha: Controller and link functions will execute.
|
//gotacha: Controller and link functions will execute.
|
||||||
@ -141,6 +169,7 @@
|
|||||||
|
|
||||||
it('$scope.toggleAllCheckers should toggle all checkboxes in table', function(){
|
it('$scope.toggleAllCheckers should toggle all checkboxes in table', function(){
|
||||||
//Run Controller Logic to Test
|
//Run Controller Logic to Test
|
||||||
|
scope.table.rows = sampleSubmissions;
|
||||||
scope.table.masterChecker = true;
|
scope.table.masterChecker = true;
|
||||||
scope.toggleAllCheckers();
|
scope.toggleAllCheckers();
|
||||||
|
|
||||||
@ -151,6 +180,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('$scope.isAtLeastOneChecked should return true when at least one checkbox is selected', function(){
|
it('$scope.isAtLeastOneChecked should return true when at least one checkbox is selected', function(){
|
||||||
|
scope.table.rows = sampleSubmissions;
|
||||||
scope.table.masterChecker = true;
|
scope.table.masterChecker = true;
|
||||||
scope.toggleAllCheckers();
|
scope.toggleAllCheckers();
|
||||||
|
|
||||||
@ -161,16 +191,22 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('$scope.deleteSelectedSubmissions should delete all submissions that are selected', function(){
|
it('$scope.deleteSelectedSubmissions should delete all submissions that are selected', function(){
|
||||||
|
$httpBackend.expect('GET', /^(\/forms\/)([0-9a-fA-F]{24})(\/submissions)$/).respond(200, sampleSubmissions);
|
||||||
scope.table.masterChecker = true;
|
scope.table.masterChecker = true;
|
||||||
scope.toggleAllCheckers();
|
scope.getSubmissions(function(err){
|
||||||
|
scope.toggleAllCheckers();
|
||||||
|
|
||||||
$httpBackend.expect('DELETE', /^(\/forms\/)([0-9a-fA-F]{24})(\/submissions)$/).respond(200);
|
$httpBackend.expect('DELETE', /^(\/forms\/)([0-9a-fA-F]{24})(\/submissions)$/).respond(200);
|
||||||
|
|
||||||
//Run Controller Logic to Test
|
//Run Controller Logic to Test
|
||||||
scope.deleteSelectedSubmissions();
|
scope.deleteSelectedSubmissions().then(function(){
|
||||||
|
expect(scope.table.rows.length).toEqual(0);
|
||||||
|
});
|
||||||
|
expect(err).not.toBeDefined();
|
||||||
|
|
||||||
|
});
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
expect(scope.table.rows.length).toEqual(0);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -62,6 +62,52 @@
|
|||||||
beforeEach(module('module-templates'));
|
beforeEach(module('module-templates'));
|
||||||
beforeEach(module('stateMock'));
|
beforeEach(module('stateMock'));
|
||||||
|
|
||||||
|
//Mock FormFields Service
|
||||||
|
beforeEach(module(function($provide) {
|
||||||
|
$provide.service('FormFields', function() {
|
||||||
|
return {
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
name : 'textfield',
|
||||||
|
value : 'Short Text'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'email',
|
||||||
|
value : 'Email'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
var newFakeModal = function(){
|
||||||
|
var modal = {
|
||||||
|
opened: true,
|
||||||
|
close: function( item ) {
|
||||||
|
//The user clicked OK on the modal dialog, call the stored confirm callback with the selected item
|
||||||
|
this.opened = false;
|
||||||
|
},
|
||||||
|
dismiss: function( type ) {
|
||||||
|
//The user clicked cancel on the modal dialog, call the stored cancel callback
|
||||||
|
this.opened = false;
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
then: function (cb) {
|
||||||
|
if(cb && typeof cb === 'function'){
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return modal;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Mock $uibModal
|
||||||
|
beforeEach(inject(function($uibModal) {
|
||||||
|
var modal = newFakeModal();
|
||||||
|
spyOn($uibModal, 'open').and.returnValue(modal);
|
||||||
|
}));
|
||||||
|
|
||||||
beforeEach(inject(function($compile, $controller, $rootScope, _$httpBackend_) {
|
beforeEach(inject(function($compile, $controller, $rootScope, _$httpBackend_) {
|
||||||
//Instantiate directive.
|
//Instantiate directive.
|
||||||
var tmp_scope = $rootScope.$new();
|
var tmp_scope = $rootScope.$new();
|
||||||
@ -97,26 +143,12 @@
|
|||||||
scope.myform = _.cloneDeep(sampleForm);
|
scope.myform = _.cloneDeep(sampleForm);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('$scope.addNewField() should ADD a new field to $scope.myform.form_fields', function() {
|
it('$scope.addNewField() should open the new field modal', function() {
|
||||||
|
|
||||||
//Run controller methods
|
//Run controller methods
|
||||||
scope.addNewField(true, 'textfield');
|
scope.addNewField('textfield');
|
||||||
|
|
||||||
var expectedFormField = {
|
expect(scope.editFieldModal.opened).toBeTruthy();
|
||||||
title: 'Short Text2',
|
|
||||||
fieldType: 'textfield',
|
|
||||||
fieldValue: '',
|
|
||||||
required: true,
|
|
||||||
disabled: false,
|
|
||||||
deletePreserved: false,
|
|
||||||
logicJump: Object({ })
|
|
||||||
};
|
|
||||||
|
|
||||||
var actualFormField = _.cloneDeep(_.last(scope.myform.form_fields));
|
|
||||||
delete actualFormField._id;
|
|
||||||
|
|
||||||
expect(scope.myform.form_fields.length).toEqual(sampleForm.form_fields.length+1);
|
|
||||||
expect(actualFormField).toEqualData(expectedFormField);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('$scope.deleteField() should DELETE a field to $scope.myform.form_fields', function() {
|
it('$scope.deleteField() should DELETE a field to $scope.myform.form_fields', function() {
|
||||||
|
|||||||
@ -5,7 +5,6 @@
|
|||||||
describe('FieldIcon Directive Tests', function() {
|
describe('FieldIcon Directive Tests', function() {
|
||||||
// Initialize global variables
|
// Initialize global variables
|
||||||
var scope,
|
var scope,
|
||||||
FormFields,
|
|
||||||
faClasses = {
|
faClasses = {
|
||||||
'textfield': 'fa fa-pencil-square-o',
|
'textfield': 'fa fa-pencil-square-o',
|
||||||
'dropdown': 'fa fa-th-list',
|
'dropdown': 'fa fa-th-list',
|
||||||
@ -28,10 +27,68 @@
|
|||||||
// Load the main application module
|
// Load the main application module
|
||||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||||
|
|
||||||
|
//Mock FormFields Service
|
||||||
|
var FormFields = {
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
name : 'textfield',
|
||||||
|
value : 'Short Text'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'email',
|
||||||
|
value : 'Email'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'radio',
|
||||||
|
value : 'Muliple Choice'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'dropdown',
|
||||||
|
value : 'Dropdown'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'date',
|
||||||
|
value : 'Date'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'textarea',
|
||||||
|
value : 'Paragraph',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'yes_no',
|
||||||
|
value : 'Yes/No',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'legal',
|
||||||
|
value : 'Legal',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'rating',
|
||||||
|
value : 'Rating',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'link',
|
||||||
|
value : 'Link',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'number',
|
||||||
|
value : 'Numbers',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'statement',
|
||||||
|
value : 'Statement'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
beforeEach(module(function($provide) {
|
||||||
|
$provide.service('FormFields', function() {
|
||||||
|
return FormFields;
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
beforeEach(inject(function ($rootScope, _FormFields_) {
|
beforeEach(inject(function ($rootScope, _FormFields_) {
|
||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
FormFields = _FormFields_;
|
}));
|
||||||
}));
|
|
||||||
|
|
||||||
it('should be able render all field-icon types', inject(function($compile) {
|
it('should be able render all field-icon types', inject(function($compile) {
|
||||||
var currType, currClass;
|
var currType, currClass;
|
||||||
|
|||||||
@ -5,11 +5,63 @@
|
|||||||
describe('Field Directive Tests', function() {
|
describe('Field Directive Tests', function() {
|
||||||
// Initialize global variables
|
// Initialize global variables
|
||||||
var scope,
|
var scope,
|
||||||
FormFields,
|
|
||||||
$templateCache,
|
$templateCache,
|
||||||
$httpBackend,
|
$httpBackend,
|
||||||
$compile;
|
$compile;
|
||||||
|
|
||||||
|
var FormFields = {
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
name : 'textfield',
|
||||||
|
value : 'Short Text'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'email',
|
||||||
|
value : 'Email'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'radio',
|
||||||
|
value : 'Muliple Choice'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'dropdown',
|
||||||
|
value : 'Dropdown'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'date',
|
||||||
|
value : 'Date'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'textarea',
|
||||||
|
value : 'Paragraph',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'yes_no',
|
||||||
|
value : 'Yes/No',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'legal',
|
||||||
|
value : 'Legal',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'rating',
|
||||||
|
value : 'Rating',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'link',
|
||||||
|
value : 'Link',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'number',
|
||||||
|
value : 'Numbers',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'statement',
|
||||||
|
value : 'Statement'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
var sampleUser = {
|
var sampleUser = {
|
||||||
firstName: 'Full',
|
firstName: 'Full',
|
||||||
lastName: 'Name',
|
lastName: 'Name',
|
||||||
@ -65,9 +117,15 @@
|
|||||||
|
|
||||||
beforeEach(module('ngSanitize', 'ui.select'));
|
beforeEach(module('ngSanitize', 'ui.select'));
|
||||||
|
|
||||||
|
//Mock FormFields Service
|
||||||
|
beforeEach(module(function($provide) {
|
||||||
|
$provide.service('FormFields', function() {
|
||||||
|
return FormFields;
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
beforeEach(inject(function($rootScope, _FormFields_, _$compile_, _$httpBackend_) {
|
beforeEach(inject(function($rootScope, _FormFields_, _$compile_, _$httpBackend_) {
|
||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
FormFields = _FormFields_;
|
|
||||||
|
|
||||||
// Point global variables to injected services
|
// Point global variables to injected services
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
@ -76,6 +134,7 @@
|
|||||||
$compile = _$compile_;
|
$compile = _$compile_;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it('should be able to render all field types in html', inject(function($rootScope) {
|
it('should be able to render all field types in html', inject(function($rootScope) {
|
||||||
scope.fields = sampleFields;
|
scope.fields = sampleFields;
|
||||||
|
|
||||||
|
|||||||
@ -4,15 +4,73 @@
|
|||||||
// Forms Controller Spec
|
// Forms Controller Spec
|
||||||
describe('onFinishRender Directive Tests', function() {
|
describe('onFinishRender Directive Tests', function() {
|
||||||
// Initialize global variables
|
// Initialize global variables
|
||||||
var scope,
|
var scope;
|
||||||
FormFields;
|
|
||||||
|
var FormFields = {
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
name : 'textfield',
|
||||||
|
value : 'Short Text'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'email',
|
||||||
|
value : 'Email'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'radio',
|
||||||
|
value : 'Muliple Choice'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'dropdown',
|
||||||
|
value : 'Dropdown'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'date',
|
||||||
|
value : 'Date'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'textarea',
|
||||||
|
value : 'Paragraph',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'yes_no',
|
||||||
|
value : 'Yes/No',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'legal',
|
||||||
|
value : 'Legal',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'rating',
|
||||||
|
value : 'Rating',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'link',
|
||||||
|
value : 'Link',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'number',
|
||||||
|
value : 'Numbers',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'statement',
|
||||||
|
value : 'Statement'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
// Load the main application module
|
// Load the main application module
|
||||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||||
|
|
||||||
beforeEach(inject(function ($rootScope, _FormFields_) {
|
//Mock FormFields Service
|
||||||
|
beforeEach(module(function($provide) {
|
||||||
|
$provide.service('FormFields', function() {
|
||||||
|
return FormFields;
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(inject(function ($rootScope) {
|
||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
FormFields = _FormFields_;
|
|
||||||
spyOn($rootScope, '$broadcast');
|
spyOn($rootScope, '$broadcast');
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|||||||
@ -9,7 +9,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
|
|||||||
$scope.forms = {};
|
$scope.forms = {};
|
||||||
|
|
||||||
$scope.signin = function() {
|
$scope.signin = function() {
|
||||||
if(!$scope.forms.signinForm.$invalid){
|
if($scope.forms && $scope.forms.hasOwnProperty('siginForm') && !$scope.forms.signinForm.$invalid){
|
||||||
User.login($scope.credentials).then(
|
User.login($scope.credentials).then(
|
||||||
function(response) {
|
function(response) {
|
||||||
Auth.login(response);
|
Auth.login(response);
|
||||||
|
|||||||
@ -80,7 +80,7 @@
|
|||||||
|
|
||||||
// Load the main application module
|
// Load the main application module
|
||||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||||
|
beforeEach(module('module-templates'));
|
||||||
beforeEach(module('stateMock'));
|
beforeEach(module('stateMock'));
|
||||||
|
|
||||||
// Mock Users Service
|
// Mock Users Service
|
||||||
|
|||||||
10
server.js
10
server.js
@ -3,12 +3,15 @@
|
|||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require('dotenv').config({path: './.env'});
|
|
||||||
|
|
||||||
if(!process.env.NODE_ENV){
|
if(!process.env.NODE_ENV){
|
||||||
process.env.NODE_ENV = 'development';
|
process.env.NODE_ENV = 'development';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Don't check .env file if we are in travis-ci
|
||||||
|
if(!process.env.TRAVIS){
|
||||||
|
require('dotenv').config({path: './.env'});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
require('events').EventEmitter.prototype._maxListeners = 0;
|
require('events').EventEmitter.prototype._maxListeners = 0;
|
||||||
|
|
||||||
@ -62,9 +65,6 @@ console.log('--');
|
|||||||
console.log(chalk.green('Environment:\t\t\t' + process.env.NODE_ENV));
|
console.log(chalk.green('Environment:\t\t\t' + process.env.NODE_ENV));
|
||||||
console.log(chalk.green('Port:\t\t\t\t' + config.port));
|
console.log(chalk.green('Port:\t\t\t\t' + config.port));
|
||||||
console.log(chalk.green('Database:\t\t\t' + config.db.uri));
|
console.log(chalk.green('Database:\t\t\t' + config.db.uri));
|
||||||
if (process.env.NODE_ENV === 'secure') {
|
|
||||||
console.log(chalk.green('HTTPs:\t\t\t\ton'));
|
|
||||||
}
|
|
||||||
console.log('--');
|
console.log('--');
|
||||||
|
|
||||||
process.on('uncaughtException', function (err) {
|
process.on('uncaughtException', function (err) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user