Skip to content
This repository was archived by the owner on Aug 30, 2021. It is now read-only.

Commit 1c7d742

Browse files
committed
[hotfix] Fixes db seed password bug
Fixes the database seeding bug with the password not passing the owasp test. Adds a UserSchema static method that generates a random passphrase that passes the owasp test. Performed minor refactoring of the database seed configuration to implement the new UserSchema method. Added model test for the UserSchema generateRandomPassphrase static method.
1 parent 0a91e34 commit 1c7d742

File tree

4 files changed

+94
-31
lines changed

4 files changed

+94
-31
lines changed

config/lib/seed.js

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,56 +29,66 @@ var seedAdmin = {
2929
roles: ['user', 'admin']
3030
};
3131

32-
3332
//If production only seed admin if it does not exist
3433
if (process.env.NODE_ENV === 'production') {
3534
//Add Local Admin
36-
User.find({username: 'admin'}, function (err, users) {
35+
User.find({username: seedAdmin.username}, function (err, users) {
3736
if (users.length === 0) {
38-
var password = crypto.randomBytes(64).toString('hex').slice(1, 20);
39-
seedAdmin.password = password;
4037
var user = new User(seedAdmin);
41-
// Then save the user
42-
user.save(function (err) {
43-
if (err) {
44-
console.log('Failed to add local admin');
45-
} else {
46-
console.log(chalk.bold.red('Local admin added with password set to ' + password));
47-
}
48-
});
38+
39+
// generate a random password and save
40+
User.generateRandomPassphrase()
41+
.then(saveUser(user))
42+
.catch(reportError);
43+
4944
} else {
50-
console.log('Admin user exists');
45+
console.log(seedAdmin.username + ' user exists');
5146
}
5247
});
5348
} else {
49+
5450
//Add Local User
55-
User.find({username: 'user'}).remove(function () {
56-
var password = crypto.randomBytes(64).toString('hex').slice(1, 20);
57-
seedUser.password = password;
51+
User.find({username: seedUser.username}).remove(function () {
5852
var user = new User(seedUser);
59-
// Then save the user
60-
user.save(function (err) {
61-
if (err) {
62-
console.log('Failed to add local user');
63-
} else {
64-
console.log(chalk.bold.red('Local user added with password set to ' + password));
65-
}
66-
});
67-
});
6853

54+
// generate a random password and save
55+
User.generateRandomPassphrase()
56+
.then(saveUser(user))
57+
.catch(reportError);
58+
});
6959

7060
//Add Local Admin
71-
User.find({username: 'admin'}).remove(function () {
72-
var password = crypto.randomBytes(64).toString('hex').slice(1, 20);
73-
seedAdmin.password = password;
61+
User.find({username: seedAdmin.username}).remove(function () {
7462
var user = new User(seedAdmin);
63+
64+
// generate a random password and save
65+
User.generateRandomPassphrase()
66+
.then(saveUser(user))
67+
.catch(reportError);
68+
});
69+
}
70+
71+
// save the specified user with the password provided from the resolved promise
72+
function saveUser(user) {
73+
return function (password) {
74+
// set the new password
75+
user.password = password;
76+
7577
// Then save the user
7678
user.save(function (err) {
7779
if (err) {
78-
console.log('Failed to add local admin');
80+
console.log('Database Seeding:\t\t\tFailed to add local ' + user.username);
7981
} else {
80-
console.log(chalk.bold.red('Local admin added with password set to ' + password));
82+
console.log(chalk.bold.red('Database Seeding:\t\t\tLocal ' + user.username + ' added with password set to ' + password));
8183
}
8284
});
83-
});
85+
};
86+
}
87+
88+
// report the error
89+
function reportError(err) {
90+
console.log();
91+
console.log('Database Seeding:\t\t\t Failed to generate random password');
92+
console.log(err);
93+
console.log();
8494
}

modules/users/server/models/user.server.model.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ var mongoose = require('mongoose'),
77
Schema = mongoose.Schema,
88
crypto = require('crypto'),
99
validator = require('validator'),
10+
generatePassword = require('generate-password'),
1011
owasp = require('owasp-password-strength-test');
1112

1213
/**
@@ -166,4 +167,39 @@ UserSchema.statics.findUniqueUsername = function (username, suffix, callback) {
166167
});
167168
};
168169

170+
/**
171+
* Generates a random passphrase that passes the owasp test.
172+
* Returns a promise that resolves with the generated passphrase, or rejects with an error if something goes wrong.
173+
* NOTE: Passphrases are only tested against the required owasp strength tests, and not the optional tests.
174+
*/
175+
UserSchema.statics.generateRandomPassphrase = function () {
176+
return new Promise(function (resolve, reject) {
177+
var password = '';
178+
179+
// iterate until the we have a valid passphrase.
180+
// NOTE: Should rarely iterate more than once, but we need this to ensure no repeating characters are present.
181+
while (password.length < 20) {
182+
// build the random password
183+
password = generatePassword.generate({
184+
length: Math.floor(Math.random() * (20)) + 20, // randomize length between 20 and 40 characters
185+
numbers: true,
186+
symbols: false,
187+
uppercase: true,
188+
excludeSimilarCharacters: true,
189+
});
190+
191+
// check if we need to remove any repeating characters.
192+
password = password.replace(/(.)\1{2,}/g, '');
193+
}
194+
195+
// Send the rejection back if the passphrase fails to pass the strength test
196+
if (owasp.test(password).errors.length) {
197+
reject(new Error('An unexpected problem occured while generating the random passphrase'));
198+
} else {
199+
// resolve with the validated passphrase
200+
resolve(password);
201+
}
202+
});
203+
};
204+
169205
mongoose.model('User', UserSchema);

modules/users/tests/server/user.server.model.tests.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,22 @@ describe('User Model Unit Tests:', function () {
228228
});
229229
});
230230

231+
it('should validate a randomly generated passphrase from the static schema method', function () {
232+
var _user1 = new User(user1);
233+
234+
User.generateRandomPassphrase()
235+
.then(function (password) {
236+
_user1.password = password;
237+
_user1.validate(function (err) {
238+
should.not.exist(err);
239+
});
240+
})
241+
.catch(function (err) {
242+
should.not.exist(err);
243+
});
244+
245+
});
246+
231247
it('should validate when the password is undefined', function () {
232248
var _user1 = new User(user1);
233249
_user1.password = undefined;

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"express": "^4.13.1",
3636
"express-session": "^1.11.3",
3737
"forever": "~0.14.2",
38+
"generate-password": "^1.1.1",
3839
"glob": "^5.0.13",
3940
"grunt": "0.4.5",
4041
"grunt-cli": "~0.1.13",

0 commit comments

Comments
 (0)