mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-05-07 22:06:07 +02:00
merge
This commit is contained in:
@@ -9,7 +9,7 @@ process.on('message', function (msg) {
|
||||
if (msg.type === 'hash') {
|
||||
hashPassword(msg.password, msg.rounds);
|
||||
} else if (msg.type === 'compare') {
|
||||
bcrypt.compare(msg.password, msg.hash, done);
|
||||
bcrypt.compare(String(msg.password || ''), String(msg.hash || ''), done);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ module.exports = function (Categories) {
|
||||
], next);
|
||||
},
|
||||
function (next) {
|
||||
async.each(privileges.privilegeList, function (privilege, next) {
|
||||
async.eachSeries(privileges.privilegeList, function (privilege, next) {
|
||||
groups.destroy('cid:' + cid + ':privileges:' + privilege, next);
|
||||
}, next);
|
||||
},
|
||||
|
||||
@@ -16,22 +16,30 @@ var info = {};
|
||||
infoController.get = function (req, res) {
|
||||
info = {};
|
||||
pubsub.publish('sync:node:info:start');
|
||||
var timeoutMS = 1000;
|
||||
setTimeout(function () {
|
||||
var data = [];
|
||||
Object.keys(info).forEach(function (key) {
|
||||
data.push(info[key]);
|
||||
});
|
||||
data.sort(function (a, b) {
|
||||
if (a.os.hostname < b.os.hostname) {
|
||||
if (a.id < b.id) {
|
||||
return -1;
|
||||
}
|
||||
if (a.os.hostname > b.os.hostname) {
|
||||
if (a.id > b.id) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
res.render('admin/development/info', { info: data, infoJSON: JSON.stringify(data, null, 4), host: os.hostname(), port: nconf.get('port') });
|
||||
}, 500);
|
||||
res.render('admin/development/info', {
|
||||
info: data,
|
||||
infoJSON: JSON.stringify(data, null, 4),
|
||||
host: os.hostname(),
|
||||
port: nconf.get('port'),
|
||||
nodeCount: data.length,
|
||||
timeout: timeoutMS,
|
||||
});
|
||||
}, timeoutMS);
|
||||
};
|
||||
|
||||
pubsub.on('sync:node:info:start', function () {
|
||||
@@ -39,7 +47,8 @@ pubsub.on('sync:node:info:start', function () {
|
||||
if (err) {
|
||||
return winston.error(err);
|
||||
}
|
||||
pubsub.publish('sync:node:info:end', { data: data, id: os.hostname() + ':' + nconf.get('port') });
|
||||
data.id = os.hostname() + ':' + nconf.get('port');
|
||||
pubsub.publish('sync:node:info:end', { data: data, id: data.id });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ languagesController.get = function (req, res, next) {
|
||||
|
||||
res.render('admin/general/languages', {
|
||||
languages: languages,
|
||||
autoDetectLang: parseInt(meta.config.autoDetectLang, 10) === 1,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ var path = require('path');
|
||||
var async = require('async');
|
||||
var nconf = require('nconf');
|
||||
var winston = require('winston');
|
||||
var mime = require('mime');
|
||||
|
||||
var meta = require('../../meta');
|
||||
var file = require('../../file');
|
||||
@@ -102,6 +103,11 @@ uploadsController.uploadLogo = function (req, res, next) {
|
||||
uploadsController.uploadSound = function (req, res, next) {
|
||||
var uploadedFile = req.files.files[0];
|
||||
|
||||
var mimeType = mime.lookup(uploadedFile.name);
|
||||
if (!/^audio\//.test(mimeType)) {
|
||||
return next(Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
file.saveFileToLocal(uploadedFile.name, 'sounds', uploadedFile.path, function (err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
|
||||
@@ -17,7 +17,7 @@ var translator = require('../translator');
|
||||
|
||||
var sockets = require('../socket.io');
|
||||
|
||||
var authenticationController = {};
|
||||
var authenticationController = module.exports;
|
||||
|
||||
authenticationController.register = function (req, res) {
|
||||
var registrationType = meta.config.registrationType || 'normal';
|
||||
@@ -345,21 +345,21 @@ authenticationController.localLogin = function (req, username, password, next) {
|
||||
var uid;
|
||||
var userData = {};
|
||||
|
||||
if (!password || !utils.isPasswordValid(password)) {
|
||||
return next(new Error('[[error:invalid-password]]'));
|
||||
}
|
||||
|
||||
if (password.length > 4096) {
|
||||
return next(new Error('[[error:password-too-long]]'));
|
||||
}
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
user.isPasswordValid(password, next);
|
||||
},
|
||||
function (next) {
|
||||
user.getUidByUserslug(userslug, next);
|
||||
},
|
||||
function (_uid, next) {
|
||||
if (!_uid) {
|
||||
return next(new Error('[[error:no-user]]'));
|
||||
}
|
||||
uid = _uid;
|
||||
user.auth.logAttempt(uid, req.ip, next);
|
||||
},
|
||||
function (next) {
|
||||
|
||||
async.parallel({
|
||||
userData: function (next) {
|
||||
db.getObjectFields('user:' + uid, ['password', 'passwordExpiry'], next);
|
||||
@@ -381,19 +381,18 @@ authenticationController.localLogin = function (req, username, password, next) {
|
||||
return next(new Error('[[error:local-login-disabled]]'));
|
||||
}
|
||||
|
||||
if (!userData || !userData.password) {
|
||||
return next(new Error('[[error:invalid-user-data]]'));
|
||||
}
|
||||
|
||||
if (result.banned) {
|
||||
return banUser(uid, next);
|
||||
}
|
||||
|
||||
user.auth.logAttempt(uid, req.ip, next);
|
||||
},
|
||||
function (next) {
|
||||
Password.compare(password, userData.password, next);
|
||||
},
|
||||
function (passwordMatch, next) {
|
||||
if (!passwordMatch) {
|
||||
return next(new Error('[[error:invalid-password]]'));
|
||||
return next(new Error('[[error:invalid-login-credentials]]'));
|
||||
}
|
||||
user.auth.clearLoginAttempts(uid);
|
||||
next(null, userData, '[[success:authentication-successful]]');
|
||||
@@ -447,5 +446,3 @@ function banUser(uid, next) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = authenticationController;
|
||||
|
||||
@@ -4,6 +4,7 @@ var async = require('async');
|
||||
var plugins = require('../plugins');
|
||||
var utils = require('../utils');
|
||||
var db = require('./../database');
|
||||
var batch = require('../batch');
|
||||
|
||||
module.exports = function (Groups) {
|
||||
Groups.destroy = function (groupName, callback) {
|
||||
@@ -29,14 +30,14 @@ module.exports = function (Groups) {
|
||||
async.apply(db.delete, 'group:' + groupName + ':member:pids'),
|
||||
async.apply(db.deleteObjectField, 'groupslug:groupname', utils.slugify(groupName)),
|
||||
function (next) {
|
||||
db.getSortedSetRange('groups:createtime', 0, -1, function (err, groups) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
async.each(groups, function (group, next) {
|
||||
db.sortedSetRemove('group:' + group + ':members', groupName, next);
|
||||
}, next);
|
||||
});
|
||||
batch.processSortedSet('groups:createtime', function (groupNames, next) {
|
||||
var keys = groupNames.map(function (group) {
|
||||
return 'group:' + group + ':members';
|
||||
});
|
||||
db.sortedSetsRemove(keys, groupName, next);
|
||||
}, {
|
||||
batch: 500,
|
||||
}, next);
|
||||
},
|
||||
], function (err) {
|
||||
if (err) {
|
||||
|
||||
@@ -4,7 +4,7 @@ var fs = require('fs');
|
||||
var path = require('path');
|
||||
var async = require('async');
|
||||
|
||||
var Languages = {};
|
||||
var Languages = module.exports;
|
||||
var languagesPath = path.join(__dirname, '../build/public/language');
|
||||
|
||||
Languages.init = function (next) {
|
||||
@@ -27,10 +27,13 @@ Languages.get = function (language, namespace, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
Languages.list = function (callback) {
|
||||
var languages = [];
|
||||
var codeCache = null;
|
||||
Languages.listCodes = function (callback) {
|
||||
if (codeCache && codeCache.length) {
|
||||
return callback(null, codeCache);
|
||||
}
|
||||
|
||||
fs.readdir(languagesPath, function (err, files) {
|
||||
fs.readFile(path.join(languagesPath, 'metadata.json'), function (err, buffer) {
|
||||
if (err && err.code === 'ENOENT') {
|
||||
return callback(null, []);
|
||||
}
|
||||
@@ -38,43 +41,59 @@ Languages.list = function (callback) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
async.each(files, function (folder, next) {
|
||||
fs.stat(path.join(languagesPath, folder), function (err, stat) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
var parsed;
|
||||
try {
|
||||
parsed = JSON.parse(buffer.toString());
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
if (!stat.isDirectory()) {
|
||||
return next();
|
||||
}
|
||||
|
||||
var configPath = path.join(languagesPath, folder, 'language.json');
|
||||
|
||||
fs.readFile(configPath, function (err, buffer) {
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
return next(err);
|
||||
}
|
||||
if (buffer) {
|
||||
var lang = JSON.parse(buffer.toString());
|
||||
if (lang.name && lang.code && lang.dir) {
|
||||
languages.push(lang);
|
||||
}
|
||||
}
|
||||
next();
|
||||
});
|
||||
});
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
// Sort alphabetically
|
||||
languages = languages.sort(function (a, b) {
|
||||
return a.code > b.code ? 1 : -1;
|
||||
});
|
||||
|
||||
callback(err, languages);
|
||||
});
|
||||
var langs = parsed.languages;
|
||||
codeCache = langs;
|
||||
callback(null, langs);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = Languages;
|
||||
var listCache = null;
|
||||
Languages.list = function (callback) {
|
||||
if (listCache && listCache.length) {
|
||||
return callback(null, listCache);
|
||||
}
|
||||
|
||||
Languages.listCodes(function (err, codes) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
async.map(codes, function (folder, next) {
|
||||
var configPath = path.join(languagesPath, folder, 'language.json');
|
||||
|
||||
fs.readFile(configPath, function (err, buffer) {
|
||||
if (err && err.code === 'ENOENT') {
|
||||
return next();
|
||||
}
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
try {
|
||||
var lang = JSON.parse(buffer.toString());
|
||||
next(null, lang);
|
||||
} catch (e) {
|
||||
next(e);
|
||||
}
|
||||
});
|
||||
}, function (err, languages) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// filter out invalid ones
|
||||
languages = languages.filter(function (lang) {
|
||||
return lang && lang.code && lang.name && lang.dir;
|
||||
});
|
||||
|
||||
listCache = languages;
|
||||
callback(null, languages);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -78,6 +78,7 @@ module.exports = function (Meta) {
|
||||
'public/src/modules/helpers.js',
|
||||
'public/src/modules/string.js',
|
||||
'public/src/modules/flags.js',
|
||||
'public/src/modules/storage.js',
|
||||
],
|
||||
|
||||
// modules listed below are built (/src/modules) so they can be defined anonymously
|
||||
|
||||
@@ -100,6 +100,25 @@ function getTranslationTree(callback) {
|
||||
});
|
||||
},
|
||||
|
||||
// save a list of languages to `${buildLanguagesPath}/metadata.json`
|
||||
// avoids readdirs later on
|
||||
function (ref, next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
mkdirp(buildLanguagesPath, next);
|
||||
},
|
||||
function (x, next) {
|
||||
fs.writeFile(path.join(buildLanguagesPath, 'metadata.json'), JSON.stringify({
|
||||
languages: ref.languages.sort(),
|
||||
namespaces: ref.namespaces.sort(),
|
||||
}), next);
|
||||
},
|
||||
function (next) {
|
||||
next(null, ref);
|
||||
},
|
||||
], next);
|
||||
},
|
||||
|
||||
// for each language and namespace combination,
|
||||
// run through core and all plugins to generate
|
||||
// a full translation hash
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var nconf = require('nconf');
|
||||
var fs = require('fs');
|
||||
var winston = require('winston');
|
||||
|
||||
module.exports = function (Meta) {
|
||||
Meta.logs = {
|
||||
path: path.join(nconf.get('base_dir'), 'logs', 'output.log'),
|
||||
path: path.join(__dirname, '..', '..', 'logs', 'output.log'),
|
||||
};
|
||||
|
||||
Meta.logs.get = function (callback) {
|
||||
|
||||
@@ -41,6 +41,7 @@ module.exports = function (middleware) {
|
||||
|
||||
middleware.renderHeader = function (req, res, data, callback) {
|
||||
var registrationType = meta.config.registrationType || 'normal';
|
||||
res.locals.config = res.locals.config || {};
|
||||
var templateValues = {
|
||||
title: meta.config.title || '',
|
||||
description: meta.config.description || '',
|
||||
@@ -133,6 +134,7 @@ module.exports = function (middleware) {
|
||||
templateValues.customJS = templateValues.useCustomJS ? meta.config.customJS : '';
|
||||
templateValues.maintenanceHeader = parseInt(meta.config.maintenanceMode, 10) === 1 && !results.isAdmin;
|
||||
templateValues.defaultLang = meta.config.defaultLang || 'en-GB';
|
||||
templateValues.userLang = res.locals.config.userLang;
|
||||
templateValues.privateUserInfo = parseInt(meta.config.privateUserInfo, 10) === 1;
|
||||
templateValues.privateTagListing = parseInt(meta.config.privateTagListing, 10) === 1;
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
};
|
||||
|
||||
module.compare = function (password, hash, callback) {
|
||||
if (!hash || !password) {
|
||||
return setImmediate(callback, null, false);
|
||||
}
|
||||
forkChild({ type: 'compare', password: password, hash: hash }, callback);
|
||||
};
|
||||
|
||||
|
||||
@@ -138,39 +138,46 @@ module.exports = function (SocketPosts) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
var postData;
|
||||
var topicData;
|
||||
var isMainAndLast = false;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
isMainAndLastPost(data.pid, next);
|
||||
},
|
||||
function (results, next) {
|
||||
if (results.isMain && !results.isLast) {
|
||||
return callback(new Error('[[error:cant-purge-main-post]]'));
|
||||
return next(new Error('[[error:cant-purge-main-post]]'));
|
||||
}
|
||||
if (results.isMain && results.isLast) {
|
||||
return deleteTopicOf(data.pid, socket, next);
|
||||
}
|
||||
setImmediate(next);
|
||||
isMainAndLast = results.isMain && results.isLast;
|
||||
|
||||
posts.getPostFields(data.pid, ['toPid', 'tid'], next);
|
||||
},
|
||||
function (next) {
|
||||
posts.getPostField(data.pid, 'toPid', next);
|
||||
},
|
||||
function (toPid, next) {
|
||||
postData = { pid: data.pid, toPid: toPid };
|
||||
function (_postData, next) {
|
||||
postData = _postData;
|
||||
postData.pid = data.pid;
|
||||
posts.tools.purge(socket.uid, data.pid, next);
|
||||
},
|
||||
function (next) {
|
||||
websockets.in('topic_' + data.tid).emit('event:post_purged', postData);
|
||||
topics.getTopicField(data.tid, 'title', next);
|
||||
topics.getTopicFields(data.tid, ['title', 'cid'], next);
|
||||
},
|
||||
function (title, next) {
|
||||
function (_topicData, next) {
|
||||
topicData = _topicData;
|
||||
events.log({
|
||||
type: 'post-purge',
|
||||
uid: socket.uid,
|
||||
pid: data.pid,
|
||||
ip: socket.ip,
|
||||
title: String(title),
|
||||
title: String(topicData.title),
|
||||
}, next);
|
||||
},
|
||||
function (next) {
|
||||
if (isMainAndLast) {
|
||||
socketTopics.doTopicAction('purge', 'event:topic_purged', socket, { tids: [postData.tid], cid: topicData.cid }, next);
|
||||
} else {
|
||||
setImmediate(next);
|
||||
}
|
||||
},
|
||||
], callback);
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ module.exports = function (User) {
|
||||
User.auth = {};
|
||||
|
||||
User.auth.logAttempt = function (uid, ip, callback) {
|
||||
if (!parseInt(uid, 10)) {
|
||||
return setImmediate(callback);
|
||||
}
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.exists('lockout:' + uid, next);
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<span>[[admin/development/info:nodes-responded, {nodeCount}, {timeOut}]]</span>
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
@@ -16,6 +16,17 @@
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="row">
|
||||
<div class="form-group col-sm-6">
|
||||
<div class="checkbox">
|
||||
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||
<input class="mdl-switch__input" type="checkbox" data-field="autoDetectLang" <!-- IF autoDetectLang -->checked<!-- ENDIF autoDetectLang -->/>
|
||||
<span class="mdl-switch__label">[[admin/general/languages:auto-detect]]</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -55,13 +55,16 @@ module.exports.listen = function (callback) {
|
||||
callback = callback || function () { };
|
||||
emailer.registerApp(app);
|
||||
|
||||
setupExpressApp(app);
|
||||
|
||||
helpers.register();
|
||||
|
||||
logger.init(app);
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
setupExpressApp(app, next);
|
||||
},
|
||||
function (next) {
|
||||
helpers.register();
|
||||
|
||||
logger.init(app);
|
||||
next();
|
||||
},
|
||||
initializeNodeBB,
|
||||
function (next) {
|
||||
winston.info('NodeBB Ready');
|
||||
@@ -110,7 +113,7 @@ function initializeNodeBB(callback) {
|
||||
});
|
||||
}
|
||||
|
||||
function setupExpressApp(app) {
|
||||
function setupExpressApp(app, callback) {
|
||||
var middleware = require('./middleware');
|
||||
|
||||
var relativePath = nconf.get('relative_path');
|
||||
@@ -158,6 +161,8 @@ function setupExpressApp(app) {
|
||||
var toobusy = require('toobusy-js');
|
||||
toobusy.maxLag(parseInt(meta.config.eventLoopLagThreshold, 10) || 100);
|
||||
toobusy.interval(parseInt(meta.config.eventLoopInterval, 10) || 500);
|
||||
|
||||
setupAutoLocale(app, callback);
|
||||
}
|
||||
|
||||
function ping(req, res) {
|
||||
@@ -195,6 +200,35 @@ function setupCookie() {
|
||||
return cookie;
|
||||
}
|
||||
|
||||
function setupAutoLocale(app, callback) {
|
||||
languages.listCodes(function (err, codes) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var defaultLang = meta.config.defaultLang || 'en-GB';
|
||||
|
||||
var langs = [defaultLang].concat(codes).filter(function (el, i, arr) {
|
||||
return arr.indexOf(el) === i;
|
||||
});
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
if (parseInt(req.uid, 10) > 0 || parseInt(meta.config.autoDetectLang, 10) !== 1) {
|
||||
return next();
|
||||
}
|
||||
|
||||
var lang = req.acceptsLanguages(langs);
|
||||
if (!lang) {
|
||||
return next();
|
||||
}
|
||||
req.query.lang = lang;
|
||||
next();
|
||||
});
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function listen(callback) {
|
||||
callback = callback || function () { };
|
||||
var port = parseInt(nconf.get('port'), 10);
|
||||
|
||||
Reference in New Issue
Block a user