mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-06 22:15:48 +01:00
merging master to pull baris' latest fixes
This commit is contained in:
21
app.js
21
app.js
@@ -19,7 +19,8 @@
|
|||||||
var fs = require('fs'),
|
var fs = require('fs'),
|
||||||
winston = require('winston'),
|
winston = require('winston'),
|
||||||
pkg = require('./package.json'),
|
pkg = require('./package.json'),
|
||||||
url = require('url');
|
url = require('url'),
|
||||||
|
meta = require('./src/meta.js');
|
||||||
|
|
||||||
nconf = require('nconf');
|
nconf = require('nconf');
|
||||||
// Runtime environment
|
// Runtime environment
|
||||||
@@ -49,28 +50,22 @@ winston.info('This program comes with ABSOLUTELY NO WARRANTY.');
|
|||||||
winston.info('This is free software, and you are welcome to redistribute it under certain conditions.');
|
winston.info('This is free software, and you are welcome to redistribute it under certain conditions.');
|
||||||
winston.info('===');
|
winston.info('===');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(nconf.get('upgrade')) {
|
if(nconf.get('upgrade')) {
|
||||||
|
meta.configs.init(function() {
|
||||||
require('./src/upgrade').upgrade();
|
require('./src/upgrade').upgrade();
|
||||||
|
});
|
||||||
} else if (!nconf.get('setup') && nconf.get('base_url')) {
|
} else if (!nconf.get('setup') && nconf.get('base_url')) {
|
||||||
nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path') + '/');
|
nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path') + '/');
|
||||||
nconf.set('upload_url', nconf.get('url') + 'uploads/');
|
nconf.set('upload_url', nconf.get('url') + 'uploads/');
|
||||||
|
|
||||||
|
|
||||||
winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
||||||
winston.info('Base Configuration OK.');
|
winston.info('Base Configuration OK.');
|
||||||
|
|
||||||
// TODO: Replace this with nconf-redis
|
meta.configs.init(function() {
|
||||||
var meta = require('./src/meta.js');
|
|
||||||
global.config = {};
|
|
||||||
meta.config.get(function(config) {
|
|
||||||
for(c in config) {
|
|
||||||
if (config.hasOwnProperty(c)) {
|
|
||||||
global.config[c] = config[c];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var categories = require('./src/categories.js'),
|
var categories = require('./src/categories.js'),
|
||||||
RDB = require('./src/redis.js'),
|
|
||||||
templates = require('./public/src/templates.js'),
|
templates = require('./public/src/templates.js'),
|
||||||
webserver = require('./src/webserver.js'),
|
webserver = require('./src/webserver.js'),
|
||||||
websockets = require('./src/websockets.js'),
|
websockets = require('./src/websockets.js'),
|
||||||
@@ -80,6 +75,7 @@ if(nconf.get('upgrade')) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DEVELOPMENT = true;
|
DEVELOPMENT = true;
|
||||||
|
RDB = require('./src/redis.js');
|
||||||
|
|
||||||
global.configuration = {};
|
global.configuration = {};
|
||||||
global.templates = {};
|
global.templates = {};
|
||||||
@@ -127,6 +123,7 @@ if(nconf.get('upgrade')) {
|
|||||||
setup_categories();
|
setup_categories();
|
||||||
}(global.configuration));
|
}(global.configuration));
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// New install, ask setup questions
|
// New install, ask setup questions
|
||||||
if (nconf.get('setup')) winston.info('NodeBB Setup Triggered via Command Line');
|
if (nconf.get('setup')) winston.info('NodeBB Setup Triggered via Command Line');
|
||||||
|
|||||||
@@ -34,7 +34,8 @@
|
|||||||
"cheerio": "~0.12.0",
|
"cheerio": "~0.12.0",
|
||||||
"request": "~2.25.0",
|
"request": "~2.25.0",
|
||||||
"reds": "~0.2.4",
|
"reds": "~0.2.4",
|
||||||
"winston": "~0.7.2"
|
"winston": "~0.7.2",
|
||||||
|
"nodebb-plugin-mentions": "~0.1.0"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/designcreateplay/NodeBB/issues"
|
"url": "https://github.com/designcreateplay/NodeBB/issues"
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ footer.footer {
|
|||||||
color: #333;
|
color: #333;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
overflow:hidden;
|
||||||
p {
|
p {
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,10 +77,10 @@ var ajaxify = {};
|
|||||||
app.scrollToPost(hash.substr(1));
|
app.scrollToPost(hash.substr(1));
|
||||||
});
|
});
|
||||||
|
|
||||||
}, url, template);
|
|
||||||
|
|
||||||
utils.refreshTitle(url);
|
utils.refreshTitle(url);
|
||||||
|
|
||||||
|
}, url, template);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,9 +94,12 @@ var ajaxify = {};
|
|||||||
|
|
||||||
// Enhancing all anchors to ajaxify...
|
// Enhancing all anchors to ajaxify...
|
||||||
$(document.body).on('click', 'a', function(e) {
|
$(document.body).on('click', 'a', function(e) {
|
||||||
if (this.href == window.location.href + "#") return;
|
|
||||||
if(this.href.slice(-1) === "#") return;
|
|
||||||
|
|
||||||
|
function hrefEmpty(href) {
|
||||||
|
return href == 'javascript:;' || href == window.location.href + "#" || href.slice(-1) === "#";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hrefEmpty(this.href)) return;
|
||||||
|
|
||||||
var url = this.href.replace(rootUrl +'/', '');
|
var url = this.href.replace(rootUrl +'/', '');
|
||||||
|
|
||||||
|
|||||||
@@ -218,7 +218,6 @@ var socket,
|
|||||||
|
|
||||||
app.current_room = null;
|
app.current_room = null;
|
||||||
app.enter_room = function(room) {
|
app.enter_room = function(room) {
|
||||||
|
|
||||||
if(socket) {
|
if(socket) {
|
||||||
if (app.current_room === room)
|
if (app.current_room === room)
|
||||||
return;
|
return;
|
||||||
@@ -333,28 +332,47 @@ var socket,
|
|||||||
app.infiniteLoaderActive = false;
|
app.infiniteLoaderActive = false;
|
||||||
if(data.posts.length) {
|
if(data.posts.length) {
|
||||||
app.createNewPosts(data);
|
app.createNewPosts(data);
|
||||||
if(callback)
|
|
||||||
callback();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(callback)
|
||||||
|
callback(data.posts);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
app.scrollToPost = function(pid) {
|
app.scrollToPost = function(pid) {
|
||||||
|
|
||||||
if(!pid)
|
if(!pid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var container = $(document.body),
|
var container = $(document.body),
|
||||||
scrollTo = $('#post_anchor_' + pid),
|
scrollTo = $('#post_anchor_' + pid),
|
||||||
tid = $('#post-container').attr('data-tid');
|
tid = $('#post-container').attr('data-tid');
|
||||||
|
|
||||||
while(!scrollTo.length) {
|
function animateScroll() {
|
||||||
app.loadMorePosts(tid, function() {
|
$('body,html').animate({
|
||||||
scrollTo = $('#post_anchor_' + pid);
|
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
container.animate({
|
if(!scrollTo.length && tid) {
|
||||||
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height()
|
|
||||||
|
var intervalID = setInterval(function() {
|
||||||
|
app.loadMorePosts(tid, function(posts) {
|
||||||
|
scrollTo = $('#post_anchor_' + pid);
|
||||||
|
|
||||||
|
if(tid && scrollTo.length) {
|
||||||
|
animateScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!posts.length || scrollTo.length)
|
||||||
|
clearInterval(intervalID);
|
||||||
});
|
});
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
} else if(tid) {
|
||||||
|
animateScroll();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery('document').ready(function() {
|
jQuery('document').ready(function() {
|
||||||
|
|||||||
@@ -26,17 +26,12 @@
|
|||||||
if (thread_state.pinned === '1') set_pinned_state(true);
|
if (thread_state.pinned === '1') set_pinned_state(true);
|
||||||
|
|
||||||
if (expose_tools === '1') {
|
if (expose_tools === '1') {
|
||||||
var deleteThreadEl = document.getElementById('delete_thread'),
|
var moveThreadModal = $('#move_thread_modal');
|
||||||
lockThreadEl = document.getElementById('lock_thread'),
|
|
||||||
pinThreadEl = document.getElementById('pin_thread'),
|
|
||||||
moveThreadEl = document.getElementById('move_thread'),
|
|
||||||
moveThreadModal = $('#move_thread_modal');
|
|
||||||
|
|
||||||
adminTools.style.visibility = 'inherit';
|
adminTools.style.visibility = 'inherit';
|
||||||
|
|
||||||
// Add events to the thread tools
|
// Add events to the thread tools
|
||||||
deleteThreadEl.addEventListener('click', function(e) {
|
$('#delete_thread').on('click', function(e) {
|
||||||
e.preventDefault();
|
|
||||||
if (thread_state.deleted !== '1') {
|
if (thread_state.deleted !== '1') {
|
||||||
bootbox.confirm('Are you sure you want to delete this thread?', function(confirm) {
|
bootbox.confirm('Are you sure you want to delete this thread?', function(confirm) {
|
||||||
if (confirm) socket.emit('api:topic.delete', { tid: tid });
|
if (confirm) socket.emit('api:topic.delete', { tid: tid });
|
||||||
@@ -46,30 +41,31 @@
|
|||||||
if (confirm) socket.emit('api:topic.restore', { tid: tid });
|
if (confirm) socket.emit('api:topic.restore', { tid: tid });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, false);
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
lockThreadEl.addEventListener('click', function(e) {
|
$('#lock_thread').on('click', function(e) {
|
||||||
e.preventDefault();
|
|
||||||
if (thread_state.locked !== '1') {
|
if (thread_state.locked !== '1') {
|
||||||
socket.emit('api:topic.lock', { tid: tid });
|
socket.emit('api:topic.lock', { tid: tid });
|
||||||
} else {
|
} else {
|
||||||
socket.emit('api:topic.unlock', { tid: tid });
|
socket.emit('api:topic.unlock', { tid: tid });
|
||||||
}
|
}
|
||||||
}, false);
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
pinThreadEl.addEventListener('click', function(e) {
|
$('#pin_thread').on('click', function(e) {
|
||||||
e.preventDefault();
|
|
||||||
if (thread_state.pinned !== '1') {
|
if (thread_state.pinned !== '1') {
|
||||||
socket.emit('api:topic.pin', { tid: tid });
|
socket.emit('api:topic.pin', { tid: tid });
|
||||||
} else {
|
} else {
|
||||||
socket.emit('api:topic.unpin', { tid: tid });
|
socket.emit('api:topic.unpin', { tid: tid });
|
||||||
}
|
}
|
||||||
}, false);
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
moveThreadEl.addEventListener('click', function(e) {
|
$('#move_thread').on('click', function(e) {
|
||||||
e.preventDefault();
|
|
||||||
moveThreadModal.modal('show');
|
moveThreadModal.modal('show');
|
||||||
}, false);
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
moveThreadModal.on('shown', function() {
|
moveThreadModal.on('shown', function() {
|
||||||
var loadingEl = document.getElementById('categories-loading');
|
var loadingEl = document.getElementById('categories-loading');
|
||||||
|
|||||||
@@ -153,6 +153,11 @@
|
|||||||
.addClass('badge-inverse')
|
.addClass('badge-inverse')
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
isRelativeUrl: function(url) {
|
||||||
|
var firstChar = url.slice(0, 1);
|
||||||
|
return (firstChar === '.' || firstChar === '/');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
</script>
|
</script>
|
||||||
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
|
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
|
||||||
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
|
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
|
||||||
|
<script src="{relative_path}/src/utils.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/style.css" />
|
<link rel="stylesheet" type="text/css" href="{relative_path}/css/style.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/admin.css" />
|
<link rel="stylesheet" type="text/css" href="{relative_path}/css/admin.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -85,10 +85,10 @@ var async = require('async'),
|
|||||||
server_conf.base_url = protocol + '//' + host;
|
server_conf.base_url = protocol + '//' + host;
|
||||||
server_conf.relative_path = relative_path;
|
server_conf.relative_path = relative_path;
|
||||||
|
|
||||||
meta.config.set('postDelay', 10000);
|
meta.configs.set('postDelay', 10000);
|
||||||
meta.config.set('minimumPostLength', 8);
|
meta.configs.set('minimumPostLength', 8);
|
||||||
meta.config.set('minimumTitleLength', 3);
|
meta.configs.set('minimumTitleLength', 3);
|
||||||
meta.config.set('imgurClientID', '');
|
meta.configs.set('imgurClientID', '');
|
||||||
|
|
||||||
install.save(server_conf, client_conf, callback);
|
install.save(server_conf, client_conf, callback);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,13 +25,17 @@ var user = require('./user.js'),
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
user.getUserFields(uid, ['password', 'banned'], function(userData) {
|
user.getUserFields(uid, ['password', 'banned'], function(err, userData) {
|
||||||
|
if(err)
|
||||||
|
return next(err);
|
||||||
|
|
||||||
if(userData.banned && userData.banned === '1') {
|
if(userData.banned && userData.banned === '1') {
|
||||||
return next({
|
return next({
|
||||||
status: "error",
|
status: "error",
|
||||||
message: "user-banned"
|
message: "user-banned"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bcrypt.compare(password, userData.password, function(err, res) {
|
bcrypt.compare(password, userData.password, function(err, res) {
|
||||||
if(err) {
|
if(err) {
|
||||||
winston.err(err);
|
winston.err(err);
|
||||||
|
|||||||
15
src/meta.js
15
src/meta.js
@@ -5,7 +5,14 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
fs = require('fs');
|
fs = require('fs');
|
||||||
|
|
||||||
(function(Meta) {
|
(function(Meta) {
|
||||||
Meta.config = {
|
|
||||||
|
Meta.configs = {
|
||||||
|
init: function(callback) {
|
||||||
|
Meta.configs.get(function(config) {
|
||||||
|
Meta.config = config;
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
},
|
||||||
get: function(callback) {
|
get: function(callback) {
|
||||||
RDB.hgetall('config', function(err, config) {
|
RDB.hgetall('config', function(err, config) {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
@@ -80,8 +87,8 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
}, function(err, values) {
|
}, function(err, values) {
|
||||||
var title;
|
var title;
|
||||||
|
|
||||||
if (err) title = global.config.title || 'NodeBB';
|
if (err) title = Meta.config.title || 'NodeBB';
|
||||||
else title = (values.title ? values.title + ' | ' : '') + (global.config.title || 'NodeBB');
|
else title = (values.title ? values.title + ' | ' : '') + (Meta.config.title || 'NodeBB');
|
||||||
|
|
||||||
callback(null, title, values.notifCount);
|
callback(null, title, values.notifCount);
|
||||||
});
|
});
|
||||||
@@ -110,4 +117,6 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
} else callback(null);
|
} else callback(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}(exports));
|
}(exports));
|
||||||
|
|
||||||
|
|||||||
@@ -20,28 +20,14 @@ var fs = require('fs'),
|
|||||||
function(plugins, next) {
|
function(plugins, next) {
|
||||||
async.each(plugins, function(plugin) {
|
async.each(plugins, function(plugin) {
|
||||||
// TODO: Update this check to also check node_modules
|
// TODO: Update this check to also check node_modules
|
||||||
var pluginPath = path.join(__dirname, '../plugins/', plugin);
|
var pluginPath = path.join(__dirname, '../plugins/', plugin),
|
||||||
fs.exists(pluginPath, function(exists) {
|
modulePath = path.join(__dirname, '../node_modules/', plugin);
|
||||||
if (exists) {
|
if (fs.existsSync(pluginPath)) _self.loadPlugin(pluginPath, next);
|
||||||
fs.readFile(path.join(pluginPath, 'plugin.json'), function(err, data) {
|
else if (fs.existsSync(modulePath)) _self.loadPlugin(modulePath, next);
|
||||||
if (err) return next(err);
|
else {
|
||||||
|
|
||||||
var pluginData = JSON.parse(data);
|
|
||||||
_self.libraries[pluginData.id] = require(path.join(pluginPath, pluginData.library));
|
|
||||||
if (pluginData.hooks) {
|
|
||||||
for(var x=0,numHooks=pluginData.hooks.length;x<numHooks;x++) {
|
|
||||||
_self.registerHook(pluginData.id, pluginData.hooks[x]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (global.env === 'development') winston.info('[plugins] Loaded plugin: ' + pluginData.id);
|
|
||||||
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (global.env === 'development') winston.info('[plugins] Plugin \'' + plugin + '\' not found');
|
if (global.env === 'development') winston.info('[plugins] Plugin \'' + plugin + '\' not found');
|
||||||
next(); // Ignore this plugin silently
|
next(); // Ignore this plugin silently
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}, next);
|
}, next);
|
||||||
}
|
}
|
||||||
], function(err) {
|
], function(err) {
|
||||||
@@ -54,6 +40,24 @@ var fs = require('fs'),
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
initialized: false,
|
initialized: false,
|
||||||
|
loadPlugin: function(pluginPath, callback) {
|
||||||
|
var _self = this;
|
||||||
|
|
||||||
|
fs.readFile(path.join(pluginPath, 'plugin.json'), function(err, data) {
|
||||||
|
if (err) return callback(err);
|
||||||
|
|
||||||
|
var pluginData = JSON.parse(data);
|
||||||
|
_self.libraries[pluginData.id] = require(path.join(pluginPath, pluginData.library));
|
||||||
|
if (pluginData.hooks) {
|
||||||
|
for(var x=0,numHooks=pluginData.hooks.length;x<numHooks;x++) {
|
||||||
|
_self.registerHook(pluginData.id, pluginData.hooks[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (global.env === 'development') winston.info('[plugins] Loaded plugin: ' + pluginData.id);
|
||||||
|
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
},
|
||||||
registerHook: function(id, data) {
|
registerHook: function(id, data) {
|
||||||
/*
|
/*
|
||||||
`data` is an object consisting of (* is required):
|
`data` is an object consisting of (* is required):
|
||||||
@@ -66,7 +70,7 @@ var fs = require('fs'),
|
|||||||
|
|
||||||
if (data.hook && data.method) {
|
if (data.hook && data.method) {
|
||||||
_self.loadedHooks[data.hook] = _self.loadedHooks[data.hook] || [];
|
_self.loadedHooks[data.hook] = _self.loadedHooks[data.hook] || [];
|
||||||
_self.loadedHooks[data.hook].push([id, data.method]);
|
_self.loadedHooks[data.hook].push([id, data.method, !!data.callbacked]);
|
||||||
if (global.env === 'development') winston.info('[plugins] Hook registered: ' + data.hook + ' will call ' + id);
|
if (global.env === 'development') winston.info('[plugins] Hook registered: ' + data.hook + ' will call ' + id);
|
||||||
} else return;
|
} else return;
|
||||||
},
|
},
|
||||||
@@ -84,7 +88,7 @@ var fs = require('fs'),
|
|||||||
var returnVal = (Array.isArray(args) ? args[0] : args);
|
var returnVal = (Array.isArray(args) ? args[0] : args);
|
||||||
|
|
||||||
async.each(hookList, function(hookObj, next) {
|
async.each(hookList, function(hookObj, next) {
|
||||||
if (hookObj.callbacked) {
|
if (hookObj[2]) {
|
||||||
_self.libraries[hookObj[0]][hookObj[1]](returnVal, function(err, afterVal) {
|
_self.libraries[hookObj[0]][hookObj[1]](returnVal, function(err, afterVal) {
|
||||||
returnVal = afterVal;
|
returnVal = afterVal;
|
||||||
next(err);
|
next(err);
|
||||||
@@ -95,7 +99,9 @@ var fs = require('fs'),
|
|||||||
}
|
}
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (global.env === 'development') winston.info('[plugins] Problem executing hook: ' + hook);
|
if (global.env === 'development') {
|
||||||
|
winston.info('[plugins] Problem executing hook: ' + hook);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(returnVal);
|
callback(returnVal);
|
||||||
@@ -150,26 +156,49 @@ var fs = require('fs'),
|
|||||||
showInstalled: function(callback) {
|
showInstalled: function(callback) {
|
||||||
// TODO: Also check /node_modules
|
// TODO: Also check /node_modules
|
||||||
var _self = this;
|
var _self = this;
|
||||||
moduleBasePath = path.join(__dirname, '../plugins');
|
localPluginPath = path.join(__dirname, '../plugins'),
|
||||||
|
npmPluginPath = path.join(__dirname, '../node_modules');
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function(next) {
|
function(next) {
|
||||||
fs.readdir(moduleBasePath, next);
|
async.parallel([
|
||||||
|
function(next) {
|
||||||
|
fs.readdir(localPluginPath, next);
|
||||||
|
},
|
||||||
|
function(next) {
|
||||||
|
fs.readdir(npmPluginPath, next);
|
||||||
|
}
|
||||||
|
], function(err, dirs) {
|
||||||
|
if (err) return next(err);
|
||||||
|
|
||||||
|
dirs[0] = dirs[0].map(function(file) {
|
||||||
|
return path.join(localPluginPath, file);
|
||||||
|
}).filter(function(file) {
|
||||||
|
var stats = fs.statSync(file);
|
||||||
|
if (stats.isDirectory()) return true;
|
||||||
|
else return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
dirs[1] = dirs[1].map(function(file) {
|
||||||
|
return path.join(npmPluginPath, file);
|
||||||
|
}).filter(function(file) {
|
||||||
|
var stats = fs.statSync(file);
|
||||||
|
if (stats.isDirectory() && file.substr(npmPluginPath.length+1, 14) === 'nodebb-plugin-') return true;
|
||||||
|
else return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
next(err, dirs[0].concat(dirs[1]));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
function(files, next) {
|
function(files, next) {
|
||||||
var plugins = [];
|
var plugins = [];
|
||||||
|
|
||||||
async.each(files, function(file, next) {
|
async.each(files, function(file, next) {
|
||||||
var modulePath = path.join(moduleBasePath, file),
|
var configPath;
|
||||||
configPath;
|
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function(next) {
|
function(next) {
|
||||||
fs.stat(path.join(moduleBasePath, file), next);
|
fs.readFile(path.join(file, 'plugin.json'), next);
|
||||||
},
|
|
||||||
function(stats, next) {
|
|
||||||
if (stats.isDirectory()) fs.readFile(path.join(modulePath, 'plugin.json'), next);
|
|
||||||
else next(new Error('not-a-directory'));
|
|
||||||
},
|
},
|
||||||
function(configJSON, next) {
|
function(configJSON, next) {
|
||||||
var config = JSON.parse(configJSON);
|
var config = JSON.parse(configJSON);
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ var RDB = require('./redis.js'),
|
|||||||
reds = require('reds'),
|
reds = require('reds'),
|
||||||
postSearch = reds.createSearch('nodebbpostsearch'),
|
postSearch = reds.createSearch('nodebbpostsearch'),
|
||||||
topicSearch = reds.createSearch('nodebbtopicsearch'),
|
topicSearch = reds.createSearch('nodebbtopicsearch'),
|
||||||
winston = require('winston');
|
winston = require('winston'),
|
||||||
|
meta = require('./meta.js');
|
||||||
|
|
||||||
(function(PostTools) {
|
(function(PostTools) {
|
||||||
PostTools.isMain = function(pid, tid, callback) {
|
PostTools.isMain = function(pid, tid, callback) {
|
||||||
@@ -41,7 +42,7 @@ var RDB = require('./redis.js'),
|
|||||||
|
|
||||||
function hasEnoughRep(next) {
|
function hasEnoughRep(next) {
|
||||||
user.getUserField(uid, 'reputation', function(reputation) {
|
user.getUserField(uid, 'reputation', function(reputation) {
|
||||||
next(null, reputation >= global.config['privileges:manage_content']);
|
next(null, reputation >= meta.config['privileges:manage_content']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +176,7 @@ var RDB = require('./redis.js'),
|
|||||||
this.attr('rel', 'nofollow');
|
this.attr('rel', 'nofollow');
|
||||||
var href = this.attr('href');
|
var href = this.attr('href');
|
||||||
|
|
||||||
if (href && !href.match(domain)) {
|
if (href && !href.match(domain) && !utils.isRelativeUrl(href)) {
|
||||||
this.attr('href', domain + 'outgoing?url=' + encodeURIComponent(href));
|
this.attr('href', domain + 'outgoing?url=' + encodeURIComponent(href));
|
||||||
if (!isSignature) this.append(' <i class="icon-external-link"></i>');
|
if (!isSignature) this.append(' <i class="icon-external-link"></i>');
|
||||||
}
|
}
|
||||||
|
|||||||
75
src/posts.js
75
src/posts.js
@@ -11,6 +11,7 @@ var RDB = require('./redis.js'),
|
|||||||
plugins = require('./plugins'),
|
plugins = require('./plugins'),
|
||||||
reds = require('reds'),
|
reds = require('reds'),
|
||||||
nconf = require('nconf'),
|
nconf = require('nconf'),
|
||||||
|
meta = require('./meta.js'),
|
||||||
postSearch = reds.createSearch('nodebbpostsearch'),
|
postSearch = reds.createSearch('nodebbpostsearch'),
|
||||||
winston = require('winston');
|
winston = require('winston');
|
||||||
|
|
||||||
@@ -32,7 +33,9 @@ var RDB = require('./redis.js'),
|
|||||||
}
|
}
|
||||||
|
|
||||||
Posts.addUserInfoToPost = function(post, callback) {
|
Posts.addUserInfoToPost = function(post, callback) {
|
||||||
user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(userData) {
|
user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(err, userData) {
|
||||||
|
if(err)
|
||||||
|
return callback();
|
||||||
|
|
||||||
post.username = userData.username || 'anonymous';
|
post.username = userData.username || 'anonymous';
|
||||||
post.userslug = userData.userslug || '';
|
post.userslug = userData.userslug || '';
|
||||||
@@ -43,7 +46,9 @@ var RDB = require('./redis.js'),
|
|||||||
post.signature = postTools.markdownToHTML(userData.signature, true);
|
post.signature = postTools.markdownToHTML(userData.signature, true);
|
||||||
|
|
||||||
if(post.editor !== '') {
|
if(post.editor !== '') {
|
||||||
user.getUserFields(post.editor, ['username', 'userslug'], function(editorData) {
|
user.getUserFields(post.editor, ['username', 'userslug'], function(err, editorData) {
|
||||||
|
if(err)
|
||||||
|
return callback();
|
||||||
post.editorname = editorData.username;
|
post.editorname = editorData.username;
|
||||||
post.editorslug = editorData.userslug;
|
post.editorslug = editorData.userslug;
|
||||||
callback();
|
callback();
|
||||||
@@ -97,7 +102,10 @@ var RDB = require('./redis.js'),
|
|||||||
Posts.getPostData = function(pid, callback) {
|
Posts.getPostData = function(pid, callback) {
|
||||||
RDB.hgetall('post:' + pid, function(err, data) {
|
RDB.hgetall('post:' + pid, function(err, data) {
|
||||||
if(err === null) {
|
if(err === null) {
|
||||||
|
plugins.fireHook('filter:post.get', data.content, function(content) {
|
||||||
|
data.content = content;
|
||||||
callback(data);
|
callback(data);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@@ -143,7 +151,12 @@ var RDB = require('./redis.js'),
|
|||||||
postData.content = postTools.markdownToHTML(postData.content);
|
postData.content = postTools.markdownToHTML(postData.content);
|
||||||
|
|
||||||
if(postData.uploadedImages) {
|
if(postData.uploadedImages) {
|
||||||
|
try {
|
||||||
postData.uploadedImages = JSON.parse(postData.uploadedImages);
|
postData.uploadedImages = JSON.parse(postData.uploadedImages);
|
||||||
|
} catch(err) {
|
||||||
|
postData.uploadedImages = [];
|
||||||
|
winston.err(err);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
postData.uploadedImages = [];
|
postData.uploadedImages = [];
|
||||||
}
|
}
|
||||||
@@ -181,7 +194,7 @@ var RDB = require('./redis.js'),
|
|||||||
type: 'error',
|
type: 'error',
|
||||||
timeout: 2000,
|
timeout: 2000,
|
||||||
title: 'Content too short',
|
title: 'Content too short',
|
||||||
message: "Please enter a longer post. At least " + config.minimumPostLength + " characters.",
|
message: "Please enter a longer post. At least " + meta.config.minimumPostLength + " characters.",
|
||||||
alert_id: 'post_error'
|
alert_id: 'post_error'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -189,7 +202,7 @@ var RDB = require('./redis.js'),
|
|||||||
Posts.emitTooManyPostsAlert = function(socket) {
|
Posts.emitTooManyPostsAlert = function(socket) {
|
||||||
socket.emit('event:alert', {
|
socket.emit('event:alert', {
|
||||||
title: 'Too many posts!',
|
title: 'Too many posts!',
|
||||||
message: 'You can only post every '+ config.postDelay/1000 + ' seconds.',
|
message: 'You can only post every '+ meta.config.postDelay/1000 + ' seconds.',
|
||||||
type: 'error',
|
type: 'error',
|
||||||
timeout: 2000
|
timeout: 2000
|
||||||
});
|
});
|
||||||
@@ -200,13 +213,13 @@ var RDB = require('./redis.js'),
|
|||||||
content = content.trim();
|
content = content.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!content || content.length < config.minimumPostLength) {
|
if (!content || content.length < meta.config.minimumPostLength) {
|
||||||
callback(new Error('content-too-short'), null);
|
callback(new Error('content-too-short'), null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
user.getUserField(uid, 'lastposttime', function(lastposttime) {
|
user.getUserField(uid, 'lastposttime', function(lastposttime) {
|
||||||
if(Date.now() - lastposttime < config.postDelay) {
|
if(Date.now() - lastposttime < meta.config.postDelay) {
|
||||||
callback(new Error('too-many-posts'), null);
|
callback(new Error('too-many-posts'), null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -224,22 +237,8 @@ var RDB = require('./redis.js'),
|
|||||||
|
|
||||||
threadTools.notify_followers(tid, uid);
|
threadTools.notify_followers(tid, uid);
|
||||||
|
|
||||||
postData.content = postTools.markdownToHTML(postData.content);
|
Posts.addUserInfoToPost(postData, function() {
|
||||||
postData.post_rep = 0;
|
var socketData = { posts: [postData] };
|
||||||
postData.relativeTime = utils.relativeTime(postData.timestamp);
|
|
||||||
postData.fav_button_class = '';
|
|
||||||
postData.fav_star_class = 'icon-star-empty';
|
|
||||||
postData['edited-class'] = 'none';
|
|
||||||
postData.show_banned = 'hide';
|
|
||||||
postData.uploadedImages = JSON.parse(postData.uploadedImages);
|
|
||||||
|
|
||||||
var socketData = {
|
|
||||||
'posts' : [
|
|
||||||
postData
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
posts.addUserInfoToPost(socketData['posts'][0], function() {
|
|
||||||
io.sockets.in('topic_' + tid).emit('event:new_post', socketData);
|
io.sockets.in('topic_' + tid).emit('event:new_post', socketData);
|
||||||
io.sockets.in('recent_posts').emit('event:new_post', socketData);
|
io.sockets.in('recent_posts').emit('event:new_post', socketData);
|
||||||
});
|
});
|
||||||
@@ -263,7 +262,7 @@ var RDB = require('./redis.js'),
|
|||||||
RDB.incr('global:next_post_id', function(err, pid) {
|
RDB.incr('global:next_post_id', function(err, pid) {
|
||||||
RDB.handle(err);
|
RDB.handle(err);
|
||||||
|
|
||||||
plugins.fireHook('filter:save_post_content', content, function(content) {
|
plugins.fireHook('filter:post.save', content, function(content) {
|
||||||
var timestamp = Date.now(),
|
var timestamp = Date.now(),
|
||||||
postData = {
|
postData = {
|
||||||
'pid': pid,
|
'pid': pid,
|
||||||
@@ -275,7 +274,14 @@ var RDB = require('./redis.js'),
|
|||||||
'editor': '',
|
'editor': '',
|
||||||
'edited': 0,
|
'edited': 0,
|
||||||
'deleted': 0,
|
'deleted': 0,
|
||||||
'uploadedImages': ''
|
'uploadedImages': '[]',
|
||||||
|
'fav_button_class': '',
|
||||||
|
'fav_star_class': 'icon-star-empty',
|
||||||
|
'show_banned': 'hide',
|
||||||
|
'relativeTime': '0 seconds',
|
||||||
|
'post_rep': '0',
|
||||||
|
'edited-class': 'none',
|
||||||
|
'relativeEditTime': ''
|
||||||
};
|
};
|
||||||
|
|
||||||
RDB.hmset('post:' + pid, postData);
|
RDB.hmset('post:' + pid, postData);
|
||||||
@@ -306,17 +312,30 @@ var RDB = require('./redis.js'),
|
|||||||
|
|
||||||
user.onNewPostMade(uid, tid, pid, timestamp);
|
user.onNewPostMade(uid, tid, pid, timestamp);
|
||||||
|
|
||||||
|
async.parallel({
|
||||||
|
uploadedImages: function(next) {
|
||||||
uploadPostImages(postData, images, function(err, uploadedImages) {
|
uploadPostImages(postData, images, function(err, uploadedImages) {
|
||||||
if(err) {
|
if(err) {
|
||||||
winston.error('Uploading images failed!', err.stack);
|
winston.error('Uploading images failed!', err.stack);
|
||||||
|
next(null, []);
|
||||||
} else {
|
} else {
|
||||||
postData.uploadedImages = JSON.stringify(uploadedImages);
|
next(null, uploadedImages);
|
||||||
Posts.setPostField(pid, 'uploadedImages', postData.uploadedImages);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
content: function(next) {
|
||||||
|
plugins.fireHook('filter:post.get', content, function(content) {
|
||||||
|
next(null, content);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, function(err, results) {
|
||||||
|
postData.uploadedImages = results.uploadedImages;
|
||||||
|
Posts.setPostField(pid, 'uploadedImages', JSON.stringify(postData.uploadedImages));
|
||||||
|
postData.content = results.content;
|
||||||
callback(postData);
|
callback(postData);
|
||||||
});
|
});
|
||||||
|
|
||||||
plugins.fireHook('action:save_post_content', [pid, content]);
|
plugins.fireHook('action:post.save', [pid, content]);
|
||||||
|
|
||||||
postSearch.index(content, pid);
|
postSearch.index(content, pid);
|
||||||
});
|
});
|
||||||
@@ -329,7 +348,7 @@ var RDB = require('./redis.js'),
|
|||||||
|
|
||||||
function uploadPostImages(postData, images, callback) {
|
function uploadPostImages(postData, images, callback) {
|
||||||
var imgur = require('./imgur');
|
var imgur = require('./imgur');
|
||||||
imgur.setClientID(config.imgurClientID);
|
imgur.setClientID(meta.config.imgurClientID);
|
||||||
|
|
||||||
var uploadedImages = [];
|
var uploadedImages = [];
|
||||||
|
|
||||||
|
|||||||
@@ -16,19 +16,14 @@ var user = require('./../user.js'),
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.get('/api/config', function(req, res, next) {
|
app.get('/api/config', function(req, res, next) {
|
||||||
meta.config.getFields(['postDelay', 'minimumTitleLength', 'minimumPostLength', 'imgurClientID'], function(err, metaConfig) {
|
var config = require('../../public/config.json');
|
||||||
if(err) return next();
|
|
||||||
var clientConfig = require('../../public/config.json');
|
|
||||||
|
|
||||||
for (var attrname in metaConfig) {
|
config['postDelay'] = meta.config['postDelay'];
|
||||||
clientConfig[attrname] = metaConfig[attrname];
|
config['minimumTitleLength'] = meta.config['minimumTitleLength'];
|
||||||
}
|
config['minimumPostLength'] = meta.config['minimumPostLength'];
|
||||||
|
config['imgurClientIDSet'] = !!meta.config['imgurClientID'];
|
||||||
|
|
||||||
clientConfig['imgurClientIDSet'] = !!clientConfig['imgurClientID'];
|
res.json(200, config);
|
||||||
delete clientConfig['imgurClientID'];
|
|
||||||
|
|
||||||
res.json(200, clientConfig);
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/api/home', function(req, res) {
|
app.get('/api/home', function(req, res) {
|
||||||
@@ -48,8 +43,9 @@ var user = require('./../user.js'),
|
|||||||
}
|
}
|
||||||
|
|
||||||
require('async').each(data.categories, iterator, function(err) {
|
require('async').each(data.categories, iterator, function(err) {
|
||||||
data.motd_class = (config.show_motd === '1' || config.show_motd === undefined) ? '' : 'none';
|
data.motd_class = (meta.config.show_motd === '1' || meta.config.show_motd === undefined) ? '' : 'none';
|
||||||
data.motd = marked(config.motd || "# NodeBB <span>v " + pkg.version + "</span>\nWelcome to NodeBB, the discussion platform of the future.\n\n<div class='btn-group'><a target=\"_blank\" href=\"http://www.nodebb.org\" class=\"btn btn-default btn-lg\"><i class=\"icon-comment\"></i><span><span> Get NodeBB</span></span></a> <a target=\"_blank\" href=\"https://github.com/designcreateplay/NodeBB\" class=\"btn btn-default btn-lg\"><i class=\"icon-github-alt\"></i><span> Fork us on Github</span></a> <a target=\"_blank\" href=\"https://twitter.com/dcplabs\" class=\"btn btn-default btn-lg\"><i class=\"icon-twitter\"></i><span> @dcplabs</span></a></div>");
|
data.motd = marked(meta.config.motd || "# NodeBB <span>v " + pkg.version + "</span>\nWelcome to NodeBB, the discussion platform of the future.\n\n<div class='btn-group'><a target=\"_blank\" href=\"http://www.nodebb.org\" class=\"btn btn-default btn-lg\"><i class=\"icon-comment\"></i><span><span> Get NodeBB</span></span></a> <a target=\"_blank\" href=\"https://github.com/designcreateplay/NodeBB\" class=\"btn btn-default btn-lg\"><i class=\"icon-github-alt\"></i><span> Fork us on Github</span></a> <a target=\"_blank\" href=\"https://twitter.com/dcplabs\" class=\"btn btn-default btn-lg\"><i class=\"icon-twitter\"></i><span> @dcplabs</span></a></div>");
|
||||||
|
|
||||||
res.json(data);
|
res.json(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
passportFacebook = require('passport-facebook').Strategy,
|
passportFacebook = require('passport-facebook').Strategy,
|
||||||
login_strategies = [],
|
login_strategies = [],
|
||||||
nconf = require('nconf'),
|
nconf = require('nconf'),
|
||||||
|
meta = require('../meta'),
|
||||||
user = require('../user'),
|
user = require('../user'),
|
||||||
winston = require('winston'),
|
winston = require('winston'),
|
||||||
login_module = require('./../login.js');
|
login_module = require('./../login.js');
|
||||||
@@ -17,10 +18,10 @@
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (global.config['social:twitter:key'] && global.config['social:twitter:secret']) {
|
if (meta.config['social:twitter:key'] && meta.config['social:twitter:secret']) {
|
||||||
passport.use(new passportTwitter({
|
passport.use(new passportTwitter({
|
||||||
consumerKey: global.config['social:twitter:key'],
|
consumerKey: meta.config['social:twitter:key'],
|
||||||
consumerSecret: global.config['social:twitter:secret'],
|
consumerSecret: meta.config['social:twitter:secret'],
|
||||||
callbackURL: nconf.get('url') + 'auth/twitter/callback'
|
callbackURL: nconf.get('url') + 'auth/twitter/callback'
|
||||||
}, function(token, tokenSecret, profile, done) {
|
}, function(token, tokenSecret, profile, done) {
|
||||||
login_module.loginViaTwitter(profile.id, profile.username, profile.photos, function(err, user) {
|
login_module.loginViaTwitter(profile.id, profile.username, profile.photos, function(err, user) {
|
||||||
@@ -32,10 +33,10 @@
|
|||||||
login_strategies.push('twitter');
|
login_strategies.push('twitter');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global.config['social:google:id'] && global.config['social:google:secret']) {
|
if (meta.config['social:google:id'] && meta.config['social:google:secret']) {
|
||||||
passport.use(new passportGoogle({
|
passport.use(new passportGoogle({
|
||||||
clientID: global.config['social:google:id'],
|
clientID: meta.config['social:google:id'],
|
||||||
clientSecret: global.config['social:google:secret'],
|
clientSecret: meta.config['social:google:secret'],
|
||||||
callbackURL: nconf.get('url') + 'auth/google/callback'
|
callbackURL: nconf.get('url') + 'auth/google/callback'
|
||||||
}, function(accessToken, refreshToken, profile, done) {
|
}, function(accessToken, refreshToken, profile, done) {
|
||||||
login_module.loginViaGoogle(profile.id, profile.displayName, profile.emails[0].value, function(err, user) {
|
login_module.loginViaGoogle(profile.id, profile.displayName, profile.emails[0].value, function(err, user) {
|
||||||
@@ -47,10 +48,10 @@
|
|||||||
login_strategies.push('google');
|
login_strategies.push('google');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global.config['social:facebook:app_id'] && global.config['social:facebook:secret']) {
|
if (meta.config['social:facebook:app_id'] && meta.config['social:facebook:secret']) {
|
||||||
passport.use(new passportFacebook({
|
passport.use(new passportFacebook({
|
||||||
clientID: global.config['social:facebook:app_id'],
|
clientID: meta.config['social:facebook:app_id'],
|
||||||
clientSecret: global.config['social:facebook:secret'],
|
clientSecret: meta.config['social:facebook:secret'],
|
||||||
callbackURL: nconf.get('url') + 'auth/facebook/callback'
|
callbackURL: nconf.get('url') + 'auth/facebook/callback'
|
||||||
}, function(accessToken, refreshToken, profile, done) {
|
}, function(accessToken, refreshToken, profile, done) {
|
||||||
login_module.loginViaFacebook(profile.id, profile.displayName, profile.emails[0].value, function(err, user) {
|
login_module.loginViaFacebook(profile.id, profile.displayName, profile.emails[0].value, function(err, user) {
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ var user = require('./../user.js'),
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/api/users/:userslug/settings', function(req, res) {
|
app.get('/api/users/:userslug/settings', function(req, res, next) {
|
||||||
var callerUID = req.user ? req.user.uid : 0;
|
var callerUID = req.user ? req.user.uid : 0;
|
||||||
|
|
||||||
user.get_uid_by_userslug(req.params.userslug, function(uid) {
|
user.get_uid_by_userslug(req.params.userslug, function(uid) {
|
||||||
@@ -294,7 +294,10 @@ var user = require('./../user.js'),
|
|||||||
res.json(403, { error: 'Not allowed!' });
|
res.json(403, { error: 'Not allowed!' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
user.getUserFields(uid, ['username','userslug','showemail'], function(userData) {
|
user.getUserFields(uid, ['username','userslug','showemail'], function(err, userData) {
|
||||||
|
if(err)
|
||||||
|
return next(err);
|
||||||
|
|
||||||
if(userData) {
|
if(userData) {
|
||||||
if(userData.showemail && userData.showemail === "1")
|
if(userData.showemail && userData.showemail === "1")
|
||||||
userData.showemail = "checked";
|
userData.showemail = "checked";
|
||||||
@@ -322,7 +325,10 @@ var user = require('./../user.js'),
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
user.getUserFields(uid, ['username','userslug'], function(userData) {
|
user.getUserFields(uid, ['username','userslug'], function(err, userData) {
|
||||||
|
if(err)
|
||||||
|
return next(err);
|
||||||
|
|
||||||
if(userData) {
|
if(userData) {
|
||||||
posts.getFavourites(uid, function(err, posts) {
|
posts.getFavourites(uid, function(err, posts) {
|
||||||
if(err)
|
if(err)
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ var RDB = require('./redis.js'),
|
|||||||
posts = require('./posts'),
|
posts = require('./posts'),
|
||||||
reds = require('reds'),
|
reds = require('reds'),
|
||||||
topicSearch = reds.createSearch('nodebbtopicsearch'),
|
topicSearch = reds.createSearch('nodebbtopicsearch'),
|
||||||
winston = require('winston');
|
winston = require('winston'),
|
||||||
|
meta = require('./meta');
|
||||||
|
|
||||||
(function(ThreadTools) {
|
(function(ThreadTools) {
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ var RDB = require('./redis.js'),
|
|||||||
|
|
||||||
function hasEnoughRep(next) {
|
function hasEnoughRep(next) {
|
||||||
user.getUserField(uid, 'reputation', function(reputation) {
|
user.getUserField(uid, 'reputation', function(reputation) {
|
||||||
next(null, reputation >= global.config['privileges:manage_topic']);
|
next(null, reputation >= meta.config['privileges:manage_topic']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,12 +111,12 @@ var RDB = require('./redis.js'),
|
|||||||
topics.setTopicField(tid, 'deleted', 0);
|
topics.setTopicField(tid, 'deleted', 0);
|
||||||
ThreadTools.unlock(tid, uid);
|
ThreadTools.unlock(tid, uid);
|
||||||
|
|
||||||
if (socket) {
|
|
||||||
io.sockets.in('topic_' + tid).emit('event:topic_restored', {
|
io.sockets.in('topic_' + tid).emit('event:topic_restored', {
|
||||||
tid: tid,
|
tid: tid,
|
||||||
status: 'ok'
|
status: 'ok'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (socket) {
|
||||||
socket.emit('api:topic.restore', {
|
socket.emit('api:topic.restore', {
|
||||||
status: 'ok',
|
status: 'ok',
|
||||||
tid: tid
|
tid: tid
|
||||||
@@ -187,7 +188,7 @@ var RDB = require('./redis.js'),
|
|||||||
|
|
||||||
multi.exec(function(err, result) {
|
multi.exec(function(err, result) {
|
||||||
|
|
||||||
if (!err && result === 1) {
|
if (!err && result[0] === 1 && result[1] === 1) {
|
||||||
|
|
||||||
topics.setTopicField(tid, 'cid', cid);
|
topics.setTopicField(tid, 'cid', cid);
|
||||||
|
|
||||||
|
|||||||
@@ -211,9 +211,7 @@ marked.setOptions({
|
|||||||
function getTopicInfo(topicData, callback) {
|
function getTopicInfo(topicData, callback) {
|
||||||
|
|
||||||
function getUserInfo(next) {
|
function getUserInfo(next) {
|
||||||
user.getUserFields(topicData.uid, ['username'], function(userData) {
|
user.getUserFields(topicData.uid, ['username'], next);
|
||||||
next(null, userData);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasReadTopic(next) {
|
function hasReadTopic(next) {
|
||||||
@@ -520,7 +518,10 @@ marked.setOptions({
|
|||||||
if (!err) {
|
if (!err) {
|
||||||
posts.getPostFields(pid, ['content', 'uid', 'timestamp'], function(postData) {
|
posts.getPostFields(pid, ['content', 'uid', 'timestamp'], function(postData) {
|
||||||
|
|
||||||
user.getUserFields(postData.uid, ['username', 'picture'], function(userData) {
|
user.getUserFields(postData.uid, ['username', 'picture'], function(err, userData) {
|
||||||
|
if(err)
|
||||||
|
return callback(err, null);
|
||||||
|
|
||||||
var stripped = postData.content,
|
var stripped = postData.content,
|
||||||
timestamp = postData.timestamp;
|
timestamp = postData.timestamp;
|
||||||
|
|
||||||
@@ -546,7 +547,7 @@ marked.setOptions({
|
|||||||
type: 'error',
|
type: 'error',
|
||||||
timeout: 2000,
|
timeout: 2000,
|
||||||
title: 'Title too short',
|
title: 'Title too short',
|
||||||
message: "Please enter a longer title. At least " + config.minimumTitleLength + " characters.",
|
message: "Please enter a longer title. At least " + meta.config.minimumTitleLength + " characters.",
|
||||||
alert_id: 'post_error'
|
alert_id: 'post_error'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -563,17 +564,17 @@ marked.setOptions({
|
|||||||
if (uid === 0) {
|
if (uid === 0) {
|
||||||
callback(new Error('not-logged-in'), null);
|
callback(new Error('not-logged-in'), null);
|
||||||
return;
|
return;
|
||||||
} else if(!title || title.length < config.minimumTitleLength) {
|
} else if(!title || title.length < meta.config.minimumTitleLength) {
|
||||||
callback(new Error('title-too-short'), null);
|
callback(new Error('title-too-short'), null);
|
||||||
return;
|
return;
|
||||||
} else if (!content || content.length < config.miminumPostLength) {
|
} else if (!content || content.length < meta.config.miminumPostLength) {
|
||||||
callback(new Error('content-too-short'), null);
|
callback(new Error('content-too-short'), null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
user.getUserField(uid, 'lastposttime', function(lastposttime) {
|
user.getUserField(uid, 'lastposttime', function(lastposttime) {
|
||||||
|
|
||||||
if(Date.now() - lastposttime < config.postDelay) {
|
if(Date.now() - lastposttime < meta.config.postDelay) {
|
||||||
callback(new Error('too-many-posts'), null);
|
callback(new Error('too-many-posts'), null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
var RDB = require('./redis.js'),
|
var RDB = require('./redis.js'),
|
||||||
async = require('async'),
|
async = require('async'),
|
||||||
winston = require('winston');
|
winston = require('winston'),
|
||||||
|
user = require('./user');
|
||||||
|
|
||||||
|
|
||||||
function upgradeCategory(cid, callback) {
|
function upgradeCategory(cid, callback) {
|
||||||
@@ -36,7 +37,7 @@ function upgradeCategory(cid, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function upgradeUser(uid, callback) {
|
function upgradeUser(uid, callback) {
|
||||||
RDB.hmgetObject('user:' + uid, ['joindate', 'postcount', 'reputation'], function(err, userData) {
|
user.getUserFields(uid, ['joindate', 'postcount', 'reputation'], function(err, userData) {
|
||||||
if(err)
|
if(err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@@ -46,7 +47,6 @@ function upgradeUser(uid, callback) {
|
|||||||
|
|
||||||
callback(null);
|
callback(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.upgrade = function() {
|
exports.upgrade = function() {
|
||||||
|
|||||||
33
src/user.js
33
src/user.js
@@ -2,7 +2,8 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
RDB = require('./redis.js'),
|
RDB = require('./redis.js'),
|
||||||
crypto = require('crypto'),
|
crypto = require('crypto'),
|
||||||
emailjs = require('emailjs'),
|
emailjs = require('emailjs'),
|
||||||
emailjsServer = emailjs.server.connect(config.mailer),
|
meta = require('./meta.js'),
|
||||||
|
emailjsServer = emailjs.server.connect(meta.config.mailer),
|
||||||
bcrypt = require('bcrypt'),
|
bcrypt = require('bcrypt'),
|
||||||
marked = require('marked'),
|
marked = require('marked'),
|
||||||
notifications = require('./notifications.js'),
|
notifications = require('./notifications.js'),
|
||||||
@@ -148,13 +149,7 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
}
|
}
|
||||||
|
|
||||||
User.getUserFields = function(uid, fields, callback) {
|
User.getUserFields = function(uid, fields, callback) {
|
||||||
RDB.hmgetObject('user:' + uid, fields, function(err, data) {
|
RDB.hmgetObject('user:' + uid, fields, callback);
|
||||||
if(err === null) {
|
|
||||||
callback(data);
|
|
||||||
} else {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
User.getMultipleUserFields = function(uids, fields, callback) {
|
User.getMultipleUserFields = function(uids, fields, callback) {
|
||||||
@@ -170,7 +165,9 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
});
|
});
|
||||||
|
|
||||||
function iterator(uid, callback) {
|
function iterator(uid, callback) {
|
||||||
User.getUserFields(uid, fields, function(userData) {
|
User.getUserFields(uid, fields, function(err, userData) {
|
||||||
|
if(err)
|
||||||
|
return callback(err);
|
||||||
returnData.push(userData);
|
returnData.push(userData);
|
||||||
callback(null);
|
callback(null);
|
||||||
});
|
});
|
||||||
@@ -261,7 +258,10 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
if(field === 'email') {
|
if(field === 'email') {
|
||||||
var gravatarpicture = User.createGravatarURLFromEmail(data[field]);
|
var gravatarpicture = User.createGravatarURLFromEmail(data[field]);
|
||||||
User.setUserField(uid, 'gravatarpicture', gravatarpicture);
|
User.setUserField(uid, 'gravatarpicture', gravatarpicture);
|
||||||
User.getUserFields(uid, ['email', 'picture', 'uploadedpicture'], function(userData) {
|
User.getUserFields(uid, ['email', 'picture', 'uploadedpicture'], function(err, userData) {
|
||||||
|
if(err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
RDB.del('email:' + userData['email'] + ':uid');
|
RDB.del('email:' + userData['email'] + ':uid');
|
||||||
RDB.set('email:' + data['email'] + ':uid', uid);
|
RDB.set('email:' + data['email'] + ':uid', uid);
|
||||||
User.setUserField(uid, field, data[field]);
|
User.setUserField(uid, field, data[field]);
|
||||||
@@ -385,7 +385,7 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bcrypt.genSalt(config.bcrypt_rounds, function(err, salt) {
|
bcrypt.genSalt(nconf.get('bcrypt_rounds'), function(err, salt) {
|
||||||
bcrypt.hash(password, salt, function(err, hash) {
|
bcrypt.hash(password, salt, function(err, hash) {
|
||||||
callback(hash);
|
callback(hash);
|
||||||
});
|
});
|
||||||
@@ -450,9 +450,9 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
}
|
}
|
||||||
|
|
||||||
User.sendConfirmationEmail = function (email) {
|
User.sendConfirmationEmail = function (email) {
|
||||||
if (global.config['email:host'] && global.config['email:port'] && global.config['email:from']) {
|
if (meta.config['email:host'] && meta.config['email:port'] && meta.config['email:from']) {
|
||||||
var confirm_code = utils.generateUUID(),
|
var confirm_code = utils.generateUUID(),
|
||||||
confirm_link = config.url + 'confirm/' + confirm_code,
|
confirm_link = nconf.get('url') + 'confirm/' + confirm_code,
|
||||||
confirm_email = global.templates['emails/header'] + global.templates['emails/email_confirm'].parse({'CONFIRM_LINK': confirm_link}) + global.templates['emails/footer'],
|
confirm_email = global.templates['emails/header'] + global.templates['emails/email_confirm'].parse({'CONFIRM_LINK': confirm_link}) + global.templates['emails/footer'],
|
||||||
confirm_email_plaintext = global.templates['emails/email_confirm_plaintext'].parse({ 'CONFIRM_LINK': confirm_link });
|
confirm_email_plaintext = global.templates['emails/email_confirm_plaintext'].parse({ 'CONFIRM_LINK': confirm_link });
|
||||||
|
|
||||||
@@ -469,7 +469,7 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
// Send intro email w/ confirm code
|
// Send intro email w/ confirm code
|
||||||
var message = emailjs.message.create({
|
var message = emailjs.message.create({
|
||||||
text: confirm_email_plaintext,
|
text: confirm_email_plaintext,
|
||||||
from: config.mailer.from,
|
from: meta.config.mailer.from,
|
||||||
to: email,
|
to: email,
|
||||||
subject: '[NodeBB] Registration Email Verification',
|
subject: '[NodeBB] Registration Email Verification',
|
||||||
attachment: [
|
attachment: [
|
||||||
@@ -625,7 +625,8 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
RDB.zrevrange('users:joindate', 0, 0, function(err, uid) {
|
RDB.zrevrange('users:joindate', 0, 0, function(err, uid) {
|
||||||
RDB.handle(err);
|
RDB.handle(err);
|
||||||
|
|
||||||
User.getUserFields(uid, ['username', 'userslug'], function(userData) {
|
User.getUserFields(uid, ['username', 'userslug'], function(err, userData) {
|
||||||
|
if(!err && userData)
|
||||||
socket.emit('user.latest', {userslug: userData.userslug, username: userData.username});
|
socket.emit('user.latest', {userslug: userData.userslug, username: userData.username});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -848,7 +849,7 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
|
|
||||||
var message = emailjs.message.create({
|
var message = emailjs.message.create({
|
||||||
text: reset_email_plaintext,
|
text: reset_email_plaintext,
|
||||||
from: config.mailer?config.mailer.from:'localhost@example.org',
|
from: meta.config.mailer?meta.config.mailer.from:'localhost@example.org',
|
||||||
to: email,
|
to: email,
|
||||||
subject: 'Password Reset Requested',
|
subject: 'Password Reset Requested',
|
||||||
attachment: [
|
attachment: [
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ var express = require('express'),
|
|||||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1.0' },
|
{ name: 'viewport', content: 'width=device-width, initial-scale=1.0' },
|
||||||
{ name: 'content-type', content: 'text/html; charset=UTF-8' },
|
{ name: 'content-type', content: 'text/html; charset=UTF-8' },
|
||||||
{ name: 'apple-mobile-web-app-capable', content: 'yes' },
|
{ name: 'apple-mobile-web-app-capable', content: 'yes' },
|
||||||
{ property: 'og:site_name', content: global.config.title || 'NodeBB' },
|
{ property: 'og:site_name', content: meta.config.title || 'NodeBB' },
|
||||||
],
|
],
|
||||||
metaString = utils.buildMetaTags(defaultMetaTags.concat(options.metaTags || [])),
|
metaString = utils.buildMetaTags(defaultMetaTags.concat(options.metaTags || [])),
|
||||||
templateValues = {
|
templateValues = {
|
||||||
cssSrc: global.config['theme:src'] || nconf.get('relative_path') + '/vendor/bootstrap/css/bootstrap.min.css',
|
cssSrc: meta.config['theme:src'] || nconf.get('relative_path') + '/vendor/bootstrap/css/bootstrap.min.css',
|
||||||
title: global.config['title'] || 'NodeBB',
|
title: meta.config['title'] || 'NodeBB',
|
||||||
browserTitle: global.config['title'] || 'NodeBB',
|
browserTitle: meta.config['title'] || 'NodeBB',
|
||||||
csrf: options.res.locals.csrf_token,
|
csrf: options.res.locals.csrf_token,
|
||||||
relative_path: nconf.get('relative_path'),
|
relative_path: nconf.get('relative_path'),
|
||||||
meta_tags: metaString
|
meta_tags: metaString
|
||||||
@@ -183,9 +183,9 @@ var express = require('express'),
|
|||||||
req: req,
|
req: req,
|
||||||
res: res,
|
res: res,
|
||||||
metaTags: [
|
metaTags: [
|
||||||
{ name: "title", content: global.config.title || 'NodeBB' },
|
{ name: "title", content: meta.config.title || 'NodeBB' },
|
||||||
{ name: "description", content: global.config.description || '' },
|
{ name: "description", content: meta.config.description || '' },
|
||||||
{ property: 'og:title', content: 'Index | ' + (global.config.title || 'NodeBB') },
|
{ property: 'og:title', content: 'Index | ' + (meta.config.title || 'NodeBB') },
|
||||||
{ property: "og:type", content: 'website' }
|
{ property: "og:type", content: 'website' }
|
||||||
]
|
]
|
||||||
}, next);
|
}, next);
|
||||||
@@ -241,7 +241,7 @@ var express = require('express'),
|
|||||||
res: res,
|
res: res,
|
||||||
metaTags: [
|
metaTags: [
|
||||||
{ name: "title", content: topicData.topic_name },
|
{ name: "title", content: topicData.topic_name },
|
||||||
{ property: 'og:title', content: topicData.topic_name + ' | ' + (global.config.title || 'NodeBB') },
|
{ property: 'og:title', content: topicData.topic_name + ' | ' + (meta.config.title || 'NodeBB') },
|
||||||
{ property: "og:type", content: 'article' },
|
{ property: "og:type", content: 'article' },
|
||||||
{ property: "og:url", content: nconf.get('url') + 'topic/' + topicData.slug },
|
{ property: "og:url", content: nconf.get('url') + 'topic/' + topicData.slug },
|
||||||
{ property: 'og:image', content: topicData.main_posts[0].picture },
|
{ property: 'og:image', content: topicData.main_posts[0].picture },
|
||||||
|
|||||||
@@ -177,9 +177,11 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
|
|
||||||
socket.on('api:updateHeader', function(data) {
|
socket.on('api:updateHeader', function(data) {
|
||||||
if(uid) {
|
if(uid) {
|
||||||
user.getUserFields(uid, data.fields, function(fields) {
|
user.getUserFields(uid, data.fields, function(err, fields) {
|
||||||
|
if(!err && fields) {
|
||||||
fields.uid = uid;
|
fields.uid = uid;
|
||||||
socket.emit('api:updateHeader', fields);
|
socket.emit('api:updateHeader', fields);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -261,10 +263,14 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
var type = data.type;
|
var type = data.type;
|
||||||
|
|
||||||
function updateHeader() {
|
function updateHeader() {
|
||||||
user.getUserFields(uid, ['picture'], function(fields) {
|
user.getUserFields(uid, ['picture'], function(err, fields) {
|
||||||
|
if(!err && fields) {
|
||||||
fields.uid = uid;
|
fields.uid = uid;
|
||||||
socket.emit('api:updateHeader', fields);
|
socket.emit('api:updateHeader', fields);
|
||||||
callback(true);
|
callback(true);
|
||||||
|
} else {
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,19 +531,19 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:config.get', function(data) {
|
socket.on('api:config.get', function(data) {
|
||||||
meta.config.get(function(config) {
|
meta.configs.get(function(config) {
|
||||||
socket.emit('api:config.get', config);
|
socket.emit('api:config.get', config);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:config.set', function(data) {
|
socket.on('api:config.set', function(data) {
|
||||||
meta.config.set(data.key, data.value, function(err) {
|
meta.configs.set(data.key, data.value, function(err) {
|
||||||
if (!err) socket.emit('api:config.set', { status: 'ok' });
|
if (!err) socket.emit('api:config.set', { status: 'ok' });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:config.remove', function(key) {
|
socket.on('api:config.remove', function(key) {
|
||||||
meta.config.remove(key);
|
meta.configs.remove(key);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:composer.push', function(data) {
|
socket.on('api:composer.push', function(data) {
|
||||||
@@ -555,7 +561,8 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else if (parseInt(data.cid) > 0) {
|
} else if (parseInt(data.cid) > 0) {
|
||||||
user.getUserFields(uid, ['username', 'picture'], function(userData) {
|
user.getUserFields(uid, ['username', 'picture'], function(err, userData) {
|
||||||
|
if(!err && userData) {
|
||||||
socket.emit('api:composer.push', {
|
socket.emit('api:composer.push', {
|
||||||
tid: 0,
|
tid: 0,
|
||||||
cid: data.cid,
|
cid: data.cid,
|
||||||
@@ -563,6 +570,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
picture: userData.picture,
|
picture: userData.picture,
|
||||||
title: undefined
|
title: undefined
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else if (parseInt(data.pid) > 0) {
|
} else if (parseInt(data.pid) > 0) {
|
||||||
async.parallel([
|
async.parallel([
|
||||||
|
|||||||
Reference in New Issue
Block a user