diff --git a/bin/cli-serve b/bin/cli-serve index d861d8c5d..0427dcf34 100755 --- a/bin/cli-serve +++ b/bin/cli-serve @@ -4,7 +4,6 @@ const app = require('../app'); const program = require('./commander'); const debug = require('debug')('talk:server'); const http = require('http'); -const init = require('../init'); const scraper = require('../services/scraper'); const mailer = require('../services/mailer'); const kue = require('../services/kue'); @@ -87,19 +86,13 @@ function onListening() { * Start the app. */ function startApp() { - init().then(() => { - /** - * Listen on provided port, on all network interfaces. - */ - server.listen(port); - server.on('error', onError); - server.on('listening', onListening); - }) - .catch((err) => { - console.error(err); - util.shutdown(1); - }); + /** + * Listen on provided port, on all network interfaces. + */ + server.listen(port); + server.on('error', onError); + server.on('listening', onListening); } //============================================================================== diff --git a/bin/cli-setup b/bin/cli-setup index 1c348d212..7645e171d 100755 --- a/bin/cli-setup +++ b/bin/cli-setup @@ -31,20 +31,21 @@ program console.log('We\'ll ask you some questions in order to setup your installation of Talk.\n'); SettingsService - .retrieve() - .catch(() => new SettingModel()) + .init() .then((settings) => { - - if (settings && settings.id) { - console.log('We found preexisting settings in the database, we\'ll use it\'s values as defaults.\n'); - } - return inquirer.prompt([ { type: 'input', name: 'organizationName', message: 'Organization Name', - default: settings.organizationName + default: settings.organizationName, + validate: (input) => { + if (input && input.length > 0) { + return true; + } + + return 'Organization Name is required.'; + } }, { type: 'list', @@ -69,7 +70,7 @@ SettingsService } }); - return SettingsService.update(settings); + return settings.save(); }); }) .then(() => { diff --git a/bin/cli-users b/bin/cli-users index 3ce418927..ab89626eb 100755 --- a/bin/cli-users +++ b/bin/cli-users @@ -12,8 +12,8 @@ const mongoose = require('../services/mongoose'); const util = require('../util'); const Table = require('cli-table'); -const validateRequired = (msg = 'Field is required') => (input) => { - if (input && input.length > 0) { +const validateRequired = (msg = 'Field is required', len = 1) => (input) => { + if (input && input.length >= len) { return true; } @@ -53,18 +53,36 @@ function getUserCreateAnswers(options) { name: 'password', message: 'Password', type: 'password', - validate: validateRequired('Password is required') + filter: (password) => { + return UsersService + .isValidPassword(password) + .catch((err) => { + throw err.message; + }); + } }, { name: 'confirmPassword', message: 'Confirm Password', type: 'password', - validate: validateRequired('Confirm Password is required') + filter: (confirmPassword) => { + return UsersService + .isValidPassword(confirmPassword) + .catch((err) => { + throw err.message; + }); + } }, { name: 'displayName', message: 'Display Name', - validate: validateRequired('Display Name is required') + filter: (displayName) => { + return UsersService + .isValidDisplayName(displayName) + .catch((err) => { + throw err.message; + }); + } }, { name: 'roles', diff --git a/init.js b/init.js deleted file mode 100644 index cd0c0bbc9..000000000 --- a/init.js +++ /dev/null @@ -1,13 +0,0 @@ -const SettingsService = require('./services/settings'); - -module.exports = () => Promise.all([ - - // Upsert the settings object. - SettingsService.init({ - moderation: 'POST', - wordlist: { - banned: [], - suspect: [] - } - }) -]); diff --git a/models/setting.js b/models/setting.js index 26faf1319..25882b3f8 100644 --- a/models/setting.js +++ b/models/setting.js @@ -6,13 +6,6 @@ const MODERATION_OPTIONS = [ 'POST' ]; -const WordlistSchema = new Schema({ - banned: [String], - suspect: [String] -}, { - _id: false -}); - /** * SettingSchema manages application settings that get used on front and backend. * @type {Schema} @@ -48,7 +41,16 @@ const SettingSchema = new Schema({ type: String, default: 'Expired' }, - wordlist: WordlistSchema, + wordlist: { + banned: { + type: Array, + default: [] + }, + suspect: { + type: Array, + default: [] + } + }, charCount: { type: Number, default: 5000 diff --git a/services/settings.js b/services/settings.js index 5d4133fe4..2bb15319d 100644 --- a/services/settings.js +++ b/services/settings.js @@ -44,15 +44,14 @@ module.exports = class SettingsService { /** * This is run once when the app starts to ensure settings are populated. - * @return {Promise} null initialize the global settings object */ - static init(defaults) { + static init(defaults = {}) { + return SettingsService + .retrieve() + .catch(() => { + let settings = new SettingModel(defaults); - // Inject the defaults on top of the passed in defaults to ensure that the new - // settings conform to the required selector. - defaults = Object.assign({}, defaults, selector); - - // Actually update the settings collection. - return SettingsService.update(defaults); + return settings.save(); + }); } }; diff --git a/services/users.js b/services/users.js index 7a888ede1..635e39e47 100644 --- a/services/users.js +++ b/services/users.js @@ -189,6 +189,18 @@ module.exports = class UsersService { return Wordlist.displayNameCheck(displayName); } + static isValidPassword(password) { + if (!password) { + return Promise.reject(errors.ErrMissingPassword); + } + + if (password.length < 8) { + return Promise.reject(errors.ErrPasswordTooShort); + } + + return Promise.resolve(password); + } + /** * Creates the local user with a given email, password, and name. * @param {String} email email of the new user @@ -205,15 +217,10 @@ module.exports = class UsersService { email = email.toLowerCase().trim(); displayName = displayName.toLowerCase().trim(); - if (!password) { - return Promise.reject(errors.ErrMissingPassword); - } - - if (password.length < 8) { - return Promise.reject(errors.ErrPasswordTooShort); - } - - return UsersService.isValidDisplayName(displayName) + return Promise.all([ + UsersService.isValidDisplayName(displayName), + UsersService.isValidPassword(password) + ]) .then(() => { // displayName is valid return new Promise((resolve, reject) => { bcrypt.hash(password, SALT_ROUNDS, (err, hashedPassword) => { diff --git a/test/routes/api/auth/index.js b/test/routes/api/auth/index.js index 4882d859e..1bf8f4992 100644 --- a/test/routes/api/auth/index.js +++ b/test/routes/api/auth/index.js @@ -66,7 +66,7 @@ describe('/api/v1/auth/local', () => { describe('email confirmation enabled', () => { - beforeEach(() => SettingsService.init({requireEmailConfirmation: true})); + beforeEach(() => SettingsService.update({requireEmailConfirmation: true})); describe('#post', () => { it('should not allow a login from a user that is not confirmed', () => { @@ -74,7 +74,7 @@ describe('/api/v1/auth/local', () => { .post('/api/v1/auth/local') .send({email: 'maria@gmail.com', password: 'password!'}) .catch((err) => { - err.response.should.have.status(401); + expect(err).to.have.status(401); return UsersService.createEmailConfirmToken(mockUser.id, mockUser.profiles[0].id); })