mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-07-06 10:09:38 +02:00
Merge remote-tracking branch 'origin'
This commit is contained in:
48
app.js
48
app.js
@@ -16,8 +16,8 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Read config.js to grab redis info
|
||||
var fs = require('fs'),
|
||||
winston = require('winston'),
|
||||
nconf = require('nconf'),
|
||||
pkg = require('./package.json'),
|
||||
url = require('url');
|
||||
@@ -28,11 +28,26 @@ global.env = process.env.NODE_ENV || 'production',
|
||||
// Configuration setup
|
||||
nconf.argv().file({ file: __dirname + '/config.json'});
|
||||
|
||||
winston.remove(winston.transports.Console);
|
||||
winston.add(winston.transports.Console, {
|
||||
colorize:true
|
||||
});
|
||||
|
||||
winston.add(winston.transports.File, {
|
||||
filename:'error.log',
|
||||
level:'error'
|
||||
})
|
||||
|
||||
// TODO: remove once https://github.com/flatiron/winston/issues/280 is fixed
|
||||
winston.err = function(err) {
|
||||
winston.error(err.stack);
|
||||
};
|
||||
|
||||
// Log GNU copyright info along with server info
|
||||
console.log('Info: NodeBB v' + pkg.version + ' Copyright (C) 2013 DesignCreatePlay Inc.');
|
||||
console.log('Info: This program comes with ABSOLUTELY NO WARRANTY.');
|
||||
console.log('Info: This is free software, and you are welcome to redistribute it under certain conditions.');
|
||||
console.log('Info: ===');
|
||||
winston.info('NodeBB v' + pkg.version + ' Copyright (C) 2013 DesignCreatePlay Inc.');
|
||||
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('===');
|
||||
|
||||
if(nconf.get('upgrade')) {
|
||||
require('./src/upgrade').upgrade();
|
||||
@@ -41,8 +56,8 @@ if(nconf.get('upgrade')) {
|
||||
nconf.set('upload_url', nconf.get('url') + 'uploads/');
|
||||
global.nconf = nconf;
|
||||
|
||||
console.log('Info: Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
||||
console.log('Info: Base Configuration OK.');
|
||||
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.');
|
||||
|
||||
// TODO: Replace this with nconf-redis
|
||||
var meta = require('./src/meta.js');
|
||||
@@ -84,10 +99,10 @@ if(nconf.get('upgrade')) {
|
||||
|
||||
//setup scripts to be moved outside of the app in future.
|
||||
function setup_categories() {
|
||||
console.log('Info: Checking categories...');
|
||||
winston.info('Checking categories...');
|
||||
categories.getAllCategories(function(data) {
|
||||
if (data.categories.length === 0) {
|
||||
console.log('Info: Setting up default categories...');
|
||||
winston.info('Setting up default categories...');
|
||||
|
||||
fs.readFile(config.ROOT_DIRECTORY + '/install/data/categories.json', function(err, default_categories) {
|
||||
default_categories = JSON.parse(default_categories);
|
||||
@@ -98,21 +113,24 @@ if(nconf.get('upgrade')) {
|
||||
});
|
||||
|
||||
|
||||
console.log('Info: Hardcoding uid 1 as an admin');
|
||||
winston.info('Hardcoding uid 1 as an admin');
|
||||
var user = require('./src/user.js');
|
||||
user.makeAdministrator(1);
|
||||
|
||||
|
||||
} else {
|
||||
console.log('Info: Categories OK. Found ' + data.categories.length + ' categories.');
|
||||
winston.info('Categories OK. Found ' + data.categories.length + ' categories.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setup_categories();
|
||||
}(global.configuration));
|
||||
});
|
||||
} else {
|
||||
// New install, ask setup questions
|
||||
if (nconf.get('setup')) console.log('Info: NodeBB Setup Triggered via Command Line');
|
||||
else console.log('Info: Configuration not found, starting NodeBB setup');
|
||||
if (nconf.get('setup')) winston.info('NodeBB Setup Triggered via Command Line');
|
||||
else winston.info('Configuration not found, starting NodeBB setup');
|
||||
|
||||
var install = require('./src/install');
|
||||
|
||||
@@ -124,7 +142,7 @@ if(nconf.get('upgrade')) {
|
||||
|
||||
install.setup(function(err) {
|
||||
if (err) {
|
||||
console.log('Error: There was a problem completing NodeBB setup: ', err.message);
|
||||
winston.error('There was a problem completing NodeBB setup: ', err.message);
|
||||
} else {
|
||||
if (!nconf.get('setup')) {
|
||||
process.stdout.write(
|
||||
@@ -132,7 +150,7 @@ if(nconf.get('upgrade')) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "nodebb",
|
||||
"license": "GPLv3 or later",
|
||||
"description": "NodeBB Forum",
|
||||
"version": "0.0.4",
|
||||
"version": "0.0.5",
|
||||
"homepage": "http://www.nodebb.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -33,7 +33,8 @@
|
||||
"sitemap": "~0.6.0",
|
||||
"cheerio": "~0.12.0",
|
||||
"request": "~2.25.0",
|
||||
"reds": "~0.2.4"
|
||||
"reds": "~0.2.4",
|
||||
"winston": "~0.7.2"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/designcreateplay/NodeBB/issues"
|
||||
|
||||
@@ -197,6 +197,12 @@ footer.footer {
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.account-block {
|
||||
div {
|
||||
padding-bottom:10px;
|
||||
}
|
||||
}
|
||||
|
||||
.account-picture-block{
|
||||
display:inline-block;
|
||||
vertical-align:top;
|
||||
@@ -213,7 +219,6 @@ footer.footer {
|
||||
|
||||
.user-profile-picture {
|
||||
width:128px;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.user-picture-label {
|
||||
@@ -392,7 +397,7 @@ body .navbar .nodebb-inline-block {
|
||||
#admin-redis-info {
|
||||
span {
|
||||
display:inline-block;
|
||||
width:200px;
|
||||
width:220px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,7 +834,7 @@ body .navbar .nodebb-inline-block {
|
||||
.form-search {
|
||||
float: left;
|
||||
margin-top: 5px;
|
||||
margin-bottom:0px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.search-result-post {
|
||||
|
||||
@@ -117,8 +117,6 @@
|
||||
|
||||
.topic-title {
|
||||
width: auto;
|
||||
white-space: nowrap;
|
||||
text-overflow:ellipsis;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
@@ -26,6 +26,7 @@ var ajaxify = {};
|
||||
};
|
||||
|
||||
ajaxify.go = function(url, callback, template, quiet) {
|
||||
$(window).off('scroll');
|
||||
// leave room and join global
|
||||
app.enter_room('global');
|
||||
|
||||
|
||||
@@ -5,11 +5,12 @@ var socket,
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
var showWelcomeMessage = false;
|
||||
|
||||
function loadConfig() {
|
||||
|
||||
$.ajax({
|
||||
url: RELATIVE_PATH + '/config.json?v=' + new Date().getTime(),
|
||||
url: RELATIVE_PATH + '/api/config',
|
||||
success: function(data) {
|
||||
API_URL = data.api_url;
|
||||
|
||||
@@ -28,10 +29,6 @@ var socket,
|
||||
socket.on('event:alert', function(data) {
|
||||
app.alert(data);
|
||||
});
|
||||
|
||||
socket.on('event:consolelog', function(data) {
|
||||
console.log(data);
|
||||
});
|
||||
|
||||
socket.on('connect', function(data){
|
||||
if(reconnecting) {
|
||||
@@ -285,8 +282,9 @@ var socket,
|
||||
timeout: 5000
|
||||
});
|
||||
}
|
||||
|
||||
if(location.href.indexOf('loggedin') !== -1) {
|
||||
|
||||
if(showWelcomeMessage) {
|
||||
showWelcomeMessage = false;
|
||||
if(document.readyState !== 'complete') {
|
||||
$(document).ready(showAlert);
|
||||
} else {
|
||||
@@ -371,6 +369,8 @@ var socket,
|
||||
})
|
||||
});
|
||||
|
||||
showWelcomeMessage = location.href.indexOf('loggedin') !== -1;
|
||||
|
||||
loadConfig();
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
return (parent.attr('data-admin') !== "0");
|
||||
}
|
||||
|
||||
function isUserBanned(element) {
|
||||
var parent = $(element).parents('.users-box');
|
||||
return (parent.attr('data-banned') !== "" && parent.attr('data-banned') !== "0");
|
||||
}
|
||||
|
||||
function getUID(element) {
|
||||
var parent = $(element).parents('.users-box');
|
||||
return parent.attr('data-uid');
|
||||
@@ -34,6 +39,20 @@
|
||||
deleteBtn.show();
|
||||
});
|
||||
|
||||
jQuery('.ban-btn').each(function(index, element) {
|
||||
var banBtn = $(element);
|
||||
var isAdmin = isUserAdmin(banBtn);
|
||||
var isBanned = isUserBanned(banBtn);
|
||||
|
||||
if(isAdmin)
|
||||
banBtn.addClass('disabled');
|
||||
else if(isBanned)
|
||||
banBtn.addClass('btn-warning');
|
||||
else
|
||||
banBtn.removeClass('btn-warning');
|
||||
|
||||
});
|
||||
|
||||
jQuery('.admin-btn').on('click', function() {
|
||||
var adminBtn = $(this);
|
||||
var isAdmin = isUserAdmin(adminBtn);
|
||||
@@ -74,13 +93,38 @@
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
jQuery('.ban-btn').on('click', function() {
|
||||
var banBtn = $(this);
|
||||
var isAdmin = isUserAdmin(banBtn);
|
||||
var isBanned = isUserBanned(banBtn);
|
||||
var parent = banBtn.parents('.users-box');
|
||||
var uid = getUID(banBtn);
|
||||
|
||||
if(!isAdmin) {
|
||||
if(isBanned) {
|
||||
socket.emit('api:admin.user.unbanUser', uid);
|
||||
banBtn.removeClass('btn-warning');
|
||||
parent.attr('data-banned', 0);
|
||||
} else {
|
||||
bootbox.confirm('Do you really want to ban "' + parent.attr('data-username') +'"?', function(confirm) {
|
||||
socket.emit('api:admin.user.banUser', uid);
|
||||
banBtn.addClass('btn-warning');
|
||||
parent.attr('data-banned', 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
jQuery('document').ready(function() {
|
||||
|
||||
var yourid = templates.get('yourid');
|
||||
var timeoutId = 0;
|
||||
var yourid = templates.get('yourid'),
|
||||
timeoutId = 0,
|
||||
loadingMoreUsers = false;
|
||||
|
||||
var url = window.location.href,
|
||||
parts = url.split('/'),
|
||||
@@ -114,8 +158,7 @@
|
||||
socket.removeAllListeners('api:admin.user.search');
|
||||
|
||||
socket.on('api:admin.user.search', function(data) {
|
||||
|
||||
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
|
||||
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
|
||||
users: data
|
||||
}),
|
||||
userListEl = document.querySelector('.users');
|
||||
@@ -139,6 +182,45 @@
|
||||
initUsers();
|
||||
});
|
||||
|
||||
function onUsersLoaded(users) {
|
||||
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({ users: users });
|
||||
$('#users-container').append(html);
|
||||
}
|
||||
|
||||
function loadMoreUsers() {
|
||||
var set = '';
|
||||
if(active === 'latest') {
|
||||
set = 'users:joindate';
|
||||
} else if(active === 'sort-posts') {
|
||||
set = 'users:postcount';
|
||||
} else if(active === 'sort-reputation') {
|
||||
set = 'users:reputation';
|
||||
}
|
||||
|
||||
if(set) {
|
||||
loadingMoreUsers = true;
|
||||
socket.emit('api:users.loadMore', {
|
||||
set: set,
|
||||
after: $('#users-container').children().length
|
||||
}, function(data) {
|
||||
if(data.users.length) {
|
||||
onUsersLoaded(data.users);
|
||||
}
|
||||
loadingMoreUsers = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$('#load-more-users-btn').on('click', loadMoreUsers);
|
||||
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
||||
|
||||
if (document.body.scrollTop > bottom && !loadingMoreUsers) {
|
||||
loadMoreUsers();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
}());
|
||||
@@ -122,10 +122,9 @@
|
||||
}
|
||||
|
||||
$(window).off('scroll').on('scroll', function(ev) {
|
||||
var windowHeight = document.body.offsetHeight - $(window).height(),
|
||||
half = windowHeight / 2;
|
||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
||||
|
||||
if (document.body.scrollTop > half && !loadingMoreTopics) {
|
||||
if (document.body.scrollTop > bottom && !loadingMoreTopics) {
|
||||
loadMoreTopics(cid);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -27,11 +27,15 @@
|
||||
url: RELATIVE_PATH + '/login',
|
||||
data: loginData,
|
||||
success: function(data, textStatus, jqXHR) {
|
||||
$('#login-error-notify').hide();
|
||||
window.location.replace(RELATIVE_PATH + "/?loggedin");
|
||||
if(!data.success) {
|
||||
$('#login-error-notify').html(data.message).show();
|
||||
} else {
|
||||
$('#login-error-notify').hide();
|
||||
window.location.replace(RELATIVE_PATH + "/?loggedin");
|
||||
}
|
||||
},
|
||||
error : function(data, textStatus, jqXHR) {
|
||||
$('#login-error-notify').show().delay(1000).fadeOut(250);
|
||||
$('#login-error-notify').show();
|
||||
},
|
||||
dataType: 'json',
|
||||
async: true,
|
||||
|
||||
@@ -69,10 +69,9 @@
|
||||
}
|
||||
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
var windowHeight = document.body.offsetHeight - $(window).height(),
|
||||
half = windowHeight / 2;
|
||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
||||
|
||||
if (document.body.scrollTop > half && !loadingMoreTopics) {
|
||||
if (document.body.scrollTop > bottom && !loadingMoreTopics) {
|
||||
loadMoreTopics();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -202,10 +202,9 @@
|
||||
|
||||
// Infinite scrolling of posts
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
var windowHeight = document.body.offsetHeight - $(window).height(),
|
||||
half = windowHeight / 2;
|
||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
||||
|
||||
if (document.body.scrollTop > half && !app.infiniteLoaderActive && $('#post-container').children().length) {
|
||||
if (document.body.scrollTop > bottom && !app.infiniteLoaderActive && $('#post-container').children().length) {
|
||||
app.loadMorePosts(tid);
|
||||
}
|
||||
});
|
||||
@@ -255,11 +254,9 @@
|
||||
|
||||
var element = $(this).find('i');
|
||||
if(element.attr('class') == 'icon-star-empty') {
|
||||
element.attr('class', 'icon-star');
|
||||
socket.emit('api:posts.favourite', {pid: pid, room_id: app.current_room});
|
||||
}
|
||||
else {
|
||||
element.attr('class', 'icon-star-empty');
|
||||
socket.emit('api:posts.unfavourite', {pid: pid, room_id: app.current_room});
|
||||
}
|
||||
});
|
||||
@@ -388,7 +385,14 @@
|
||||
});
|
||||
|
||||
socket.on('api:posts.favourite', function(data) {
|
||||
if (data.status !== 'ok' && data.pid) {
|
||||
if (data.status === 'ok' && data.pid) {
|
||||
var favEl = document.querySelector('.post_rep_' + data.pid).nextSibling;
|
||||
if (favEl) favEl.className = 'icon-star';
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:posts.unfavourite', function(data) {
|
||||
if (data.status === 'ok' && data.pid) {
|
||||
var favEl = document.querySelector('.post_rep_' + data.pid).nextSibling;
|
||||
if (favEl) favEl.className = 'icon-star-empty';
|
||||
}
|
||||
|
||||
@@ -84,10 +84,9 @@
|
||||
}
|
||||
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
var windowHeight = document.body.offsetHeight - $(window).height(),
|
||||
half = windowHeight / 2;
|
||||
|
||||
if (document.body.scrollTop > half && !loadingMoreTopics) {
|
||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
||||
|
||||
if (document.body.scrollTop > bottom && !loadingMoreTopics) {
|
||||
loadMoreTopics();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
$(document).ready(function() {
|
||||
var timeoutId = 0;
|
||||
var loadingMoreUsers = false;
|
||||
|
||||
var url = window.location.href,
|
||||
parts = url.split('/'),
|
||||
@@ -74,6 +75,46 @@
|
||||
$(element).html(app.addCommas($(element).html()));
|
||||
});
|
||||
|
||||
function onUsersLoaded(users) {
|
||||
var html = templates.prepare(templates['users'].blocks['users']).parse({ users: users });
|
||||
$('#users-container').append(html);
|
||||
}
|
||||
|
||||
function loadMoreUsers() {
|
||||
var set = '';
|
||||
if(active === 'users-latest' || active === 'users') {
|
||||
set = 'users:joindate';
|
||||
} else if(active === 'users-sort-posts') {
|
||||
set = 'users:postcount';
|
||||
} else if(active === 'users-sort-reputation') {
|
||||
set = 'users:reputation';
|
||||
}
|
||||
|
||||
if(set) {
|
||||
loadingMoreUsers = true;
|
||||
socket.emit('api:users.loadMore', {
|
||||
set: set,
|
||||
after: $('#users-container').children().length
|
||||
}, function(data) {
|
||||
if(data.users.length) {
|
||||
onUsersLoaded(data.users);
|
||||
} else {
|
||||
$('#load-more-users-btn').addClass('disabled');
|
||||
}
|
||||
loadingMoreUsers = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$('#load-more-users-btn').on('click', loadMoreUsers);
|
||||
|
||||
$(window).off('scroll').on('scroll', function() {
|
||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
||||
|
||||
if (document.body.scrollTop > bottom && !loadingMoreUsers) {
|
||||
loadMoreUsers();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}());
|
||||
@@ -299,22 +299,22 @@ define(['taskbar'], function(taskbar) {
|
||||
titleEl.value = titleEl.value.trim();
|
||||
bodyEl.value = bodyEl.value.trim();
|
||||
|
||||
if (titleEl.value.length < 3) {
|
||||
if (titleEl.value.length < config.minimumTitleLength) {
|
||||
return app.alert({
|
||||
type: 'error',
|
||||
timeout: 2000,
|
||||
title: 'Title too short',
|
||||
message: "Please enter a longer title. At least 3 characters.",
|
||||
message: "Please enter a longer title. At least " + config.minimumTitleLength+ " characters.",
|
||||
alert_id: 'post_error'
|
||||
});
|
||||
}
|
||||
|
||||
if (bodyEl.value.length < 8) {
|
||||
if (bodyEl.value.length < config.minimumPostLength) {
|
||||
return app.alert({
|
||||
type: 'error',
|
||||
timeout: 2000,
|
||||
title: 'Content too short',
|
||||
message: "Please enter a longer post. At least 8 characters.",
|
||||
message: "Please enter a longer post. At least " + config.minimumPostLength + " characters.",
|
||||
alert_id: 'post_error'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,13 +17,16 @@
|
||||
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span2" style="text-align: center; margin-bottom:20px;">
|
||||
<div class="span2 account-block" style="text-align: center; margin-bottom:20px;">
|
||||
<div class="account-picture-block">
|
||||
<img src="{picture}" class="user-profile-picture img-polaroid"/>
|
||||
</div>
|
||||
<div class="account-online-status">
|
||||
<span><i class="icon-circle-blank"></i> <span>offline</span></span>
|
||||
</div>
|
||||
<div class="{show_banned}">
|
||||
<span class="label label-important">banned</span>
|
||||
</div>
|
||||
<div id="user-actions">
|
||||
<a id="follow-btn" href="#" class="btn hide">Follow</a>
|
||||
<a id="unfollow-btn" href="#" class="btn hide">Unfollow</a>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<hr/>
|
||||
<span>Total Connections Received</span> <span class="text-right">{total_connections_received}</span><br/>
|
||||
<span>Total Commands Processed</span> <span class="text-right">{total_commands_processed}</span><br/>
|
||||
<span>Instantaneous Ops. Per Second</span> <span class="text-right">{instantaneous_ops_per_sec}</span><br/>
|
||||
<hr/>
|
||||
<span>Keyspace Hits</span> <span class="text-right">{keyspace_hits}</span><br/>
|
||||
<span>Keyspace Misses</span> <span class="text-right">{keyspace_misses}</span><br/>
|
||||
|
||||
@@ -48,6 +48,16 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form>
|
||||
<h3>Post Settings</h3>
|
||||
<div class="alert alert-notify">
|
||||
<strong>Post Delay</strong><br /> <input type="text" class="" value="10000" data-field="postDelay"><br />
|
||||
<strong>Minimum Title Length</strong><br /> <input type="text" class="" value="3" data-field="minimumTitleLength"><br />
|
||||
<strong>Minimum Post Length</strong><br /> <input type="text" class="" value="8" data-field="minimumPostLength"><br />
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<button class="btn btn-large btn-primary" id="save">Save</button>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
<span id="user-notfound-notify" class="label label-important hide">User not found!</span><br/>
|
||||
</div>
|
||||
|
||||
<ul class="users">
|
||||
<ul id="users-container" class="users">
|
||||
<!-- BEGIN users -->
|
||||
<div class="users-box" data-uid="{users.uid}" data-admin="{users.administrator}" data-username="{users.username}">
|
||||
<div class="users-box" data-uid="{users.uid}" data-admin="{users.administrator}" data-username="{users.username}" data-banned="{users.banned}">
|
||||
<a href="/users/{users.userslug}">
|
||||
<img src="{users.picture}" class="img-polaroid"/>
|
||||
</a>
|
||||
@@ -37,10 +37,16 @@
|
||||
<div>
|
||||
<a href="#" class="btn delete-btn btn-danger">Delete</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#" class="btn ban-btn">Ban</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END users -->
|
||||
</ul>
|
||||
|
||||
<div class="text-center {loadmore_display}">
|
||||
<button id="load-more-users-btn" class="btn">Load More</button>
|
||||
</div>
|
||||
<input type="hidden" template-variable="yourid" value="{yourid}" />
|
||||
|
||||
|
||||
|
||||
@@ -62,11 +62,12 @@
|
||||
<li><a href="#"><i class="icon-refresh icon-spin"></i> Loading Notifications</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<form id="search-form"
|
||||
class="form-search form-inline" action="" method="GET">
|
||||
<input type="text" name="query" class="input-medium search-query">
|
||||
<button type="submit" class="btn hide">Search</button>
|
||||
</form>
|
||||
<li>
|
||||
<form id="search-form" class="form-search form-inline" action="" method="GET">
|
||||
<input type="text" name="query" class="input-medium search-query">
|
||||
<button type="submit" class="btn hide">Search</button>
|
||||
</form>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -110,7 +110,6 @@
|
||||
contentEl.addEventListener('click', function(e) {
|
||||
if (e.target.hasAttribute('data-path')) {
|
||||
var href = 'install/' + e.target.getAttribute('data-path');
|
||||
console.log(href);
|
||||
if (!e.target.disabled) ajaxify.go(href);
|
||||
}
|
||||
}, false);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<button class="btn btn-primary" id="login" type="submit">Login</button> <a href="/reset">Forgot Password?</a>
|
||||
</form>
|
||||
|
||||
<span id="login-error-notify" class="label label-important hide">Invalid username/password</span><br/>
|
||||
<div id="login-error-notify" class="alert alert-danger hide">Invalid username/password</div>
|
||||
</div>
|
||||
|
||||
<div class="well span6 {alternate_logins:display}">
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
<i class="icon-star"></i><span class="user_rep_{posts.uid} formatted-number">{posts.user_rep}</span>
|
||||
<div id="ids_{posts.pid}_{posts.uid}" class="chat hidden-phone" title="Chat"><i class="icon-comment"></i></div>
|
||||
</div>
|
||||
<span class="label label-important {posts.show_banned}">banned</span>
|
||||
</div>
|
||||
<div class="span11 span12-tablet">
|
||||
<div class="post-block">
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<span id="user-notfound-notify" class="label label-important hide">User not found!</span><br/>
|
||||
</div>
|
||||
|
||||
<ul class="users">
|
||||
<ul id="users-container" class="users">
|
||||
<!-- BEGIN users -->
|
||||
<div class="users-box">
|
||||
<a href="/users/{users.userslug}">
|
||||
@@ -36,4 +36,8 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="text-center {loadmore_display}">
|
||||
<button id="load-more-users-btn" class="btn">Load More</button>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="{relative_path}/src/forum/users.js"></script>
|
||||
@@ -45,7 +45,7 @@ var RDB = require('./../redis.js'),
|
||||
|
||||
UserAdmin.deleteUser = function(uid, theirid, socket) {
|
||||
user.isAdministrator(uid, function(amIAdmin) {
|
||||
user.isAdministrator(theirid, function(areTheyAdmin){
|
||||
user.isAdministrator(theirid, function(areTheyAdmin) {
|
||||
if(amIAdmin && !areTheyAdmin) {
|
||||
user.delete(theirid, function(data) {
|
||||
|
||||
@@ -58,8 +58,39 @@ var RDB = require('./../redis.js'),
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
UserAdmin.banUser = function(uid, theirid, socket) {
|
||||
user.isAdministrator(uid, function(amIAdmin) {
|
||||
user.isAdministrator(theirid, function(areTheyAdmin) {
|
||||
if(amIAdmin && !areTheyAdmin) {
|
||||
user.ban(theirid, function(err, result) {
|
||||
|
||||
socket.emit('event:alert', {
|
||||
title: 'User Banned',
|
||||
message: 'This user is banned!',
|
||||
type: 'success',
|
||||
timeout: 2000
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
UserAdmin.unbanUser = function(uid, theirid, socket) {
|
||||
user.isAdministrator(uid, function(amIAdmin) {
|
||||
if(amIAdmin) {
|
||||
user.unban(theirid, function(err, result) {
|
||||
socket.emit('event:alert', {
|
||||
title: 'User Unbanned',
|
||||
message: 'This user is unbanned!',
|
||||
type: 'success',
|
||||
timeout: 2000
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ var RDB = require('./redis.js'),
|
||||
utils = require('./../public/src/utils.js'),
|
||||
user = require('./user.js'),
|
||||
async = require('async'),
|
||||
topics = require('./topics.js');
|
||||
topics = require('./topics.js'),
|
||||
winston = require('winston');
|
||||
|
||||
(function(Categories) {
|
||||
|
||||
@@ -65,7 +66,6 @@ var RDB = require('./redis.js'),
|
||||
categoryData.moderators = moderators;
|
||||
categoryData.show_sidebar = 'hidden';
|
||||
categoryData.no_topics_message = 'show';
|
||||
|
||||
callback(null, categoryData);
|
||||
});
|
||||
} else {
|
||||
@@ -156,7 +156,7 @@ var RDB = require('./redis.js'),
|
||||
break;
|
||||
}
|
||||
}
|
||||
callback(allread);
|
||||
callback(allread);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -187,8 +187,9 @@ var RDB = require('./redis.js'),
|
||||
|
||||
Categories.getRecentReplies = function(cid, count, callback) {
|
||||
RDB.zrevrange('categories:recent_posts:cid:' + cid, 0, (count<10)?10:count, function(err, pids) {
|
||||
|
||||
if(err) {
|
||||
console.log(err);
|
||||
winston.err(err);
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
@@ -198,11 +199,11 @@ var RDB = require('./redis.js'),
|
||||
return;
|
||||
}
|
||||
|
||||
posts.getPostSummaryByPids(pids, function(posts) {
|
||||
if(posts.length > count) {
|
||||
posts = posts.slice(0, count);
|
||||
posts.getPostSummaryByPids(pids, function(postData) {
|
||||
if(postData.length > count) {
|
||||
postData = postData.slice(0, count);
|
||||
}
|
||||
callback(posts);
|
||||
callback(postData);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -222,12 +223,12 @@ var RDB = require('./redis.js'),
|
||||
if(!err) {
|
||||
callback(null, 1)
|
||||
} else {
|
||||
console.log(err);
|
||||
winston.err(err);
|
||||
callback(err, null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log(err);
|
||||
winston.err(err);
|
||||
callback(err, null);
|
||||
}
|
||||
});
|
||||
@@ -249,7 +250,7 @@ var RDB = require('./redis.js'),
|
||||
if(err === null)
|
||||
callback(data);
|
||||
else
|
||||
console.log(err);
|
||||
winston.err(err);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -278,7 +279,7 @@ var RDB = require('./redis.js'),
|
||||
}
|
||||
|
||||
Categories.hasReadCategory(cid, current_user, function(hasRead) {
|
||||
categoryData['badgeclass'] = (parseInt(categoryData.topic_count,10) === 0 || (hasRead && current_user != 0)) ? '' : 'badge-important';
|
||||
categoryData['badgeclass'] = (parseInt(categoryData.topic_count, 10) === 0 || (hasRead && current_user != 0)) ? '' : 'badge-important';
|
||||
|
||||
categories.push(categoryData);
|
||||
callback(null);
|
||||
@@ -288,7 +289,7 @@ var RDB = require('./redis.js'),
|
||||
|
||||
async.eachSeries(cids, getCategory, function(err) {
|
||||
if(err) {
|
||||
console.log(err);
|
||||
winston.err(err);
|
||||
callback(null);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13,11 +13,6 @@ var RDB = require('./redis.js'),
|
||||
type: 'error',
|
||||
timeout: 5000
|
||||
});
|
||||
|
||||
socket.emit('api:posts.favourite', {
|
||||
status: 'error',
|
||||
pid: pid
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,15 +23,19 @@ var RDB = require('./redis.js'),
|
||||
RDB.sadd('pid:' + pid + ':users_favourited', uid);
|
||||
RDB.hincrby('post:' + pid, 'reputation', 1);
|
||||
|
||||
if (uid !== uid_of_poster)
|
||||
user.incrementUserFieldBy(uid_of_poster, 'reputation', 1);
|
||||
if (uid !== uid_of_poster) {
|
||||
user.incrementUserFieldBy(uid_of_poster, 'reputation', 1, function(err, newreputation) {
|
||||
RDB.zadd('users:reputation', newreputation, uid_of_poster);
|
||||
});
|
||||
}
|
||||
|
||||
if (room_id) {
|
||||
io.sockets.in(room_id).emit('event:rep_up', {uid: uid !== uid_of_poster ? uid_of_poster : 0, pid: pid});
|
||||
}
|
||||
|
||||
socket.emit('api:posts.favourite', {
|
||||
status: 'ok'
|
||||
status: 'ok',
|
||||
pid: pid
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -63,12 +62,20 @@ var RDB = require('./redis.js'),
|
||||
RDB.srem('pid:' + pid + ':users_favourited', uid);
|
||||
RDB.hincrby('post:' + pid, 'reputation', -1);
|
||||
|
||||
if (uid !== uid_of_poster)
|
||||
user.incrementUserFieldBy(uid_of_poster, 'reputation', -1);
|
||||
if (uid !== uid_of_poster) {
|
||||
user.incrementUserFieldBy(uid_of_poster, 'reputation', -1, function(err, newreputation) {
|
||||
RDB.zadd('users:reputation', newreputation, uid_of_poster);
|
||||
});
|
||||
}
|
||||
|
||||
if (room_id) {
|
||||
io.sockets.in(room_id).emit('event:rep_down', {uid: uid !== uid_of_poster ? uid_of_poster : 0, pid: pid});
|
||||
}
|
||||
|
||||
socket.emit('api:posts.unfavourite', {
|
||||
status: 'ok',
|
||||
pid: pid
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
posts = require('./posts.js'),
|
||||
topics = require('./topics.js'),
|
||||
fs = require('fs'),
|
||||
rss = require('node-rss');
|
||||
rss = require('node-rss'),
|
||||
winston = require('winston');
|
||||
|
||||
function saveFeed(location, feed) {
|
||||
fs.writeFile(location, rss.getFeedXML(feed), function (err) {
|
||||
if(err) {
|
||||
console.log(err);
|
||||
winston.err(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -32,7 +33,7 @@
|
||||
var cache_time_in_seconds = 60;
|
||||
|
||||
topics.getTopicWithPosts(tid, 0, function(err, topicData) {
|
||||
if (err) console.log('Error: Problem saving topic RSS feed', err);
|
||||
if (err) winston.error('Problem saving topic RSS feed', err.stack);
|
||||
|
||||
var location = '/topic/' + topicData.slug,
|
||||
xml_url = '/topic/' + tid + '.rss';
|
||||
@@ -69,7 +70,7 @@
|
||||
Feed.updateCategory = function(cid) {
|
||||
categories.getCategoryById(cid, 0, function(err, categoryData) {
|
||||
if (err) {
|
||||
console.log('Error: Could not update RSS feed for category ' + cid);
|
||||
winston.error('Could not update RSS feed for category ' + cid, err.stack);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ var async = require('async'),
|
||||
fs = require('fs'),
|
||||
url = require('url'),
|
||||
path = require('path'),
|
||||
meta = require('./meta'),
|
||||
install = {
|
||||
questions: [
|
||||
'base_url|Publically accessible URL of this installation? (http://localhost)',
|
||||
@@ -78,12 +79,16 @@ var async = require('async'),
|
||||
port: config.port
|
||||
},
|
||||
api_url: protocol + '//' + host + (config.use_port ? ':' + config.port : '') + relative_path + '/api/',
|
||||
relative_path: relative_path
|
||||
relative_path: relative_path
|
||||
};
|
||||
|
||||
server_conf.base_url = protocol + '//' + host;
|
||||
server_conf.relative_path = relative_path;
|
||||
server_conf.imgurClientID = '';
|
||||
|
||||
meta.config.set('postDelay', 10000);
|
||||
meta.config.set('minimumPostLength', 8);
|
||||
meta.config.set('minimumTitleLength', 3);
|
||||
|
||||
install.save(server_conf, client_conf, callback);
|
||||
});
|
||||
|
||||
15
src/login.js
15
src/login.js
@@ -2,7 +2,8 @@
|
||||
var user = require('./user.js'),
|
||||
bcrypt = require('bcrypt'),
|
||||
RDB = require('./redis.js'),
|
||||
path = require('path');
|
||||
path = require('path'),
|
||||
winston = require('winston');
|
||||
|
||||
(function(Login){
|
||||
|
||||
@@ -24,10 +25,16 @@ var user = require('./user.js'),
|
||||
});
|
||||
}
|
||||
|
||||
user.getUserField(uid, 'password', function(user_password) {
|
||||
bcrypt.compare(password, user_password, function(err, res) {
|
||||
user.getUserFields(uid, ['password', 'banned'], function(userData) {
|
||||
if(userData.banned && userData.banned === '1') {
|
||||
return next({
|
||||
status: "error",
|
||||
message: "user-banned"
|
||||
});
|
||||
}
|
||||
bcrypt.compare(password, userData.password, function(err, res) {
|
||||
if(err) {
|
||||
console.log(err);
|
||||
winston.err(err);
|
||||
next({
|
||||
status: "error",
|
||||
message: 'bcrypt compare error'
|
||||
|
||||
@@ -9,6 +9,7 @@ var utils = require('./../public/src/utils.js'),
|
||||
get: function(callback) {
|
||||
RDB.hgetall('config', function(err, config) {
|
||||
if (!err) {
|
||||
config = config || {};
|
||||
config.status = 'ok';
|
||||
callback(config);
|
||||
} else {
|
||||
@@ -18,9 +19,13 @@ var utils = require('./../public/src/utils.js'),
|
||||
}
|
||||
});
|
||||
},
|
||||
getFields: function(fields, callback) {
|
||||
RDB.hmgetObject('config', fields, callback);
|
||||
},
|
||||
set: function(field, value, callback) {
|
||||
RDB.hset('config', field, value, function(err, res) {
|
||||
callback(err);
|
||||
if(callback)
|
||||
callback(err, res);
|
||||
});
|
||||
},
|
||||
remove: function(field) {
|
||||
@@ -76,7 +81,7 @@ var utils = require('./../public/src/utils.js'),
|
||||
var title;
|
||||
|
||||
if (err) title = global.config.title || 'NodeBB';
|
||||
else title = (values.notifCount > 0 ? '(' + values.notifCount + ') ' : '') + (values.title ? values.title + ' | ' : '') + global.config.title || 'NodeBB';
|
||||
else title = (values.notifCount > 0 ? '(' + values.notifCount + ') ' : '') + (values.title ? values.title + ' | ' : '') + (global.config.title || 'NodeBB');
|
||||
|
||||
callback(null, title);
|
||||
});
|
||||
|
||||
@@ -2,12 +2,13 @@ var fs = require('fs'),
|
||||
path = require('path'),
|
||||
RDB = require('./redis.js'),
|
||||
async = require('async'),
|
||||
winston = require('winston'),
|
||||
plugins = {
|
||||
libraries: [],
|
||||
loadedHooks: {},
|
||||
init: function() {
|
||||
if (this.initialized) return;
|
||||
if (global.env === 'development') console.log('Info: [plugins] Initializing plugins system');
|
||||
if (global.env === 'development') winston.info('[plugins] Initializing plugins system');
|
||||
|
||||
var _self = this;
|
||||
|
||||
@@ -32,12 +33,12 @@ var fs = require('fs'),
|
||||
_self.registerHook(pluginData.id, pluginData.hooks[x]);
|
||||
}
|
||||
}
|
||||
if (global.env === 'development') console.log('Info: [plugins] Loaded plugin: ' + pluginData.id);
|
||||
if (global.env === 'development') winston.info('[plugins] Loaded plugin: ' + pluginData.id);
|
||||
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
if (global.env === 'development') console.log('Info: [plugins] Plugin \'' + plugin + '\' not found');
|
||||
if (global.env === 'development') winston.info('[plugins] Plugin \'' + plugin + '\' not found');
|
||||
next(); // Ignore this plugin silently
|
||||
}
|
||||
})
|
||||
@@ -45,11 +46,11 @@ var fs = require('fs'),
|
||||
}
|
||||
], function(err) {
|
||||
if (err) {
|
||||
if (global.env === 'development') console.log('Info: [plugins] NodeBB encountered a problem while loading plugins', err.message);
|
||||
if (global.env === 'development') winston.info('[plugins] NodeBB encountered a problem while loading plugins', err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (global.env === 'development') console.log('Info: [plugins] Plugins OK');
|
||||
if (global.env === 'development') winston.info('[plugins] Plugins OK');
|
||||
});
|
||||
},
|
||||
initialized: false,
|
||||
@@ -66,7 +67,7 @@ var fs = require('fs'),
|
||||
if (data.hook && data.method) {
|
||||
_self.loadedHooks[data.hook] = _self.loadedHooks[data.hook] || [];
|
||||
_self.loadedHooks[data.hook].push([id, data.method]);
|
||||
if (global.env === 'development') console.log('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;
|
||||
},
|
||||
fireHook: function(hook, args, callback) {
|
||||
@@ -75,7 +76,7 @@ var fs = require('fs'),
|
||||
hookList = this.loadedHooks[hook];
|
||||
|
||||
if (hookList && Array.isArray(hookList)) {
|
||||
if (global.env === 'development') console.log('Info: [plugins] Firing hook: \'' + hook + '\'');
|
||||
if (global.env === 'development') winston.info('[plugins] Firing hook: \'' + hook + '\'');
|
||||
var hookType = hook.split(':')[0];
|
||||
switch(hookType) {
|
||||
case 'filter':
|
||||
@@ -94,7 +95,7 @@ var fs = require('fs'),
|
||||
}
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
if (global.env === 'development') console.log('Info: [plugins] Problem executing hook: ' + hook);
|
||||
if (global.env === 'development') winston.info('[plugins] Problem executing hook: ' + hook);
|
||||
}
|
||||
|
||||
callback(returnVal);
|
||||
@@ -109,7 +110,7 @@ var fs = require('fs'),
|
||||
) {
|
||||
_self.libraries[hookObj[0]][hookObj[1]].apply(_self.libraries[hookObj[0]], args);
|
||||
} else {
|
||||
if (global.env === 'development') console.log('Info: [plugins] Expected method \'' + hookObj[1] + '\' in plugin \'' + hookObj[0] + '\' not found, skipping.');
|
||||
if (global.env === 'development') winston.info('[plugins] Expected method \'' + hookObj[1] + '\' in plugin \'' + hookObj[0] + '\' not found, skipping.');
|
||||
}
|
||||
});
|
||||
break;
|
||||
@@ -129,13 +130,13 @@ var fs = require('fs'),
|
||||
toggleActive: function(id, callback) {
|
||||
this.isActive(id, function(err, active) {
|
||||
if (err) {
|
||||
if (global.env === 'development') console.log('Info: [plugins] Could not toggle active state on plugin \'' + id + '\'');
|
||||
if (global.env === 'development') winston.info('[plugins] Could not toggle active state on plugin \'' + id + '\'');
|
||||
return;
|
||||
}
|
||||
|
||||
RDB[(active ? 'srem' : 'sadd')]('plugins:active', id, function(err, success) {
|
||||
if (err) {
|
||||
if (global.env === 'development') console.log('Info: [plugins] Could not toggle active state on plugin \'' + id + '\'');
|
||||
if (global.env === 'development') winston.info('[plugins] Could not toggle active state on plugin \'' + id + '\'');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ var RDB = require('./redis.js'),
|
||||
plugins = require('./plugins'),
|
||||
reds = require('reds'),
|
||||
postSearch = reds.createSearch('nodebbpostsearch'),
|
||||
topicSearch = reds.createSearch('nodebbtopicsearch');
|
||||
topicSearch = reds.createSearch('nodebbtopicsearch'),
|
||||
winston = require('winston');
|
||||
|
||||
(function(PostTools) {
|
||||
PostTools.isMain = function(pid, tid, callback) {
|
||||
@@ -99,7 +100,9 @@ var RDB = require('./redis.js'),
|
||||
|
||||
posts.getPostFields(pid, ['tid', 'uid'], function(postData) {
|
||||
|
||||
user.decrementUserFieldBy(postData.uid, 'postcount', 1);
|
||||
user.decrementUserFieldBy(postData.uid, 'postcount', 1, function(err, postcount) {
|
||||
RDB.zadd('users:postcount', postcount, postData.uid);
|
||||
});
|
||||
|
||||
io.sockets.in('topic_' + postData.tid).emit('event:post_deleted', {
|
||||
pid: pid
|
||||
@@ -109,7 +112,7 @@ var RDB = require('./redis.js'),
|
||||
threadTools.get_latest_undeleted_pid(postData.tid, function(err, pid) {
|
||||
if (err && err.message === 'no-undeleted-pids-found') {
|
||||
threadTools.delete(postData.tid, -1, function(err) {
|
||||
if (err) console.log('Error: Could not delete topic (tid: ' + postData.tid + ')');
|
||||
if (err) winston.error('Could not delete topic (tid: ' + postData.tid + ')', err.stack);
|
||||
});
|
||||
} else {
|
||||
posts.getPostField(pid, 'timestamp', function(timestamp) {
|
||||
|
||||
34
src/posts.js
34
src/posts.js
@@ -10,12 +10,12 @@ var RDB = require('./redis.js'),
|
||||
async = require('async'),
|
||||
plugins = require('./plugins'),
|
||||
reds = require('reds'),
|
||||
postSearch = reds.createSearch('nodebbpostsearch');
|
||||
nconf = require('nconf'),
|
||||
postSearch = reds.createSearch('nodebbpostsearch'),
|
||||
winston = require('winston');
|
||||
|
||||
(function(Posts) {
|
||||
|
||||
Posts.minimumPostLength = 8;
|
||||
|
||||
Posts.getPostsByTid = function(tid, start, end, callback) {
|
||||
RDB.lrange('tid:' + tid + ':posts', start, end, function(err, pids) {
|
||||
|
||||
@@ -32,12 +32,13 @@ var RDB = require('./redis.js'),
|
||||
}
|
||||
|
||||
Posts.addUserInfoToPost = function(post, callback) {
|
||||
user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'postcount', 'picture', 'signature'], function(userData) {
|
||||
user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(userData) {
|
||||
|
||||
post.username = userData.username || 'anonymous';
|
||||
post.userslug = userData.userslug || '';
|
||||
post.user_rep = userData.reputation || 0;
|
||||
post.user_postcount = userData.postcount || 0;
|
||||
post.user_banned = userData.banned || '0';
|
||||
post.picture = userData.picture || require('gravatar').url('', {}, https=global.nconf.get('https'));
|
||||
post.signature = postTools.markdownToHTML(userData.signature, true);
|
||||
|
||||
@@ -55,7 +56,7 @@ var RDB = require('./redis.js'),
|
||||
|
||||
Posts.getPostSummaryByPids = function(pids, callback) {
|
||||
|
||||
var returnData = [];
|
||||
var posts = [];
|
||||
|
||||
function getPostSummary(pid, callback) {
|
||||
Posts.getPostFields(pid, ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'], function(postData) {
|
||||
@@ -70,7 +71,7 @@ var RDB = require('./redis.js'),
|
||||
postData.content = utils.strip_tags(postTools.markdownToHTML(postData.content));
|
||||
|
||||
postData.topicSlug = topicSlug;
|
||||
returnData.push(postData);
|
||||
posts.push(postData);
|
||||
callback(null);
|
||||
});
|
||||
});
|
||||
@@ -80,13 +81,19 @@ var RDB = require('./redis.js'),
|
||||
|
||||
async.eachSeries(pids, getPostSummary, function(err) {
|
||||
if(!err) {
|
||||
callback(returnData);
|
||||
callback(posts);
|
||||
} else {
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Posts.filterBannedPosts = function(posts) {
|
||||
return posts.filter(function(post) {
|
||||
return post.user_banned === '0';
|
||||
});
|
||||
}
|
||||
|
||||
Posts.getPostData = function(pid, callback) {
|
||||
RDB.hgetall('post:' + pid, function(err, data) {
|
||||
if(err === null) {
|
||||
@@ -174,7 +181,7 @@ var RDB = require('./redis.js'),
|
||||
type: 'error',
|
||||
timeout: 2000,
|
||||
title: 'Content too short',
|
||||
message: "Please enter a longer post. At least " + Posts.minimumPostLength + " characters.",
|
||||
message: "Please enter a longer post. At least " + config.minimumPostLength + " characters.",
|
||||
alert_id: 'post_error'
|
||||
});
|
||||
}
|
||||
@@ -182,7 +189,7 @@ var RDB = require('./redis.js'),
|
||||
Posts.emitTooManyPostsAlert = function(socket) {
|
||||
socket.emit('event:alert', {
|
||||
title: 'Too many posts!',
|
||||
message: 'You can only post every '+ (config.post_delay / 1000) + ' seconds.',
|
||||
message: 'You can only post every '+ config.postDelay/1000 + ' seconds.',
|
||||
type: 'error',
|
||||
timeout: 2000
|
||||
});
|
||||
@@ -192,15 +199,14 @@ var RDB = require('./redis.js'),
|
||||
if(content) {
|
||||
content = content.trim();
|
||||
}
|
||||
|
||||
if (!content || content.length < Posts.minimumPostLength) {
|
||||
|
||||
if (!content || content.length < config.minimumPostLength) {
|
||||
callback(new Error('content-too-short'), null);
|
||||
return;
|
||||
}
|
||||
|
||||
user.getUserField(uid, 'lastposttime', function(lastposttime) {
|
||||
|
||||
if(Date.now() - lastposttime < config.post_delay) {
|
||||
if(Date.now() - lastposttime < config.postDelay) {
|
||||
callback(new Error('too-many-posts'), null);
|
||||
return;
|
||||
}
|
||||
@@ -300,7 +306,7 @@ var RDB = require('./redis.js'),
|
||||
|
||||
uploadPostImages(postData, images, function(err, uploadedImages) {
|
||||
if(err) {
|
||||
console.log('Uploading images failed!');
|
||||
winston.error('Uploading images failed!', err.stack);
|
||||
} else {
|
||||
postData.uploadedImages = JSON.stringify(uploadedImages);
|
||||
Posts.setPostField(pid, 'uploadedImages', postData.uploadedImages);
|
||||
|
||||
10
src/redis.js
10
src/redis.js
@@ -1,7 +1,8 @@
|
||||
(function(RedisDB) {
|
||||
var redis = require('redis'),
|
||||
nconf = require('nconf'),
|
||||
utils = require('./../public/src/utils.js');
|
||||
utils = require('./../public/src/utils.js'),
|
||||
winston = require('winston');
|
||||
|
||||
RedisDB.exports = redis.createClient(nconf.get('redis:port'), nconf.get('redis:host'));
|
||||
|
||||
@@ -11,14 +12,9 @@
|
||||
|
||||
RedisDB.exports.handle = function(error) {
|
||||
if (error !== null) {
|
||||
winston.err(error);
|
||||
if (global.env !== 'production') {
|
||||
console.log("################# ERROR LOG ####################");
|
||||
console.log(error);
|
||||
console.log(arguments.callee.name);
|
||||
console.log("################# ERROR LOG ####################");
|
||||
throw new Error(error);
|
||||
} else {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ var user = require('./../user.js'),
|
||||
RDB = require('./../redis.js'),
|
||||
pkg = require('./../../package.json'),
|
||||
categories = require('./../categories.js'),
|
||||
plugins = require('../plugins');
|
||||
plugins = require('../plugins'),
|
||||
winston = require('winston');
|
||||
|
||||
(function(Admin) {
|
||||
Admin.isAdmin = function(req, res, next) {
|
||||
@@ -64,39 +65,30 @@ var user = require('./../user.js'),
|
||||
});
|
||||
|
||||
app.get('/api/admin/users/search', function(req, res) {
|
||||
res.json({search_display: 'block', users: []});
|
||||
res.json({search_display: 'block', loadmore_display:'none', users: []});
|
||||
});
|
||||
|
||||
app.get('/api/admin/users/latest', function(req, res) {
|
||||
user.getUserList(function(data) {
|
||||
data = data.sort(function(a, b) {
|
||||
return b.joindate - a.joindate;
|
||||
});
|
||||
res.json({search_display: 'none', users:data, yourid:req.user.uid});
|
||||
user.getUsers('users:joindate', 0, 49, function(err, data) {
|
||||
res.json({ search_display: 'none', loadmore_display:'block', users:data, yourid:req.user.uid });
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/api/admin/users/sort-posts', function(req, res) {
|
||||
user.getUserList(function(data) {
|
||||
data = data.sort(function(a, b) {
|
||||
return b.postcount - a.postcount;
|
||||
});
|
||||
res.json({search_display: 'none', users:data, yourid:req.user.uid});
|
||||
user.getUsers('users:postcount', 0, 49, function(err, data) {
|
||||
res.json({ search_display: 'none', loadmore_display:'block', users:data, yourid:req.user.uid });
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/api/admin/users/sort-reputation', function(req, res) {
|
||||
user.getUserList(function(data) {
|
||||
data = data.sort(function(a, b) {
|
||||
return b.reputation - a.reputation;
|
||||
});
|
||||
res.json({search_display: 'none', users:data, yourid:req.user.uid});
|
||||
user.getUsers('users:reputation', 0, 49, function(err, data) {
|
||||
res.json({ search_display: 'none', loadmore_display:'block', users:data, yourid:req.user.uid });
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/api/admin/users', function(req, res) {
|
||||
user.getUserList(function(data) {
|
||||
res.json({search_display: 'none', users:data, yourid:req.user.uid});
|
||||
user.getUsers('users:joindate', 0, 49, function(err, data) {
|
||||
res.json({ search_display: 'none', users:data, yourid:req.user.uid });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -139,7 +131,10 @@ var user = require('./../user.js'),
|
||||
|
||||
for(var i in data) {
|
||||
|
||||
try {
|
||||
if(data[i].indexOf(':') == -1 || !data[i])
|
||||
continue;
|
||||
|
||||
try {
|
||||
data[i] = data[i].replace(/:/,"\":\"");
|
||||
var json = "{\"" + data[i] + "\"}";
|
||||
|
||||
@@ -148,7 +143,7 @@ var user = require('./../user.js'),
|
||||
finalData[key] = jsonObject[key];
|
||||
}
|
||||
} catch(err){
|
||||
console.log(err);
|
||||
winston.warn('can\'t parse redis status variable, ignoring', i, data[i], err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ var user = require('./../user.js'),
|
||||
topics = require('./../topics.js'),
|
||||
categories = require('./../categories.js')
|
||||
utils = require('./../../public/src/utils.js'),
|
||||
pkg = require('../../package.json');
|
||||
pkg = require('../../package.json'),
|
||||
meta = require('./../meta.js');
|
||||
|
||||
|
||||
(function(Api) {
|
||||
@@ -13,6 +14,19 @@ var user = require('./../user.js'),
|
||||
res.json(data);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/api/config', function(req, res, next) {
|
||||
meta.config.getFields(['postDelay', 'minimumTitleLength', 'minimumPostLength'], function(err, metaConfig) {
|
||||
if(err) return next();
|
||||
var clientConfig = require('../../public/config.json');
|
||||
|
||||
for (var attrname in metaConfig) {
|
||||
clientConfig[attrname] = metaConfig[attrname];
|
||||
}
|
||||
|
||||
res.json(200, clientConfig);
|
||||
})
|
||||
});
|
||||
|
||||
app.get('/api/home', function(req, res) {
|
||||
var uid = (req.user) ? req.user.uid : 0;
|
||||
@@ -187,7 +201,7 @@ var user = require('./../user.js'),
|
||||
search(topicSearch, function(err, tids) {
|
||||
if(err)
|
||||
return callback(err, null);
|
||||
console.log(tids);
|
||||
|
||||
topics.getTopicsByTids(tids, 0, function(topics) {
|
||||
callback(null, topics);
|
||||
}, 0);
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
passportFacebook = require('passport-facebook').Strategy,
|
||||
login_strategies = [],
|
||||
nconf = require('nconf'),
|
||||
users = require('../user'),
|
||||
user = require('../user'),
|
||||
winston = require('winston'),
|
||||
login_module = require('./../login.js');
|
||||
|
||||
passport.use(new passportLocal(function(user, password, next) {
|
||||
@@ -85,7 +86,7 @@
|
||||
|
||||
app.get('/logout', function(req, res) {
|
||||
if (req.user && req.user.uid > 0) {
|
||||
console.log('info: [Auth] Session ' + req.sessionID + ' logout (uid: ' + req.user.uid + ')');
|
||||
winston.info('[Auth] Session ' + req.sessionID + ' logout (uid: ' + req.user.uid + ')');
|
||||
login_module.logout(req.sessionID, function(logout) {
|
||||
req.logout();
|
||||
app.build_header({ req: req, res: res }, function(err, header) {
|
||||
@@ -132,20 +133,30 @@
|
||||
|
||||
app.get('/reset', function(req, res) {
|
||||
app.build_header({ req: req, res: res }, function(err, header) {
|
||||
console.log(header);
|
||||
res.send(header + templates['reset'] + templates['footer']);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
app.post('/login', passport.authenticate('local'), function(req, res) {
|
||||
res.json({success:1});
|
||||
|
||||
app.post('/login', function(req, res, next) {
|
||||
passport.authenticate('local', function(err, user, info) {
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
if (!user) {
|
||||
return res.send({ success : false, message : info.message });
|
||||
}
|
||||
req.login({
|
||||
uid: user.uid
|
||||
}, function() {
|
||||
res.send({ success : true, message : 'authentication succeeded' });
|
||||
});
|
||||
})(req, res, next);
|
||||
});
|
||||
|
||||
app.post('/register', function(req, res) {
|
||||
users.create(req.body.username, req.body.password, req.body.email, function(err, uid) {
|
||||
user.create(req.body.username, req.body.password, req.body.email, function(err, uid) {
|
||||
|
||||
if (err === null && uid > 0) {
|
||||
if (err === null && uid) {
|
||||
req.login({
|
||||
uid: uid
|
||||
}, function() {
|
||||
|
||||
@@ -4,7 +4,8 @@ var user = require('./../user.js'),
|
||||
fs = require('fs'),
|
||||
utils = require('./../../public/src/utils.js'),
|
||||
path = require('path'),
|
||||
marked = require('marked');
|
||||
marked = require('marked'),
|
||||
winston = require('winston');
|
||||
|
||||
(function(User) {
|
||||
User.create_routes = function(app) {
|
||||
@@ -63,13 +64,13 @@ var user = require('./../user.js'),
|
||||
|
||||
user.get_uid_by_userslug(req.params.userslug, function(uid) {
|
||||
if(!uid) {
|
||||
next();
|
||||
return;
|
||||
return next();
|
||||
}
|
||||
|
||||
|
||||
app.build_header({ req: req, res: res }, function(err, header) {
|
||||
res.send(header + app.create_route('users/'+req.params.userslug, 'account') + templates['footer']);
|
||||
});
|
||||
res.send(header + app.create_route('users/' + req.params.userslug, 'account') + templates['footer']);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -136,7 +137,7 @@ var user = require('./../user.js'),
|
||||
|
||||
fs.unlink(absolutePath, function(err) {
|
||||
if(err) {
|
||||
console.error('[%d] %s', Date.now(), + err);
|
||||
winston.error('[%d] %s', Date.now(), + err);
|
||||
}
|
||||
|
||||
uploadUserPicture(req.user.uid, path.extname(req.files.userPhoto.name), req.files.userPhoto.path, res);
|
||||
@@ -155,8 +156,7 @@ var user = require('./../user.js'),
|
||||
var filename = uid + '-profileimg' + extension;
|
||||
var uploadPath = path.join(global.configuration['ROOT_DIRECTORY'], global.nconf.get('upload_path'), filename);
|
||||
|
||||
// @todo move to proper logging code - this should only be temporary
|
||||
console.log('Info: Attempting upload to: '+ uploadPath);
|
||||
winston.info('Attempting upload to: '+ uploadPath);
|
||||
|
||||
var is = fs.createReadStream(tempPath);
|
||||
var os = fs.createWriteStream(uploadPath);
|
||||
@@ -176,11 +176,7 @@ var user = require('./../user.js'),
|
||||
height: 128
|
||||
}, function(err, stdout, stderr){
|
||||
if (err) {
|
||||
// @todo: better logging method; for now, send to stderr.
|
||||
// ideally, this should be happening in another process
|
||||
// to avoid poisoning the main process on error or allowing a significant problem
|
||||
// to crash the main process
|
||||
console.error('[%d] %s', Date.now(), + err);
|
||||
winston.err(err.message, err.stack);
|
||||
}
|
||||
|
||||
res.json({ path: imageUrl });
|
||||
@@ -189,7 +185,7 @@ var user = require('./../user.js'),
|
||||
});
|
||||
|
||||
os.on('error', function(err) {
|
||||
console.error('[%d] %s', Date.now(), + err);
|
||||
winston.error('[%d] %s', Date.now(), + err);
|
||||
});
|
||||
|
||||
is.pipe(os);
|
||||
@@ -316,49 +312,33 @@ var user = require('./../user.js'),
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/api/users', function(req, res) {
|
||||
user.getUserList(function(data) {
|
||||
data = data.sort(function(a, b) {
|
||||
return b.joindate - a.joindate;
|
||||
});
|
||||
res.json({ search_display: 'none', users: data });
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/api/users', getUsersSortedByJoinDate);
|
||||
app.get('/api/users-sort-posts', getUsersSortedByPosts);
|
||||
app.get('/api/users-sort-reputation', getUsersSortedByReputation);
|
||||
app.get('/api/users-latest', getUsersSortedByJoinDate);
|
||||
app.get('/api/users-search', getUsersForSearch);
|
||||
|
||||
|
||||
function getUsersSortedByJoinDate(req, res) {
|
||||
user.getUsers('users:joindate', 0, 49, function(err, data) {
|
||||
res.json({ search_display: 'none', loadmore_display:'block', users:data });
|
||||
});
|
||||
}
|
||||
|
||||
function getUsersSortedByPosts(req, res) {
|
||||
user.getUserList(function(data) {
|
||||
data = data.sort(function(a, b) {
|
||||
return b.postcount - a.postcount;
|
||||
});
|
||||
res.json({ search_display: 'none', users:data });
|
||||
user.getUsers('users:postcount', 0, 49, function(err, data) {
|
||||
res.json({ search_display: 'none', loadmore_display:'block', users:data });
|
||||
});
|
||||
}
|
||||
|
||||
function getUsersSortedByReputation(req, res) {
|
||||
user.getUserList(function(data) {
|
||||
data = data.sort(function(a, b) {
|
||||
return b.reputation - a.reputation;
|
||||
});
|
||||
res.json({ search_display: 'none', users:data });
|
||||
});
|
||||
}
|
||||
|
||||
function getUsersSortedByJoinDate(req, res) {
|
||||
user.getUserList(function(data) {
|
||||
data = data.sort(function(a, b) {
|
||||
return b.joindate - a.joindate;
|
||||
});
|
||||
res.json({ search_display: 'none', users:data });
|
||||
user.getUsers('users:reputation', 0, 49, function(err, data) {
|
||||
res.json({ search_display: 'none', loadmore_display:'block', users:data });
|
||||
});
|
||||
}
|
||||
|
||||
function getUsersForSearch(req, res) {
|
||||
res.json({ search_display: 'block', users: [] });
|
||||
res.json({ search_display: 'block', loadmore_display:'none', users: [] });
|
||||
}
|
||||
|
||||
function getUserDataByUserSlug(userslug, callerUID, callback) {
|
||||
@@ -391,7 +371,8 @@ var user = require('./../user.js'),
|
||||
else
|
||||
data.emailClass = "hide";
|
||||
|
||||
|
||||
data.show_banned = data.banned === '1'?'':'hide';
|
||||
|
||||
data.uid = uid;
|
||||
data.yourid = callerUID;
|
||||
data.theirid = uid;
|
||||
|
||||
@@ -6,7 +6,8 @@ var RDB = require('./redis.js'),
|
||||
notifications = require('./notifications.js'),
|
||||
posts = require('./posts'),
|
||||
reds = require('reds'),
|
||||
topicSearch = reds.createSearch('nodebbtopicsearch');
|
||||
topicSearch = reds.createSearch('nodebbtopicsearch'),
|
||||
winston = require('winston');
|
||||
|
||||
(function(ThreadTools) {
|
||||
|
||||
@@ -192,7 +193,7 @@ var RDB = require('./redis.js'),
|
||||
|
||||
categories.moveRecentReplies(tid, oldCid, cid, function(err, data) {
|
||||
if(err) {
|
||||
console.log(err);
|
||||
winston.err(err);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -289,7 +290,7 @@ var RDB = require('./redis.js'),
|
||||
var numPosts = posts.length;
|
||||
if(!numPosts)
|
||||
return callback(new Error('no-undeleted-pids-found'));
|
||||
|
||||
|
||||
while(numPosts--) {
|
||||
if(posts[numPosts].deleted !== '1') {
|
||||
callback(null, posts[numPosts].pid);
|
||||
@@ -297,8 +298,7 @@ var RDB = require('./redis.js'),
|
||||
}
|
||||
}
|
||||
|
||||
// If we got here, nothing was found...
|
||||
callback(new Error('no-undeleted-pids-found'));
|
||||
});
|
||||
});
|
||||
}
|
||||
}(exports));
|
||||
@@ -20,7 +20,7 @@ marked.setOptions({
|
||||
|
||||
(function(Topics) {
|
||||
|
||||
Topics.minimumTitleLength = 3;
|
||||
|
||||
|
||||
Topics.getTopicData = function(tid, callback) {
|
||||
RDB.hgetall('topic:' + tid, function(err, data) {
|
||||
@@ -81,6 +81,7 @@ marked.setOptions({
|
||||
for(var i=0; i<postData.length; ++i) {
|
||||
postData[i].fav_star_class = fav_data[postData[i].pid] ? 'icon-star' : 'icon-star-empty';
|
||||
postData[i]['display_moderator_tools'] = (postData[i].uid == current_user || privileges.editable) ? 'show' : 'none';
|
||||
postData[i].show_banned = postData[i].user_banned === '1'?'show':'hide';
|
||||
}
|
||||
|
||||
callback(postData);
|
||||
@@ -149,6 +150,10 @@ marked.setOptions({
|
||||
Topics.getTopicsByTids(topicIds, uid, function(topicData) {
|
||||
unreadTopics.topics = topicData;
|
||||
unreadTopics.nextStart = start + tids.length;
|
||||
if(!topicData || topicData.length === 0)
|
||||
unreadTopics.no_topics_message = 'show';
|
||||
if(uid === 0 || topicData.length === 0)
|
||||
unreadTopics.show_markallread_button = 'hidden';
|
||||
callback(unreadTopics);
|
||||
});
|
||||
}
|
||||
@@ -190,9 +195,9 @@ marked.setOptions({
|
||||
|
||||
function getTopicInfo(topicData, callback) {
|
||||
|
||||
function getUserName(next) {
|
||||
user.getUserField(topicData.uid, 'username', function(username) {
|
||||
next(null, username);
|
||||
function getUserInfo(next) {
|
||||
user.getUserFields(topicData.uid, ['username'], function(userData) {
|
||||
next(null, userData);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -215,17 +220,13 @@ marked.setOptions({
|
||||
});
|
||||
}
|
||||
|
||||
async.parallel([getUserName, hasReadTopic, getTeaserInfo, getPrivileges], function(err, results) {
|
||||
var username = results[0],
|
||||
hasReadTopic = results[1],
|
||||
teaserInfo = results[2],
|
||||
privileges = results[3];
|
||||
|
||||
async.parallel([getUserInfo, hasReadTopic, getTeaserInfo, getPrivileges], function(err, results) {
|
||||
callback({
|
||||
username: username,
|
||||
hasread: hasReadTopic,
|
||||
teaserInfo: teaserInfo,
|
||||
privileges: privileges
|
||||
username: results[0].username,
|
||||
userbanned: results[0].banned,
|
||||
hasread: results[1],
|
||||
teaserInfo: results[2],
|
||||
privileges: results[3]
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -507,10 +508,12 @@ marked.setOptions({
|
||||
user.getUserFields(postData.uid, ['username', 'picture'], function(userData) {
|
||||
var stripped = postData.content,
|
||||
timestamp = postData.timestamp;
|
||||
|
||||
if(postData.content)
|
||||
stripped = utils.strip_tags(postTools.markdownToHTML(postData.content));
|
||||
|
||||
|
||||
if(postData.content) {
|
||||
stripped = postData.content.replace(/>.+\n\n/, '');
|
||||
stripped = utils.strip_tags(postTools.markdownToHTML(stripped));
|
||||
}
|
||||
|
||||
callback(null, {
|
||||
"text": stripped,
|
||||
"username": userData.username,
|
||||
@@ -528,7 +531,7 @@ marked.setOptions({
|
||||
type: 'error',
|
||||
timeout: 2000,
|
||||
title: 'Title too short',
|
||||
message: "Please enter a longer title. At least " + Topics.minimumTitleLength + " characters.",
|
||||
message: "Please enter a longer title. At least " + config.minimumTitleLength + " characters.",
|
||||
alert_id: 'post_error'
|
||||
});
|
||||
}
|
||||
@@ -545,17 +548,17 @@ marked.setOptions({
|
||||
if (uid === 0) {
|
||||
callback(new Error('not-logged-in'), null);
|
||||
return;
|
||||
} else if(!title || title.length < Topics.minimumTitleLength) {
|
||||
} else if(!title || title.length < config.minimumTitleLength) {
|
||||
callback(new Error('title-too-short'), null);
|
||||
return;
|
||||
} else if (!content || content.length < posts.miminumPostLength) {
|
||||
} else if (!content || content.length < config.miminumPostLength) {
|
||||
callback(new Error('content-too-short'), null);
|
||||
return;
|
||||
}
|
||||
|
||||
user.getUserField(uid, 'lastposttime', function(lastposttime) {
|
||||
|
||||
if(Date.now() - lastposttime < config.post_delay) {
|
||||
if(Date.now() - lastposttime < config.postDelay) {
|
||||
callback(new Error('too-many-posts'), null);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var RDB = require('./redis.js'),
|
||||
async = require('async');
|
||||
|
||||
async = require('async'),
|
||||
winston = require('winston');
|
||||
|
||||
|
||||
function upgradeCategory(cid, callback) {
|
||||
@@ -20,7 +20,6 @@ function upgradeCategory(cid, callback) {
|
||||
|
||||
async.each(tids, moveTopic, function(err) {
|
||||
if(!err) {
|
||||
console.log('renaming ' + cid);
|
||||
RDB.rename('temp_categories:' + cid + ':tid', 'categories:' + cid + ':tid');
|
||||
callback(null);
|
||||
}
|
||||
@@ -30,43 +29,70 @@ function upgradeCategory(cid, callback) {
|
||||
|
||||
});
|
||||
} else {
|
||||
console.log('category already upgraded '+ cid);
|
||||
winston.info('category already upgraded '+ cid);
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function upgradeUser(uid, callback) {
|
||||
RDB.hmgetObject('user:' + uid, ['joindate', 'postcount', 'reputation'], function(err, userData) {
|
||||
if(err)
|
||||
return callback(err);
|
||||
|
||||
RDB.zadd('users:joindate', userData.joindate, uid);
|
||||
RDB.zadd('users:postcount', userData.postcount, uid);
|
||||
RDB.zadd('users:reputation', userData.reputation, uid);
|
||||
|
||||
callback(null);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
exports.upgrade = function() {
|
||||
|
||||
console.log('upgrading nodebb now');
|
||||
winston.info('upgrading nodebb now');
|
||||
|
||||
var schema = [
|
||||
function upgradeCategories(next) {
|
||||
console.log('upgrading categories');
|
||||
winston.info('upgrading categories');
|
||||
|
||||
RDB.lrange('categories:cid', 0, -1, function(err, cids) {
|
||||
|
||||
async.each(cids, upgradeCategory, function(err) {
|
||||
if(!err)
|
||||
next(null, 'upgraded categories');
|
||||
else
|
||||
if(!err) {
|
||||
winston.info('upgraded categories');
|
||||
next(null, null);
|
||||
} else {
|
||||
next(err, null);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
function upgradeUsers(next) {
|
||||
console.log('upgrading users');
|
||||
next(null, 'upgraded users');
|
||||
winston.info('upgrading users');
|
||||
|
||||
RDB.lrange('userlist', 0, -1, function(err, uids) {
|
||||
|
||||
async.each(uids, upgradeUser, function(err) {
|
||||
if(!err) {
|
||||
winston.info('upgraded users')
|
||||
next(null, null);
|
||||
} else {
|
||||
next(err, null);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
];
|
||||
|
||||
async.series(schema, function(err, results) {
|
||||
if(!err)
|
||||
console.log('upgrade complete');
|
||||
winston.info('upgrade complete');
|
||||
else
|
||||
console.log(err);
|
||||
winston.err(err);
|
||||
|
||||
process.exit();
|
||||
|
||||
|
||||
69
src/user.js
69
src/user.js
@@ -41,13 +41,14 @@ var utils = require('./../public/src/utils.js'),
|
||||
} else next();
|
||||
}
|
||||
], function(err, results) {
|
||||
if (err) return callback(err, 0); // FIXME: Maintaining the 0 for backwards compatibility. Do we need this?
|
||||
if (err) return callback(err, null);
|
||||
|
||||
RDB.incr('global:next_user_id', function(err, uid) {
|
||||
RDB.handle(err);
|
||||
|
||||
var gravatar = User.createGravatarURLFromEmail(email);
|
||||
|
||||
var timestamp = Date.now();
|
||||
|
||||
RDB.hmset('user:'+uid, {
|
||||
'uid': uid,
|
||||
'username' : username,
|
||||
@@ -58,7 +59,7 @@ var utils = require('./../public/src/utils.js'),
|
||||
'website':'',
|
||||
'email' : email || '',
|
||||
'signature':'',
|
||||
'joindate' : Date.now(),
|
||||
'joindate' : timestamp,
|
||||
'picture': gravatar,
|
||||
'gravatarpicture' : gravatar,
|
||||
'uploadedpicture': '',
|
||||
@@ -66,6 +67,7 @@ var utils = require('./../public/src/utils.js'),
|
||||
'postcount': 0,
|
||||
'lastposttime': 0,
|
||||
'administrator': (uid == 1) ? 1 : 0,
|
||||
'banned': 0,
|
||||
'showemail': 0
|
||||
});
|
||||
|
||||
@@ -83,7 +85,9 @@ var utils = require('./../public/src/utils.js'),
|
||||
io.sockets.emit('user.count', {count: count});
|
||||
});
|
||||
|
||||
RDB.lpush('userlist', uid);
|
||||
RDB.zadd('users:joindate', timestamp, uid);
|
||||
RDB.zadd('users:postcount', 0, uid);
|
||||
RDB.zadd('users:reputation', 0, uid);
|
||||
|
||||
io.sockets.emit('user.latest', {userslug: userslug, username: username});
|
||||
|
||||
@@ -112,7 +116,9 @@ var utils = require('./../public/src/utils.js'),
|
||||
RDB.del('followers:' + uid);
|
||||
RDB.del('following:' + uid);
|
||||
|
||||
RDB.lrem('userlist', 1, uid);
|
||||
RDB.zrem('users:joindate', uid);
|
||||
RDB.zrem('users:postcount', uid);
|
||||
RDB.zrem('users:reputation', uid);
|
||||
|
||||
callback(true);
|
||||
});
|
||||
@@ -121,6 +127,14 @@ var utils = require('./../public/src/utils.js'),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
User.ban = function(uid, callback) {
|
||||
User.setUserField(uid, 'banned', 1, callback);
|
||||
}
|
||||
|
||||
User.unban = function(uid, callback) {
|
||||
User.setUserField(uid, 'banned', 0, callback);
|
||||
}
|
||||
|
||||
User.getUserField = function(uid, field, callback) {
|
||||
RDB.hget('user:' + uid, field, function(err, data) {
|
||||
@@ -185,6 +199,12 @@ var utils = require('./../public/src/utils.js'),
|
||||
});
|
||||
}
|
||||
|
||||
User.filterBannedUsers = function(users) {
|
||||
return users.filter(function(user) {
|
||||
return (!user.banned || user.banned === '0');
|
||||
});
|
||||
}
|
||||
|
||||
User.updateProfile = function(uid, data, callback) {
|
||||
|
||||
var fields = ['email', 'fullname', 'website', 'location', 'birthday', 'signature'];
|
||||
@@ -304,28 +324,29 @@ var utils = require('./../public/src/utils.js'),
|
||||
});
|
||||
}
|
||||
|
||||
User.setUserField = function(uid, field, value) {
|
||||
RDB.hset('user:' + uid, field, value);
|
||||
User.setUserField = function(uid, field, value, callback) {
|
||||
RDB.hset('user:' + uid, field, value, callback);
|
||||
}
|
||||
|
||||
User.setUserFields = function(uid, data) {
|
||||
RDB.hmset('user:' + uid, data);
|
||||
}
|
||||
|
||||
User.incrementUserFieldBy = function(uid, field, value) {
|
||||
RDB.hincrby('user:' + uid, field, value);
|
||||
User.incrementUserFieldBy = function(uid, field, value, callback) {
|
||||
RDB.hincrby('user:' + uid, field, value, callback);
|
||||
}
|
||||
|
||||
User.decrementUserFieldBy = function(uid, field, value) {
|
||||
RDB.hincrby('user:' + uid, field, -value);
|
||||
User.decrementUserFieldBy = function(uid, field, value, callback) {
|
||||
RDB.hincrby('user:' + uid, field, -value, callback);
|
||||
}
|
||||
|
||||
User.getUserList = function(callback) {
|
||||
User.getUsers = function(set, start, stop, callback) {
|
||||
var data = [];
|
||||
|
||||
RDB.lrange('userlist', 0, -1, function(err, uids) {
|
||||
|
||||
RDB.handle(err);
|
||||
|
||||
RDB.zrevrange(set, start, stop, function(err, uids) {
|
||||
if(err) {
|
||||
return callback(err, null);
|
||||
}
|
||||
|
||||
function iterator(uid, callback) {
|
||||
User.getUserData(uid, function(userData) {
|
||||
@@ -336,13 +357,8 @@ var utils = require('./../public/src/utils.js'),
|
||||
});
|
||||
}
|
||||
|
||||
async.each(uids, iterator, function(err) {
|
||||
if(!err) {
|
||||
callback(data);
|
||||
} else {
|
||||
console.log(err);
|
||||
callback(null);
|
||||
}
|
||||
async.eachSeries(uids, iterator, function(err) {
|
||||
callback(err, data);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -401,7 +417,10 @@ var utils = require('./../public/src/utils.js'),
|
||||
User.onNewPostMade = function(uid, tid, pid, timestamp) {
|
||||
User.addPostIdToUser(uid, pid);
|
||||
|
||||
User.incrementUserFieldBy(uid, 'postcount', 1);
|
||||
User.incrementUserFieldBy(uid, 'postcount', 1, function(err, newpostcount) {
|
||||
RDB.zadd('users:postcount', newpostcount, uid);
|
||||
});
|
||||
|
||||
User.setUserField(uid, 'lastposttime', timestamp);
|
||||
|
||||
User.sendPostNotificationToFollowers(uid, tid, pid);
|
||||
@@ -602,7 +621,7 @@ var utils = require('./../public/src/utils.js'),
|
||||
};
|
||||
|
||||
User.latest = function(socket) {
|
||||
RDB.lrange('userlist', 0, 0, function(err, uid) {
|
||||
RDB.zrevrange('users:joindate', 0, 0, function(err, uid) {
|
||||
RDB.handle(err);
|
||||
|
||||
User.getUserFields(uid, ['username', 'userslug'], function(userData) {
|
||||
|
||||
@@ -108,7 +108,6 @@ var express = require('express'),
|
||||
|
||||
// respond with html page
|
||||
if (req.accepts('html')) {
|
||||
|
||||
//res.json('404', { url: req.url });
|
||||
res.redirect(global.nconf.get('relative_path') + '/404');
|
||||
return;
|
||||
@@ -116,7 +115,6 @@ var express = require('express'),
|
||||
|
||||
// respond with json
|
||||
if (req.accepts('json')) {
|
||||
console.log('sending 404 json');
|
||||
res.send({ error: 'Not found' });
|
||||
return;
|
||||
}
|
||||
@@ -126,6 +124,7 @@ var express = require('express'),
|
||||
});
|
||||
|
||||
app.use(function(err, req, res, next) {
|
||||
|
||||
// we may use properties of the error object
|
||||
// here and next(err) appropriately, or if
|
||||
// we possibly recovered from the error, simply next().
|
||||
@@ -401,6 +400,7 @@ var express = require('express'),
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}(WebServer));
|
||||
|
||||
@@ -26,7 +26,8 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
||||
'categories': require('./admin/categories.js'),
|
||||
'user': require('./admin/user.js')
|
||||
},
|
||||
plugins = require('./plugins');
|
||||
plugins = require('./plugins'),
|
||||
winston = require('winston');
|
||||
|
||||
(function(io) {
|
||||
var users = {},
|
||||
@@ -366,7 +367,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
||||
if(err) {
|
||||
if(err.message === 'content-too-short') {
|
||||
posts.emitContentTooShortAlert(socket);
|
||||
} else if(err.messages === 'too-many-posts') {
|
||||
} else if(err.message === 'too-many-posts') {
|
||||
posts.emitTooManyPostsAlert(socket);
|
||||
} else if(err.message === 'reply-error') {
|
||||
socket.emit('event:alert', {
|
||||
@@ -462,7 +463,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
||||
if(!data.title || data.title.length < topics.minimumTitleLength) {
|
||||
topics.emitTitleTooShortAlert(socket);
|
||||
return;
|
||||
} else if (!data.content || data.content.length < posts.minimumPostLength) {
|
||||
} else if (!data.content || data.content.length < require('../public/config.json').minimumPostLength) {
|
||||
posts.emitContentTooShortAlert(socket);
|
||||
return;
|
||||
}
|
||||
@@ -657,12 +658,24 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
||||
var start = data.after,
|
||||
end = start + 9;
|
||||
|
||||
console.log(start, end);
|
||||
topics.getUnreadTopics(uid, start, end, function(unreadTopics) {
|
||||
callback(unreadTopics);
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('api:users.loadMore', function(data, callback) {
|
||||
var start = data.after,
|
||||
end = start + 19;
|
||||
|
||||
user.getUsers(data.set, start, end, function(err, data) {
|
||||
if(err) {
|
||||
winston.err(err);
|
||||
} else {
|
||||
callback({users:data});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('api:admin.topics.getMore', function(data, callback) {
|
||||
topics.getAllTopics(data.limit, data.after, function(topics) {
|
||||
callback(JSON.stringify(topics));
|
||||
@@ -691,14 +704,26 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:admin.user.banUser', function(theirid) {
|
||||
if(uid && uid > 0) {
|
||||
admin.user.banUser(uid, theirid, socket);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:admin.user.unbanUser', function(theirid) {
|
||||
if(uid && uid > 0) {
|
||||
admin.user.unbanUser(uid, theirid, socket);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:admin.user.search', function(username) {
|
||||
if(uid && uid > 0) {
|
||||
user.search(username, function(data) {
|
||||
socket.emit('api:admin.user.search', data);
|
||||
});
|
||||
}
|
||||
else
|
||||
} else {
|
||||
socket.emit('api:admin.user.search', null);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('api:admin.themes.getInstalled', function(callback) {
|
||||
|
||||
Reference in New Issue
Block a user