Compare commits

...

34 commits

Author SHA1 Message Date
David Baldwynn ef23ceb07d Merge branch '2.20' into fixedSignupErrors 2017-11-05 16:26:35 -08:00
David Baldwynn 43ce60b985 Merge branch 'master' into 2.20 2017-11-05 16:24:19 -08:00
David Baldwynn 8521ede885 Merge branch 'master' into 2.20 2017-11-05 15:43:07 -08:00
David Baldwynn 8f55df1393
Merge pull request #246 from tellform/increaseTestCoverage
Increased Test Coverage
2017-10-30 12:03:53 -07:00
David Baldwynn 56cf745270 added check to not load .env on travis run 2017-10-30 11:12:44 -07:00
David Baldwynn c871d320f1 remove swig 2017-10-30 11:01:13 -07:00
David Baldwynn 814466cd1d switched to npm for travis 2017-10-30 10:47:54 -07:00
David Baldwynn 56fda0d312 switched travis scripts to yarn 2017-10-30 10:35:05 -07:00
David Baldwynn 5805c9b529 fixed travis test command 2017-10-30 09:54:03 -07:00
David Baldwynn fc4d9a12f0 fixed lcovMerge for travis 2017-10-30 09:40:09 -07:00
David Baldwynn 26716e256d migrating to yarn 2017-10-29 21:54:30 -07:00
David Baldwynn 8d9e66548b remove references to i18n-lint 2017-10-29 21:37:22 -07:00
David Baldwynn 8ea1f63c96 fixed travis settings 2017-10-29 21:32:02 -07:00
David Baldwynn b2b09171f3 fixed api tests 2017-10-29 21:22:43 -07:00
David Baldwynn d0d273a718 removed secure configuration 2017-10-29 20:23:36 -07:00
David Baldwynn 774d256507 removed unused code from user.server.model.js 2017-10-29 20:14:40 -07:00
David Baldwynn 9a0a301c3d got rid of unnessecary user middleware 2017-10-29 20:11:58 -07:00
David Baldwynn 3e3e7ccfe6 removed hasRole and hasAdminRole from passport_helpers 2017-10-29 19:02:01 -07:00
David Baldwynn e1db98ec95 added tests for api routes 2017-10-29 18:17:20 -07:00
David Baldwynn 99a6cb5009 fixed hasAuthorization bug for API 2017-10-29 17:46:08 -07:00
David Baldwynn 15eb66e455 added test for /users/me routes 2017-10-29 17:34:27 -07:00
David Baldwynn aed7c6c43b added test for changing password route 2017-10-29 17:20:34 -07:00
David Baldwynn 9fffdf5328 added tests to cover reset password routes 2017-10-29 15:47:01 -07:00
David Baldwynn 3dbfe2f88d added helper function to remove sensitive data from forms/users 2017-10-29 14:15:13 -07:00
David Baldwynn aa554c8210 added coveralls support 2017-10-29 13:02:41 -07:00
David Baldwynn 759a4efdd1 got all tests to pass 2017-10-29 12:44:12 -07:00
David Baldwynn 88fbf9e51f got user tests to pass 2017-10-29 12:20:49 -07:00
David Baldwynn 6fbfa35473 fixed on-finish-render directive tests 2017-10-29 12:17:54 -07:00
David Baldwynn f427092144 fixed field directive tests 2017-10-29 12:16:34 -07:00
David Baldwynn ebcc0c63cd fixed field-icon tests 2017-10-29 12:13:22 -07:00
David Baldwynn 7d65f0161b removed duplicate translation keyword for form admin panel 2017-10-29 12:07:42 -07:00
David Baldwynn 538030c551 got edit-form-directive tests to pass 2017-10-29 12:01:30 -07:00
David Baldwynn 76d6d54cd5 got edit-submissions-form directive tests to pass 2017-10-29 11:54:40 -07:00
David Baldwynn eaef327b37 fixed reloading bug for settings pages 2017-10-28 01:19:09 -07:00
39 changed files with 9394 additions and 527 deletions

View file

@ -11,5 +11,9 @@ services:
addons:
code_climate:
repo_token: 6c3a1b81a09b2338d6f30913c1bcad115026689752cbb499a0a25061cda6fbcf
after_script:
- grunt coverage
install:
- npm install phantomjs
- npm install -g grunt
- npm install
script:
- yarn run travis

View file

@ -9,7 +9,8 @@ var mongoose = require('mongoose'),
FormSubmission = mongoose.model('FormSubmission'),
config = require('../../config/config'),
diff = require('deep-diff'),
_ = require('lodash');
_ = require('lodash'),
helpers = require('./helpers.server.controller');
/**
* Delete a forms submissions
@ -104,15 +105,15 @@ exports.create = function(req, res) {
form.admin = req.user._id;
form.save(function(err) {
debugger;
form.save(function(err, createdForm) {
if (err) {
return res.status(500).send({
message: errorHandler.getErrorMessage(err)
});
}
return res.json(form);
createdForm = helpers.removeSensitiveModelData('private_form', createdForm);
return res.json(createdForm);
});
};
@ -123,16 +124,19 @@ exports.read = function(req, res) {
if(!req.user || (req.form.admin.id !== req.user.id) ){
readForRender(req, res);
} else {
var newForm = req.form.toJSON();
if (req.userId) {
if(req.form.admin._id+'' === req.userId+''){
return res.json(newForm);
}
if(!req.form){
return res.status(404).send({
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);
}
};
@ -148,9 +152,7 @@ var readForRender = exports.readForRender = function(req, res) {
});
}
delete newForm.lastModified;
delete newForm.__v;
delete newForm.created;
newForm = helpers.removeSensitiveModelData('public_form', newForm);
if(newForm.startPage && !newForm.startPage.showStart){
delete newForm.startPage;
@ -166,11 +168,8 @@ exports.update = function(req, res) {
var form = req.form;
var updatedForm = req.body.form;
if(form.form_fields === undefined){
form.form_fields = [];
}
if(form.analytics === undefined){
if(!form.analytics){
form.analytics = {
visitors: [],
gaCode: ''
@ -192,11 +191,6 @@ exports.update = function(req, res) {
delete updatedForm.admin;
}
if(form.analytics === null){
form.analytics.visitors = [];
form.analytics.gaCode = '';
}
//Do this so we can create duplicate fields
var checkForValidId = new RegExp('^[0-9a-fA-F]{24}$');
for(var i=0; i < req.body.form.form_fields.length; i++){
@ -214,6 +208,7 @@ exports.update = function(req, res) {
message: errorHandler.getErrorMessage(err)
});
} else {
savedForm = helpers.removeSensitiveModelData('private_form', savedForm);
res.json(savedForm);
}
});
@ -255,6 +250,8 @@ exports.list = function(req, res) {
});
} else {
for(var i=0; i<forms.length; i++){
forms[i] = helpers.removeSensitiveModelData('private_form', forms[i]);
forms[i].numberOfResponses = 0;
if(forms[i].submissions){
forms[i].numberOfResponses = forms[i].submissions.length;
@ -275,6 +272,7 @@ exports.formByID = function(req, res, next, id) {
message: 'Form is invalid'
});
}
Form.findById(id)
.populate('admin')
.exec(function(err, form) {
@ -287,12 +285,7 @@ exports.formByID = function(req, res, next, id) {
}
else {
//Remove sensitive information from User object
var _form = form;
_form.admin.password = null;
_form.admin.salt = null;
_form.provider = null;
req.form = _form;
req.form = helpers.removeSensitiveModelData('private_form', form);
return next();
}
});
@ -320,13 +313,7 @@ exports.formByIDFast = function(req, res, next, id) {
}
else {
//Remove sensitive information from User object
var _form = form;
if(_form.admin){
_form.admin.password = null;
_form.admin.salt = null;
_form.provider = null;
}
req.form = _form;
req.form = helpers.removeSensitiveModelData('public_form', form);
return next();
}
});

View file

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

View file

@ -12,7 +12,8 @@ var errorHandler = require('../errors.server.controller'),
fs = require('fs'),
i18n = require('i18n'),
async = require('async'),
pug = require('pug');
pug = require('pug'),
helpers = require('../helpers.server.controller');
var nev = require('email-verification')(mongoose);
@ -179,6 +180,8 @@ exports.signin = function(req, res, next) {
}
res.cookie('langCookie', user.language, { maxAge: 90000, httpOnly: true });
user = helpers.removeSensitiveModelData('private_user', user);
return res.json(user);
});
}
@ -198,16 +201,12 @@ exports.signout = function(req, res) {
/* Generate API Key for User */
exports.generateAPIKey = function(req, res) {
if (!req.isAuthenticated()){
return res.status(400).send({
message: 'User is not Authorized'
});
}
User.findById(req.user.id)
.exec( function(err, user) {
if (err) {
return res.status(400).send(err);
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
}
if (!user) {
@ -226,12 +225,8 @@ exports.generateAPIKey = function(req, res) {
}
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 });
});
});

View file

@ -3,36 +3,7 @@
/**
* Module dependencies.
*/
var _ = require('lodash'),
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();
});
};
var auth = require('../../../config/passport_helpers');
/**
* Require login routing middleware
*/
@ -45,22 +16,3 @@ exports.requiresLogin = function(req, res, 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'
});
}
});
};
};

View file

@ -84,7 +84,6 @@ exports.forgot = function(req, res) {
const fn = pug.compileFile(__dirname + "/../../views/templates/reset-password-email.server.view.pug");
res.locals['url'] = 'http://' + req.headers.host + '/auth/reset/' + token;
console.log(res.locals);
var renderedHtml = fn(res.locals);
done(null, renderedHtml, user);
},
@ -142,7 +141,7 @@ exports.validateResetToken = function(req, res) {
});
}
if (!user) {
return res.redirect('/#!/password/reset/invalid');
return res.redirect(400, '/#!/password/reset/invalid');
}
res.redirect('/#!/password/reset/' + req.params.token);
@ -187,7 +186,7 @@ exports.reset = function(req, res, next) {
done(null, savedUser);
});
} else {
done('Password reset token is invalid or has expired.', null);
done('invalid_reset_token', null);
}
});
},
@ -211,12 +210,18 @@ exports.reset = function(req, res, next) {
}
], function(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
});
}
return res.json({
res.json({
message: 'Successfully changed your password!'
});
});

View file

@ -5,7 +5,8 @@
*/
var _ = require('lodash'),
errorHandler = require('../errors.server.controller.js'),
mongoose = require('mongoose');
mongoose = require('mongoose'),
helpers = require('../helpers.server.controller');
/**
* Update user details
@ -14,47 +15,36 @@ exports.update = function(req, res) {
// Init Variables
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;
if (user) {
// Merge existing user
user = _.extend(user, req.body);
user.updated = Date.now();
// Merge existing user
user = _.extend(user, req.body);
user.updated = Date.now();
user.save(function(err) {
if (err) {
return res.status(500).send({
message: errorHandler.getErrorMessage(err)
});
}
req.login(user, function(loginErr) {
if (err) {
res.status(500).send(loginErr);
} else {
res.json(user);
}
user.save(function(err) {
if (err) {
return res.status(500).send({
message: errorHandler.getErrorMessage(err)
});
}
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
*/
exports.getUser = function(req, res) {
var _user = req.user;
delete _user.password;
delete _user.salt;
delete _user.provider;
delete _user.__v;
var user = helpers.removeSensitiveModelData('private_user', req.user);
res.json(req.user || null);
res.end();
return res.json(user);
};

View file

@ -101,12 +101,17 @@ var FormSchema = new Schema({
visitors: [VisitorDataSchema]
},
form_fields: [FieldSchema],
submissions: [{
type: Schema.Types.ObjectId,
ref: 'FormSubmission'
}],
form_fields: {
type: [FieldSchema],
default: []
},
submissions: {
type: [{
type: Schema.Types.ObjectId,
ref: 'FormSubmission'
}],
dfeault: []
},
admin: {
type: Schema.Types.ObjectId,
ref: 'User',
@ -153,6 +158,7 @@ var FormSchema = new Schema({
type: Boolean,
default: false
},
isLive: {
type: Boolean,
default: true
@ -288,26 +294,6 @@ FormSchema.plugin(timeStampPlugin, {
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){
var deletedIndexes = [];

View file

@ -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();
});
};

View file

@ -23,28 +23,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);
};
/**
* A Validation function for username
*/
var validateUsername = function(username) {
return (username.match(/^[a-zA-Z0-9.-_]+$/) !== null);
};
/**
* User Schema
*/
@ -85,8 +63,6 @@ var UserSchema = new Schema({
type: String,
default: 'local'
},
providerData: {},
additionalProvidersData: {},
roles: {
type: [{
type: String,
@ -123,10 +99,6 @@ var UserSchema = new Schema({
}
});
UserSchema.virtual('displayName').get(function () {
return this.firstName + ' ' + this.lastName;
});
UserSchema.plugin(timeStampPlugin, {
createdPath: 'created',
modifiedPath: 'lastModified',

View file

@ -12,6 +12,7 @@ module.exports = function(app) {
var users = require('../../app/controllers/users.server.controller');
// 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').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').post(users.resendVerificationEmail);
// Setting up the users password api
app.route('/users/password').post(users.requiresLogin, users.changePassword);
// Setting up the password reset api
app.route('/auth/forgot').post(users.forgot);
app.route('/auth/reset/:token').get(users.validateResetToken);
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/genkey').get(users.requiresLogin, users.generateAPIKey);
// Finish by binding the user middleware
app.param('userId', users.userByID);
};

View file

@ -69,7 +69,6 @@ describe('Form Routes Unit tests', function() {
.send({form: myForm})
.expect(401)
.end(function(FormSaveErr, FormSaveRes) {
console.log(FormSaveRes.text);
// Call the assertion callback
done(FormSaveErr);
});

View file

@ -17,7 +17,6 @@ var exampleDemo = {
address: '880-9650 Velit. St.',
city: '',
dateOfBirth: '10',
displayName: 'Test User',
email: 'polydaic@gmail.com',
firstName: 'Test User',
hin: '',
@ -82,7 +81,6 @@ describe('FormSubmission Model Unit Tests:', function() {
user = new User({
firstName: 'Full',
lastName: 'Name',
displayName: 'Full Name',
email: 'test1@test.com'+Date.now(),
username: 'test1'+Date.now(),
password: 'password',

View file

@ -6,24 +6,23 @@ var should = require('should'),
mongoose = require('mongoose'),
User = mongoose.model('User'),
config = require('../../config/config'),
tmpUser = mongoose.model(config.tempUserCollection);
tmpUser = mongoose.model(config.tempUserCollection),
async = require('async');
/**
* Globals
*/
var credentials, _User, activateToken, userSession;
var credentials, _User, userSession;
/**
* Form routes tests
*/
describe('User CRUD tests', function() {
this.timeout(30000);
beforeEach(function() {
before(function() {
// Create user credentials
credentials = {
email: 'test732@test.com',
username: 'test732',
email: 'test099@test.com',
username: 'test099',
password: 'password3223'
};
@ -31,77 +30,424 @@ describe('User CRUD tests', function() {
_User = {
email: credentials.email,
username: credentials.username,
password: credentials.password
password: credentials.password,
firstName: 'John',
lastName: 'Smith'
};
//Initialize Session
userSession = Session(app);
});
it(' > Create, Verify and Activate a User > ', function() {
it('should be able to create a temporary (non-activated) User', function(done) {
userSession.post('/auth/signup')
.send(_User)
.expect(200)
.end(function(FormSaveErr) {
// Handle error
should.not.exist(FormSaveErr);
tmpUser.findOne({username: _User.username}, function (err, user) {
should.not.exist(err);
describe(' > Create, Verify and Activate a User > ', function() {
this.timeout(10000);
it('should be able to create and activate a User', function(done) {
async.waterfall([
function(callback) {
userSession.post('/auth/signup')
.send(_User)
.expect(200)
.end(function(err) {
callback(err)
});
},
function(callback) {
tmpUser.findOne({username: _User.username})
.lean()
.exec(function (err, user) {
should.exist(user);
_User.username.should.equal(user.username);
_User.firstName.should.equal(user.firstName);
_User.lastName.should.equal(user.lastName);
activateToken = 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();
});
});
});
callback(err, user.GENERATED_VERIFYING_URL);
});
});
},
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 () {
tmpUser.remove().exec(function(){
userSession.destroy();

60
config/env/secure.js vendored
View file

@ -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 || ''
}
}
}
};

View file

@ -337,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);
// Return Express server instance

View file

@ -63,7 +63,6 @@ logger.setupFileLogger = function setupFileLogger() {
return false;
}
};
/**
@ -76,7 +75,7 @@ logger.getLogOptions = function getLogOptions() {
var _config = _.clone(config, true);
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');
return false;
}
@ -97,7 +96,6 @@ logger.getLogOptions = function getLogOptions() {
handleExceptions: true,
humanReadableUnhandledException: true
};
};
/**

View file

@ -6,14 +6,24 @@ module.exports.isAuthenticatedOrApiKey = function isAuthenticated(req, res, next
if (req.isAuthenticated()) {
return next();
}
// Try authenticate with API KEY
if (req.headers.apikey || req.query.apikey || req.body.apikey) {
passport.authenticate('localapikey', function (err, user, info) {
if (err)
return res.sendStatus(500);
if(!req.body.apikey && req.headers.apikey){
req.body.apikey = req.headers.apikey;
} 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 || '');
}
req.login(user, function(loginErr) {
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');
};

View file

@ -11,13 +11,15 @@ module.exports = function() {
return User.findOne({
'apiKey': apiKey
}, function(err, user) {
if (err)
if (err) {
return done(err);
}
if (!user)
if (!user){
return done(null, false, {
message: 'Unknown API Key'
});
}
return done(null, user);
});

View file

@ -1,4 +1,4 @@
'use strict';
var bowerArray = ['public/lib/angular/angular.min.js',
'public/lib/angular-scroll/angular-scroll.min.js',
@ -204,63 +204,23 @@ module.exports = function(grunt) {
singleRun: true
}
},
protractor: {
options: {
configFile: 'protractor.conf.js',
keepAlive: true,
noColor: false
},
e2e: {
options: {
args: {} // Target-specific arguments
}
}
},
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: {
src: watchFiles.serverTests,
options: {
coverageFolder: 'coverageServer',
mask: '*.test.js',
require: ['server.js']
}
},
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']
require: ['server.js'],
reportFormats: ['html','lcovonly']
}
}
},
istanbul_check_coverage: {
default: {
options: {
coverageFolder: 'coverage*', // will check both coverage folders and merge the coverage results
check: {
lines: 80,
statements: 80
}
}
}
},
lcovMerge: {
options: {
emitters: ['event'],
},
src: ['./coverageServer/*.info', './coverageClient/lcov-report/*.info']
},
html2js: {
options: {
base: 'public',
@ -287,7 +247,7 @@ module.exports = function(grunt) {
options: {
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'
}
},
@ -323,9 +283,7 @@ module.exports = function(grunt) {
});
// Code coverage tasks.
grunt.registerTask('coveralls', ['env:test','mocha_istanbul:coveralls']);
grunt.registerTask('coverage', ['env:test', 'mocha_istanbul:coverage']);
grunt.registerTask('coverage:client', ['env:test', 'mocha_istanbul:coverageClient']);
grunt.registerTask('coveralls', ['test:client', 'karma:unit', 'mocha_istanbul:coverageServer', 'lcovMerge']);
grunt.registerTask('coverage:server', ['env:test', 'mocha_istanbul:coverageServer']);
// Default task(s).
@ -339,7 +297,7 @@ module.exports = function(grunt) {
grunt.registerTask('secure', ['env:secure', 'lint', 'html2js:main', 'html2js:forms', 'concurrent:default']);
// Lint task(s).
grunt.registerTask('lint', ['jshint', 'csslint', 'i18nlint:client', 'i18nlint:server']);
grunt.registerTask('lint', ['jshint', 'csslint']);
grunt.registerTask('lint:tests', ['jshint:allTests']);
// Build task(s).
@ -349,9 +307,11 @@ module.exports = function(grunt) {
grunt.registerTask('setup', ['execute']);
// 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: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']);
};

View file

@ -29,11 +29,20 @@ module.exports = function(config) {
'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/modules/*/*.js': ['coverage'],
//'public/modules/*/*[!tests]*/*.js': ['coverage'],
'public/form_modules/forms/base/views/*.html': ['ng-html2js'],
'public/modules/*/*.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: {
stripPrefix: 'public/',
prependPrefix: 'static/',

View file

@ -21,6 +21,7 @@
"generate": "all-contributors generate",
"start": "grunt",
"test": "grunt test",
"travis": "grunt test:travis",
"postinstall": "bower install --config.interactive=false; grunt build;",
"init": "node scripts/setup.js"
},
@ -71,7 +72,6 @@
"request": "^2.83.0",
"socket.io": "^1.4.6",
"socket.io-redis": "^1.0.0",
"swig": "~1.4.1",
"uuid-token-generator": "^0.5.0",
"winston": "^2.3.1"
},
@ -88,8 +88,8 @@
"grunt-contrib-uglify": "^0.11.1",
"grunt-contrib-watch": "~0.6.1",
"grunt-execute": "^0.2.2",
"grunt-i18nlint": "github:jwarby/grunt-i18nlint",
"grunt-karma": "~0.12.1",
"grunt-lcov-merge": "^1.2.3",
"grunt-mocha-istanbul": "^3.0.1",
"grunt-mocha-test": "~0.12.1",
"grunt-newer": "~1.1.1",
@ -97,7 +97,7 @@
"grunt-usemin": "^3.1.1",
"grunt-wiredep": "^3.0.1",
"istanbul": "^0.4.0",
"jasmine-core": "^2.4.1",
"jasmine-core": "^2.6",
"karma": "~0.13.14",
"karma-chrome-launcher": "~0.2.1",
"karma-coverage": "~0.5.3",
@ -110,7 +110,7 @@
"mocha": "^3.1.2",
"mocha-lcov-reporter": "^1.0.0",
"nightwatch": "^0.9.8",
"phantomjs": "^1.9.18",
"phantomjs-prebuilt": "^2.1.15",
"selenium-server": "^3.0.1",
"should": "~7.1.1",
"supertest": "~1.2.0",

1349
public/dist/application.js vendored Normal file

File diff suppressed because it is too large Load diff

1
public/dist/application.min.js vendored Normal file

File diff suppressed because one or more lines are too long

20
public/dist/vendor.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -153,7 +153,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
MULTIPLE_CHOICE: 'Multiple Choice',
DROPDOWN: 'Dropdown',
DATE: 'Date',
PARAGRAPH_T: 'Paragraph',
PARAGRAPH_FIELD: 'Paragraph',
YES_NO: 'Yes/No',
LEGAL: 'Legal',
RATING: 'Rating',

View file

@ -152,7 +152,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
MULTIPLE_CHOICE: 'Choix multiple',
DROPDOWN: 'Menu Déroulant',
DATE: 'Date',
PARAGRAPH_T: "Paragraphe",
PARAGRAPH_FIELD: "Paragraphe",
OUI_NON: 'Oui / Non',
LEGAL: 'Légal',
RATING: "Évaluation",

View file

@ -151,7 +151,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
MULTIPLE_CHOICE: 'Mehrfachauswahl',
DROPDOWN: 'Dropdown-Liste',
DATE: 'Datum',
PARAGRAPH_T: "Absatz",
PARAGRAPH_FIELD: "Absatz",
YES_NO: 'Ja / Nein',
LEGAL: "Rechtliche",
RATING: 'Bewertung',

View file

@ -152,7 +152,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
MULTIPLE_CHOICE: 'Scelta multipla',
DROPDOWN: 'Dropdown',
DATE: 'Data',
PARAGRAPH_T: 'Paragrafo',
PARAGRAPH_FIELD: 'Paragrafo',
YES_NO: 'Sì / no',
LEGAL: 'Legale',
RATING: 'Valutazione',

View file

@ -153,7 +153,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
MULTIPLE_CHOICE: 'Opciones múltiples',
DROPDOWN: 'Desplegable',
DATE: 'Fecha',
PARAGRAPH_T: 'Párrafo',
PARAGRAPH_FIELD: 'Párrafo',
YES_NO: 'Si/No',
LEGAL: 'Legal',
RATING: 'Puntaje',

View file

@ -30,7 +30,7 @@ angular.module('forms').service('FormFields', [ '$rootScope', '$translate', 'Aut
},
{
name : 'textarea',
value : $translate.instant('PARAGRAPH'),
value : $translate.instant('PARAGRAPH_FIELD'),
},
{
name : 'yes_no',

View file

@ -5,25 +5,24 @@ angular.module('users').config(['$stateProvider',
function($stateProvider) {
var checkLoggedin = function($q, $timeout, $state, User, Auth) {
var deferred = $q.defer();
if (Auth.currentUser && Auth.currentUser.email) {
$timeout(deferred.resolve);
return;
}
else {
Auth.currentUser = User.getCurrent(
function() {
Auth.login();
$timeout(deferred.resolve());
return User.getCurrent().then(
function(user) {
Auth.login(user);
return;
},
function() {
Auth.logout();
$timeout(deferred.reject());
$state.go('signin', {reload: true});
Auth.logout();
$state.go('signin', {reload: true});
return;
});
}
return deferred.promise;
};
var checkSignupDisabled = function($window, $timeout, $q) {

View file

@ -11,7 +11,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
var statesToIgnore = ['', 'home', 'signin', 'resendVerifyEmail', 'verify', 'signup', 'signup-success', 'forgot', 'reset-invalid', 'reset', 'reset-success'];
$scope.signin = function() {
if(!$scope.forms.signinForm.$invalid){
if($scope.forms && $scope.forms.hasOwnProperty('siginForm') && !$scope.forms.signinForm.$invalid){
User.login($scope.credentials).then(
function(response) {
Auth.login(response);

View file

@ -0,0 +1,29 @@
'use strict';
angular.module('users').controller('ChangePasswordController', ['$scope', '$rootScope', '$http', '$state', 'Users', 'Auth',
function($scope, $rootScope, $http, $state, Users, Auth) {
$scope.user = Auth.currentUser;
console.log($scope.user)
$scope.cancel = function(){
$scope.user = Auth.currentUser;
}
// Change user password
$scope.changeUserPassword = function() {
$scope.success = $scope.error = null;
$http.post('/users/password', $scope.passwordDetails).success(function(response) {
// If successful show success message and clear form
$scope.success = true;
$scope.error = null;
$scope.passwordDetails = null;
}).error(function(response) {
$scope.success = null;
$scope.error = response.message;
});
};
*/
}
]);

View file

@ -5,41 +5,9 @@ angular.module('users').controller('SettingsController', ['$scope', '$rootScope'
$scope.user = Auth.currentUser;
// Check if there are additional accounts
$scope.hasConnectedAdditionalSocialAccounts = function(provider) {
for (var i in $scope.user.additionalProvidersData) {
return true;
}
return false;
};
$scope.cancel = function(){
$scope.user = Auth.currentUser;
};
// Check if provider is already in use with current user
$scope.isConnectedSocialAccount = function(provider) {
return $scope.user.provider === provider || ($scope.user.additionalProvidersData && $scope.user.additionalProvidersData[provider]);
};
// Remove a user social account
$scope.removeUserSocialAccount = function(provider) {
$scope.success = $scope.error = null;
$http.delete('/users/accounts', {
params: {
provider: provider
}
}).success(function(response) {
// If successful show success message and clear form
$scope.success = true;
$scope.error = null;
$scope.user = response;
}).error(function(response) {
$scope.success = null;
$scope.error = response.message;
});
};
}
// Update a user profile
$scope.updateUserProfile = function(isValid) {
@ -51,6 +19,7 @@ angular.module('users').controller('SettingsController', ['$scope', '$rootScope'
$scope.success = true;
$scope.error = null;
$scope.user = response;
$scope.$apply();
}, function(response) {
$scope.success = null;
$scope.error = response.data.message;
@ -59,21 +28,5 @@ angular.module('users').controller('SettingsController', ['$scope', '$rootScope'
$scope.submitted = true;
}
};
// Change user password
$scope.changeUserPassword = function() {
$scope.success = $scope.error = null;
$http.post('/users/password', $scope.passwordDetails).success(function(response) {
// If successful show success message and clear form
$scope.success = true;
$scope.error = null;
$scope.passwordDetails = null;
}).error(function(response) {
$scope.success = null;
$scope.error = response.message;
});
};
}
]);

View file

@ -0,0 +1,181 @@
'use strict';
(function() {
// Forms Controller Spec
describe('Authentication Controller Tests', function() {
// Initialize global variables
var AuthenticationController,
scope,
$httpBackend,
$stateParams,
$location,
$state;
var sampleUser = {
firstName: 'Full',
lastName: 'Name',
email: 'test@test.com',
username: 'test@test.com',
password: 'password',
provider: 'local',
roles: ['user'],
_id: 'ed873933b1f1dea0ce12fab9'
};
var sampleForm = {
title: 'Form Title',
admin: 'ed873933b1f1dea0ce12fab9',
language: 'english',
form_fields: [
{fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false},
{fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false},
{fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false}
],
_id: '525a8422f6d0f87f0e407a33'
};
var expectedForm = {
title: 'Form Title',
admin: 'ed873933b1f1dea0ce12fab9',
language: 'english',
form_fields: [
{fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false},
{fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false},
{fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false}
],
visible_form_fields: [
{fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false},
{fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false},
{fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false}
],
_id: '525a8422f6d0f87f0e407a33'
};
var sampleCredentials = {
username: sampleUser.username,
password: sampleUser.password,
};
// The $resource service augments the response object with methods for updating and deleting the resource.
// If we were to use the standard toEqual matcher, our tests would fail because the test values would not match
// the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher.
// When the toEqualData matcher compares two objects, it takes only object properties into
// account and ignores methods.
beforeEach(function() {
jasmine.addMatchers({
toEqualData: function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
return {
pass: angular.equals(actual, expected)
};
}
};
}
});
});
// Load the main application module
beforeEach(module(ApplicationConfiguration.applicationModuleName));
beforeEach(module('module-templates'));
beforeEach(module('stateMock'));
// Mock Users Service
beforeEach(module(function($provide) {
$provide.service('User', function($q) {
return {
getCurrent: function() {
var deferred = $q.defer();
deferred.resolve( JSON.stringify(sampleUser) );
return deferred.promise;
},
login: function(credentials) {
var deferred = $q.defer();
if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){
deferred.resolve( JSON.stringify(sampleUser) );
}else {
deferred.resolve('Error: User could not be loggedin');
}
return deferred.promise;
},
logout: function() {
var deferred = $q.defer();
deferred.resolve(null);
return deferred.promise;
},
signup: function(credentials) {
var deferred = $q.defer();
if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){
deferred.resolve( JSON.stringify(sampleUser) );
}else {
deferred.resolve('Error: User could not be signed up');
}
return deferred.promise;
}
};
});
}));
// Mock Authentication Service
beforeEach(module(function($provide) {
$provide.service('Auth', function() {
return {
ensureHasCurrentUser: function() {
return sampleUser;
},
isAuthenticated: function() {
return true;
},
getUserState: function() {
return true;
}
};
});
}));
// 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
// with the same name as the service.
beforeEach(inject(function($controller, $rootScope, _$state_, _$location_, _$stateParams_, _$httpBackend_, CurrentForm, Forms) {
// Set a new global scope
scope = $rootScope.$new();
scope.abc = 'hello';
// Point global variables to injected services
$stateParams = _$stateParams_;
$httpBackend = _$httpBackend_;
$location = _$location_;
$state = _$state_;
// $httpBackend.whenGET(/\.html$/).respond('');
$httpBackend.whenGET('/users/me/').respond('');
// Initialize the Forms controller.
AuthenticationController = $controller('AuthenticationController', { $scope: scope });
}));
it('$scope.signin should sigin in user with valid credentials', inject(function(Auth) {
//Set $state transition
// $state.expectTransitionTo('listForms');
//Set POST response
// $httpBackend.expect('POST', '/auth/signin', sampleCredentials).respond(200, sampleUser);
scope.abc = 'sampleCredentials';
//Run Controller Logic to Test
scope.signin();
// $httpBackend.flush();
// Test scope value
// expect(Auth.ensureHasCurrentUser()).toEqualData(sampleUser);
}));
});
}());

View file

@ -1,6 +1,6 @@
<header data-ng-include="'/static/modules/core/views/header.client.view.html'"></header>
<section class="row" data-ng-controller="SettingsController">
<section class="row" data-ng-controller="ChangePasswordController">
<h3 class="col-md-12 text-center">{{ 'CHANGE_PASSWORD' | translate }}</h3>
<div class="col-xs-offset-2 col-xs-8 col-md-offset-3 col-md-6">
<form data-ng-submit="changeUserPassword()" class="signin form-horizontal" autocomplete="off">

View file

@ -3,12 +3,15 @@
* Module dependencies.
*/
require('dotenv').config({path: './.env'});
if(!process.env.NODE_ENV){
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;
@ -62,9 +65,6 @@ console.log('--');
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('Database:\t\t\t' + config.db.uri));
if (process.env.NODE_ENV === 'secure') {
console.log(chalk.green('HTTPs:\t\t\t\ton'));
}
console.log('--');
process.on('uncaughtException', function (err) {

7203
yarn.lock Normal file

File diff suppressed because it is too large Load diff