mirror of
https://github.com/wassname/talk.git
synced 2026-07-11 21:43:56 +08:00
Fixes #266
This commit is contained in:
+6
-13
@@ -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);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
+10
-9
@@ -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(() => {
|
||||
|
||||
+23
-5
@@ -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',
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
const SettingsService = require('./services/settings');
|
||||
|
||||
module.exports = () => Promise.all([
|
||||
|
||||
// Upsert the settings object.
|
||||
SettingsService.init({
|
||||
moderation: 'POST',
|
||||
wordlist: {
|
||||
banned: [],
|
||||
suspect: []
|
||||
}
|
||||
})
|
||||
]);
|
||||
+10
-8
@@ -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
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
+16
-9
@@ -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) => {
|
||||
|
||||
@@ -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);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user