diff --git a/config/env/development.js b/config/env/development.js index 39659d564d..e2fb300ec8 100644 --- a/config/env/development.js +++ b/config/env/development.js @@ -66,5 +66,28 @@ module.exports = { } }, livereload: true, - seedDB: process.env.MONGO_SEED || false + seedDB: { + seed: process.env.MONGO_SEED === 'true' ? true : false, + options: { + logResults: process.env.MONGO_SEED_LOG_RESULTS === 'false' ? false : true, + seedUser: { + username: process.env.MONGO_SEED_USER_USERNAME || 'user', + provider: 'local', + email: process.env.MONGO_SEED_USER_EMAIL || 'user@localhost.com', + firstName: 'User', + lastName: 'Local', + displayName: 'User Local', + roles: ['user'] + }, + seedAdmin: { + username: process.env.MONGO_SEED_ADMIN_USERNAME || 'admin', + provider: 'local', + email: process.env.MONGO_SEED_ADMIN_EMAIL || 'admin@localhost.com', + firstName: 'Admin', + lastName: 'Local', + displayName: 'Admin Local', + roles: ['user', 'admin'] + } + } + } }; diff --git a/config/env/production.js b/config/env/production.js index 29fd2f8071..22f71e1c88 100644 --- a/config/env/production.js +++ b/config/env/production.js @@ -66,5 +66,28 @@ module.exports = { } } }, - seedDB: process.env.MONGO_SEED || false + seedDB: { + seed: process.env.MONGO_SEED === 'true' ? true : false, + options: { + logResults: process.env.MONGO_SEED_LOG_RESULTS === 'false' ? false : true, + seedUser: { + username: process.env.MONGO_SEED_USER_USERNAME || 'user', + provider: 'local', + email: process.env.MONGO_SEED_USER_EMAIL || 'user@localhost.com', + firstName: 'User', + lastName: 'Local', + displayName: 'User Local', + roles: ['user'] + }, + seedAdmin: { + username: process.env.MONGO_SEED_ADMIN_USERNAME || 'admin', + provider: 'local', + email: process.env.MONGO_SEED_ADMIN_EMAIL || 'admin@localhost.com', + firstName: 'Admin', + lastName: 'Local', + displayName: 'Admin Local', + roles: ['user', 'admin'] + } + } + } }; diff --git a/config/env/test.js b/config/env/test.js index 2efb791e64..48011c4901 100644 --- a/config/env/test.js +++ b/config/env/test.js @@ -57,5 +57,28 @@ module.exports = { } } }, - seedDB: process.env.MONGO_SEED || false + seedDB: { + seed: process.env.MONGO_SEED === 'true' ? true : false, + options: { + logResults: process.env.MONGO_SEED_LOG_RESULTS === 'false' ? false : true, + seedUser: { + username: process.env.MONGO_SEED_USER_USERNAME || 'user', + provider: 'local', + email: process.env.MONGO_SEED_USER_EMAIL || 'user@localhost.com', + firstName: 'User', + lastName: 'Local', + displayName: 'User Local', + roles: ['user'] + }, + seedAdmin: { + username: process.env.MONGO_SEED_ADMIN_USERNAME || 'admin', + provider: 'local', + email: process.env.MONGO_SEED_ADMIN_EMAIL || 'admin@localhost.com', + firstName: 'Admin', + lastName: 'Local', + displayName: 'Admin Local', + roles: ['user', 'admin'] + } + } + } }; diff --git a/config/lib/app.js b/config/lib/app.js index 7a09537847..d9d0b0be09 100644 --- a/config/lib/app.js +++ b/config/lib/app.js @@ -10,7 +10,7 @@ var config = require('../config'), seed = require('./seed'); function seedDB() { - if (config.seedDB) { + if (config.seedDB.seed) { console.log(chalk.bold.red('Warning: Database seeding is turned on')); seed.start(); } diff --git a/config/lib/seed.js b/config/lib/seed.js index dcfcc2a029..d1ce86eaff 100644 --- a/config/lib/seed.js +++ b/config/lib/seed.js @@ -1,15 +1,20 @@ 'use strict'; -var mongoose = require('mongoose'), +var _ = require('lodash'), + config = require('../config'), + mongoose = require('mongoose'), chalk = require('chalk'), crypto = require('crypto'); +// global seed options object +var seedOptions = {}; + function removeUser (user) { return new Promise(function (resolve, reject) { var User = mongoose.model('User'); User.find({username: user.username}).remove(function (err) { if (err) { - reject(new Error('Database Seeding:\t\t\tFailed to remove local ' + user.username)); + reject(new Error('Failed to remove local ' + user.username)); } resolve(); }); @@ -22,7 +27,7 @@ function saveUser (user) { // Then save the user user.save(function (err, theuser) { if (err) { - reject(new Error('Database Seeding:\t\t\tFailed to add local ' + user.username)); + reject(new Error('Failed to add local ' + user.username)); } else { resolve(theuser); } @@ -36,13 +41,13 @@ function checkUserNotExists (user) { var User = mongoose.model('User'); User.find({username: user.username}, function (err, users) { if (err) { - reject(new Error('Database Seeding:\t\t\tFailed to find local account ' + user.username)); + reject(new Error('Failed to find local account ' + user.username)); } if (users.length === 0) { resolve(); } else { - reject(new Error('Database Seeding:\t\t\tFailed due to local account already exists: ' + user.username)); + reject(new Error('Failed due to local account already exists: ' + user.username)); } }); }); @@ -51,7 +56,9 @@ function checkUserNotExists (user) { function reportSuccess (password) { return function (user) { return new Promise(function (resolve, reject) { - console.log(chalk.bold.red('Database Seeding:\t\t\tLocal ' + user.username + ' added with password set to ' + password)); + if (seedOptions.logResults) { + console.log(chalk.bold.red('Database Seeding:\t\t\tLocal ' + user.username + ' added with password set to ' + password)); + } resolve(); }); }; @@ -66,82 +73,86 @@ function seedTheUser (user) { // set the new password user.password = password; - if (user.username === 'admin' && process.env.NODE_ENV === 'production') { + if (user.username === seedOptions.seedAdmin.username && process.env.NODE_ENV === 'production') { checkUserNotExists(user) - .then(saveUser(user)) - .then(reportSuccess(password)) - .then(function () { - resolve(); - }) - .catch(reportError); + .then(saveUser(user)) + .then(reportSuccess(password)) + .then(function () { + resolve(); + }) + .catch(function (err) { + reject(err); + }); } else { removeUser(user) - .then(saveUser(user)) - .then(reportSuccess(password)) - .then(function () { - resolve(); - }) - .catch(reportError); + .then(saveUser(user)) + .then(reportSuccess(password)) + .then(function () { + resolve(); + }) + .catch(function (err) { + reject(err); + }); } }); }; } // report the error -function reportError (err) { - console.log(); - console.log(err); - console.log(); +function reportError (reject) { + return function (err) { + if (seedOptions.logResults) { + console.log(); + console.log('Database Seeding:\t\t\t' + err); + console.log(); + } + reject(err); + }; } -module.exports.start = function start() { +module.exports.start = function start(options) { + // Initialize the default seed options + seedOptions = _.clone(config.seedDB.options, true); + + // Check for provided options + + if (_.has(options, 'logResults')) { + seedOptions.logResults = options.logResults; + } + + if (_.has(options, 'seedUser')) { + seedOptions.seedUser = options.seedUser; + } + + if (_.has(options, 'seedAdmin')) { + seedOptions.seedAdmin = options.seedAdmin; + } + var User = mongoose.model('User'); return new Promise(function (resolve, reject) { - var seedUser = { - username: 'user', - password: 'User_Password1!', - provider: 'local', - email: 'user@localhost.com', - firstName: 'User', - lastName: 'Local', - displayName: 'User Local', - roles: ['user'] - }; - - var seedAdmin = { - username: 'admin', - password: 'Admin_Password1!', - provider: 'local', - email: 'admin@localhost.com', - firstName: 'Admin', - lastName: 'Local', - displayName: 'Admin Local', - roles: ['user', 'admin'] - }; - - var user = null; - var adminAccount = new User(seedAdmin); - var userAccount = new User(seedUser); + + var adminAccount = new User(seedOptions.seedAdmin); + var userAccount = new User(seedOptions.seedUser); //If production only seed admin if it does not exist if (process.env.NODE_ENV === 'production') { User.generateRandomPassphrase() - .then(seedTheUser(adminAccount)) - .then(function () { + .then(seedTheUser(adminAccount)) + .then(function () { resolve(); }) - .catch(reportError); + .catch(reportError(reject)); } else { // Add both Admin and User account User.generateRandomPassphrase() - .then(seedTheUser(userAccount)) - .then(User.generateRandomPassphrase) - .then(seedTheUser(adminAccount)) - .then(function () { + .then(seedTheUser(userAccount)) + .then(User.generateRandomPassphrase) + .then(seedTheUser(adminAccount)) + .then(function () { resolve(); }) - .catch(reportError); + .catch(reportError(reject)); } }); }; diff --git a/modules/core/tests/server/core.server.config.tests.js b/modules/core/tests/server/core.server.config.tests.js index 8d1aeedc69..b32302b13d 100644 --- a/modules/core/tests/server/core.server.config.tests.js +++ b/modules/core/tests/server/core.server.config.tests.js @@ -10,13 +10,43 @@ var should = require('should'), config = require(path.resolve('./config/config')), seed = require(path.resolve('./config/lib/seed')); +/** + * Globals + */ +var user1, admin1, userFromSeedConfig, adminFromSeedConfig; + describe('Configuration Tests:', function () { describe('Testing default seedDB', function () { before(function(done) { User.remove(function(err) { should.not.exist(err); + + user1 = { + username: 'user_config_test', + provider: 'local', + email: 'user_config_test_@localhost.com', + firstName: 'User', + lastName: 'Local', + displayName: 'User Local', + roles: ['user'] + }; + + admin1 = { + username: 'admin_config_test', + provider: 'local', + email: 'admin_config_test_@localhost.com', + firstName: 'Admin', + lastName: 'Local', + displayName: 'Admin Local', + roles: ['user', 'admin'] + }; + + userFromSeedConfig = config.seedDB.options.seedUser; + adminFromSeedConfig = config.seedDB.options.seedAdmin; + return done(); + }); }); @@ -27,6 +57,18 @@ describe('Configuration Tests:', function () { }); }); + it('should have seedDB configuration set for "regular" user', function() { + (typeof userFromSeedConfig).should.not.equal('undefined'); + should.exist(userFromSeedConfig.username); + should.exist(userFromSeedConfig.email); + }); + + it('should have seedDB configuration set for admin user', function() { + (typeof adminFromSeedConfig).should.not.equal('undefined'); + should.exist(adminFromSeedConfig.username); + should.exist(adminFromSeedConfig.email); + }); + it('should not be an admin user to begin with', function(done) { User.find({username: 'admin'}, function(err, users) { should.not.exist(err); @@ -43,67 +85,151 @@ describe('Configuration Tests:', function () { }); }); - it('should set NODE_ENV to production and seedDB turned on so admin account must exist', function(done) { + it('should seed ONLY the admin user account when NODE_ENV is set to "production"', function(done) { // Save original value var nodeEnv = process.env.NODE_ENV; // Set node env ro production environment process.env.NODE_ENV = 'production'; - User.find({username: 'admin'}, function(err, users) { + User.find({username: adminFromSeedConfig.username}, function(err, users) { // There shouldn't be any errors should.not.exist(err); users.should.be.instanceof(Array).and.have.lengthOf(0); - seed.start().then(function() { - User.find({username: 'admin'}, function(err, users) { - should.not.exist(err); - users.should.be.instanceof(Array).and.have.lengthOf(1); + seed + .start({ logResults: false }) + .then(function() { + User.find({username: adminFromSeedConfig.username}, function(err, users) { + should.not.exist(err); + users.should.be.instanceof(Array).and.have.lengthOf(1); - var admin = users.pop(); - admin.username.should.equal('admin'); + var _admin = users.pop(); + _admin.username.should.equal(adminFromSeedConfig.username); - // Restore original NODE_ENV environment variable - process.env.NODE_ENV = nodeEnv; + // Restore original NODE_ENV environment variable + process.env.NODE_ENV = nodeEnv; - User.remove(function(err) { - should.not.exist(err); - return done(); + User.remove(function(err) { + should.not.exist(err); + return done(); + }); }); }); - }); }); }); - it('should set NODE_ENV to test and seedDB turned on so admin, and user accounts must exist', function(done) { + it('should seed admin, and "regular" user accounts when NODE_ENV is set to "test"', function(done) { // Save original value var nodeEnv = process.env.NODE_ENV; // Set node env ro production environment process.env.NODE_ENV = 'test'; - User.find({username: 'admin'}, function(err, users) { + User.find({username: adminFromSeedConfig.username}, function(err, users) { // There shouldn't be any errors should.not.exist(err); users.should.be.instanceof(Array).and.have.lengthOf(0); - seed.start().then(function() { - User.find({username: 'admin'}, function(err, users) { + seed + .start({ logResults: false }) + .then(function() { + User.find({username: adminFromSeedConfig.username}, function(err, users) { + should.not.exist(err); + users.should.be.instanceof(Array).and.have.lengthOf(1); + + var _admin = users.pop(); + _admin.username.should.equal(adminFromSeedConfig.username); + + User.find({username: userFromSeedConfig.username}, function(err, users) { + + should.not.exist(err); + users.should.be.instanceof(Array).and.have.lengthOf(1); + + var _user = users.pop(); + _user.username.should.equal(userFromSeedConfig.username); + + // Restore original NODE_ENV environment variable + process.env.NODE_ENV = nodeEnv; + + User.remove(function(err) { + should.not.exist(err); + return done(); + }); + }); + }); + }); + }); + }); + + it('should seed admin, and "regular" user accounts when NODE_ENV is set to "test" when they already exist', function (done) { + + // Save original value + var nodeEnv = process.env.NODE_ENV; + // Set node env ro production environment + process.env.NODE_ENV = 'test'; + + var _user = new User(userFromSeedConfig); + var _admin = new User(adminFromSeedConfig); + + _admin.save(function (err) { + // There shouldn't be any errors + should.not.exist(err); + _user.save(function (err) { + // There shouldn't be any errors + should.not.exist(err); + + User.find({ username: { $in: [adminFromSeedConfig.username, userFromSeedConfig.username] } }, function (err, users) { + + // There shouldn't be any errors should.not.exist(err); - users.should.be.instanceof(Array).and.have.lengthOf(1); + users.should.be.instanceof(Array).and.have.lengthOf(2); - var admin = users.pop(); - admin.username.should.equal('admin'); + seed + .start({ logResults: false }) + .then(function () { + User.find({ username: { $in: [adminFromSeedConfig.username, userFromSeedConfig.username] } }, function (err, users) { + should.not.exist(err); + users.should.be.instanceof(Array).and.have.lengthOf(2); - User.find({username: 'user'}, function(err, users) { + // Restore original NODE_ENV environment variable + process.env.NODE_ENV = nodeEnv; + User.remove(function (err) { + should.not.exist(err); + return done(); + }); + }); + }); + }); + }); + }); + }); + + it('should ONLY seed admin user account when NODE_ENV is set to "production" with custom admin', function(done) { + + // Save original value + var nodeEnv = process.env.NODE_ENV; + // Set node env ro production environment + process.env.NODE_ENV = 'production'; + + User.find({username: admin1.username}, function(err, users) { + + // There shouldn't be any errors + should.not.exist(err); + users.should.be.instanceof(Array).and.have.lengthOf(0); + + seed + .start({ logResults: false, seedAdmin: admin1 }) + .then(function() { + User.find({username: admin1.username}, function(err, users) { should.not.exist(err); users.should.be.instanceof(Array).and.have.lengthOf(1); - var user = users.pop(); - user.username.should.equal('user'); + var _admin = users.pop(); + _admin.username.should.equal(admin1.username); // Restore original NODE_ENV environment variable process.env.NODE_ENV = nodeEnv; @@ -114,9 +240,134 @@ describe('Configuration Tests:', function () { }); }); }); - }); }); }); + + it('should seed admin, and "regular" user accounts when NODE_ENV is set to "test" with custom options', function(done) { + + // Save original value + var nodeEnv = process.env.NODE_ENV; + // Set node env ro production environment + process.env.NODE_ENV = 'test'; + + User.find({username: admin1.username}, function(err, users) { + + // There shouldn't be any errors + should.not.exist(err); + users.should.be.instanceof(Array).and.have.lengthOf(0); + + seed + .start({ logResults: false, seedAdmin: admin1, seedUser: user1 }) + .then(function() { + User.find({username: admin1.username}, function(err, users) { + should.not.exist(err); + users.should.be.instanceof(Array).and.have.lengthOf(1); + + var _admin = users.pop(); + _admin.username.should.equal(admin1.username); + + User.find({username: user1.username}, function(err, users) { + + should.not.exist(err); + users.should.be.instanceof(Array).and.have.lengthOf(1); + + var _user = users.pop(); + _user.username.should.equal(user1.username); + + // Restore original NODE_ENV environment variable + process.env.NODE_ENV = nodeEnv; + + User.remove(function(err) { + should.not.exist(err); + return done(); + }); + }); + }); + }); + }); + }); + + it('should NOT seed admin user account if it already exists when NODE_ENV is set to "production"', function(done) { + + // Save original value + var nodeEnv = process.env.NODE_ENV; + // Set node env ro production environment + process.env.NODE_ENV = 'production'; + + var _admin = new User(adminFromSeedConfig); + + _admin.save(function(err, user) { + // There shouldn't be any errors + should.not.exist(err); + user.username.should.equal(adminFromSeedConfig.username); + + seed + .start({ logResults: false }) + .then(function () { + // we don't ever expect to make it here but we don't want to timeout + User.remove(function(err) { + should.not.exist(err); + // force this test to fail since we should never be here + should.exist(undefined); + // Restore original NODE_ENV environment variable + process.env.NODE_ENV = nodeEnv; + + return done(); + }); + }) + .catch(function (err) { + should.exist(err); + err.message.should.equal('Failed due to local account already exists: ' + adminFromSeedConfig.username); + + // Restore original NODE_ENV environment variable + process.env.NODE_ENV = nodeEnv; + + User.remove(function(removeErr) { + should.not.exist(removeErr); + + return done(); + }); + }); + }); + }); + + it('should NOT seed "regular" user account if missing email when NODE_ENV set to "test"', function (done) { + + // Save original value + var nodeEnv = process.env.NODE_ENV; + // Set node env ro test environment + process.env.NODE_ENV = 'test'; + + var _user = new User(user1); + _user.email = ''; + + seed + .start({ logResults: false, seedUser: _user }) + .then(function () { + // we don't ever expect to make it here but we don't want to timeout + User.remove(function(err) { + // force this test to fail since we should never be here + should.exist(undefined); + // Restore original NODE_ENV environment variable + process.env.NODE_ENV = nodeEnv; + + return done(); + }); + }) + .catch(function (err) { + should.exist(err); + err.message.should.equal('Failed to add local ' + user1.username); + + // Restore original NODE_ENV environment variable + process.env.NODE_ENV = nodeEnv; + + User.remove(function(removeErr) { + should.not.exist(removeErr); + + return done(); + }); + }); + }); }); describe('Testing Session Secret Configuration', function () { @@ -130,30 +381,27 @@ describe('Configuration Tests:', function () { return done(); }); - it('should accept non-default session secret when running in production', function (done) { + it('should accept non-default session secret when running in production', function () { var conf = { sessionSecret: 'super amazing secret' }; // set env to production for this test process.env.NODE_ENV = 'production'; config.utils.validateSessionSecret(conf, true).should.equal(true); // set env back to test process.env.NODE_ENV = 'test'; - return done(); }); - it('should accept default session secret when running in development', function (done) { + it('should accept default session secret when running in development', function () { var conf = { sessionSecret: 'MEAN' }; // set env to development for this test process.env.NODE_ENV = 'development'; config.utils.validateSessionSecret(conf, true).should.equal(true); // set env back to test process.env.NODE_ENV = 'test'; - return done(); }); - it('should accept default session secret when running in test', function (done) { + it('should accept default session secret when running in test', function () { var conf = { sessionSecret: 'MEAN' }; config.utils.validateSessionSecret(conf, true).should.equal(true); - return done(); }); }); });