ban users, closes #125, banning a user hides all posts topics of a user and their profile page becomes inaccessible

v1.18.x
Baris Usakli 12 years ago
parent b0092b68c6
commit 929282a2f7

@ -8,6 +8,11 @@
return (parent.attr('data-admin') !== "0"); 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) { function getUID(element) {
var parent = $(element).parents('.users-box'); var parent = $(element).parents('.users-box');
return parent.attr('data-uid'); return parent.attr('data-uid');
@ -34,6 +39,20 @@
deleteBtn.show(); 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() { jQuery('.admin-btn').on('click', function() {
var adminBtn = $(this); var adminBtn = $(this);
var isAdmin = isUserAdmin(adminBtn); var isAdmin = isUserAdmin(adminBtn);
@ -74,6 +93,30 @@
return false; 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;
});
} }

@ -16,7 +16,7 @@
<ul id="users-container" class="users"> <ul id="users-container" class="users">
<!-- BEGIN 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}"> <a href="/users/{users.userslug}">
<img src="{users.picture}" class="img-polaroid"/> <img src="{users.picture}" class="img-polaroid"/>
</a> </a>
@ -37,6 +37,9 @@
<div> <div>
<a href="#" class="btn delete-btn btn-danger">Delete</a> <a href="#" class="btn delete-btn btn-danger">Delete</a>
</div> </div>
<div>
<a href="#" class="btn ban-btn">Ban</a>
</div>
</div> </div>
<!-- END users --> <!-- END users -->
</ul> </ul>

@ -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
});
});
}
}); });
}; };

@ -55,7 +55,8 @@ var RDB = require('./redis.js'),
} }
function getActiveUsers(next) { function getActiveUsers(next) {
user.getMultipleUserFields(active_users, ['username', 'userslug', 'picture'], function(users) { user.getMultipleUserFields(active_users, ['username', 'userslug', 'picture', 'banned'], function(users) {
users = user.filterBannedUsers(users);
next(null, users); next(null, users);
}); });
} }
@ -66,7 +67,6 @@ var RDB = require('./redis.js'),
categoryData.moderators = moderators; categoryData.moderators = moderators;
categoryData.show_sidebar = 'hidden'; categoryData.show_sidebar = 'hidden';
categoryData.no_topics_message = 'show'; categoryData.no_topics_message = 'show';
callback(null, categoryData); callback(null, categoryData);
}); });
} else { } else {
@ -200,11 +200,12 @@ var RDB = require('./redis.js'),
return; return;
} }
posts.getPostSummaryByPids(pids, function(posts) { posts.getPostSummaryByPids(pids, function(postData) {
if(posts.length > count) { postData = posts.filterBannedPosts(postData);
posts = posts.slice(0, count); if(postData.length > count) {
postData = postData.slice(0, count);
} }
callback(posts); callback(postData);
}); });
}); });
} }

@ -32,12 +32,13 @@ 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'], function(userData) { user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(userData) {
post.username = userData.username || 'anonymous'; post.username = userData.username || 'anonymous';
post.userslug = userData.userslug || ''; post.userslug = userData.userslug || '';
post.user_rep = userData.reputation || 0; post.user_rep = userData.reputation || 0;
post.user_postcount = userData.postcount || 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.picture = userData.picture || require('gravatar').url('', {}, https=global.nconf.get('https'));
post.signature = postTools.markdownToHTML(userData.signature, true); post.signature = postTools.markdownToHTML(userData.signature, true);
@ -55,7 +56,7 @@ var RDB = require('./redis.js'),
Posts.getPostSummaryByPids = function(pids, callback) { Posts.getPostSummaryByPids = function(pids, callback) {
var returnData = []; var posts = [];
function getPostSummary(pid, callback) { function getPostSummary(pid, callback) {
Posts.getPostFields(pid, ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'], function(postData) { 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.content = utils.strip_tags(postTools.markdownToHTML(postData.content));
postData.topicSlug = topicSlug; postData.topicSlug = topicSlug;
returnData.push(postData); posts.push(postData);
callback(null); callback(null);
}); });
}); });
@ -80,13 +81,19 @@ var RDB = require('./redis.js'),
async.eachSeries(pids, getPostSummary, function(err) { async.eachSeries(pids, getPostSummary, function(err) {
if(!err) { if(!err) {
callback(returnData); callback(posts);
} else { } else {
console.log(err); console.log(err);
} }
}); });
}; };
Posts.filterBannedPosts = function(posts) {
return posts.filter(function(post) {
return post.user_banned === '0';
});
}
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) {

@ -6,7 +6,7 @@
passportFacebook = require('passport-facebook').Strategy, passportFacebook = require('passport-facebook').Strategy,
login_strategies = [], login_strategies = [],
nconf = require('nconf'), nconf = require('nconf'),
users = require('../user'), user = require('../user'),
winston = require('winston'), winston = require('winston'),
login_module = require('./../login.js'); login_module = require('./../login.js');
@ -143,9 +143,9 @@
}); });
app.post('/register', function(req, res) { 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({ req.login({
uid: uid uid: uid
}, function() { }, function() {

@ -68,9 +68,15 @@ var user = require('./../user.js'),
return; return;
} }
user.getUserField(uid, 'banned', function(banned) {
if(banned && banned === '1') {
next();
} else {
app.build_header({ req: req, res: res }, function(err, header) { 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']);
}); });
}
});
}); });
}); });
@ -321,18 +327,21 @@ var user = require('./../user.js'),
function getUsersSortedByJoinDate(req, res) { function getUsersSortedByJoinDate(req, res) {
user.getUsers('users:joindate', 0, 49, function(err, data) { user.getUsers('users:joindate', 0, 49, function(err, data) {
data = user.filterBannedUsers(data);
res.json({ search_display: 'none', loadmore_display:'block', users:data }); res.json({ search_display: 'none', loadmore_display:'block', users:data });
}); });
} }
function getUsersSortedByPosts(req, res) { function getUsersSortedByPosts(req, res) {
user.getUsers('users:postcount', 0, 49, function(err, data) { user.getUsers('users:postcount', 0, 49, function(err, data) {
data = user.filterBannedUsers(data);
res.json({ search_display: 'none', loadmore_display:'block', users:data }); res.json({ search_display: 'none', loadmore_display:'block', users:data });
}); });
} }
function getUsersSortedByReputation(req, res) { function getUsersSortedByReputation(req, res) {
user.getUsers('users:reputation', 0, 49, function(err, data) { user.getUsers('users:reputation', 0, 49, function(err, data) {
data = user.filterBannedUsers(data);
res.json({ search_display: 'none', loadmore_display:'block', users:data }); res.json({ search_display: 'none', loadmore_display:'block', users:data });
}); });
} }

@ -291,15 +291,32 @@ var RDB = require('./redis.js'),
if(!numPosts) if(!numPosts)
return callback(new Error('no-undeleted-pids-found')); return callback(new Error('no-undeleted-pids-found'));
while(numPosts--) { posts = posts.reverse();
if(posts[numPosts].deleted !== '1') { lastPostId = 0;
callback(null, posts[numPosts].pid);
function isPostVisible(post, next) {
if(post.deleted !== '1') {
user.getUserField(post.uid, 'banned', function(banned) {
if(banned && banned === '1') {
next(null);
} else {
lastPostId = post.pid
next(post.pid);
return; return;
} }
});
} else {
next(null);
}
} }
// If we got here, nothing was found... async.eachSeries(posts, isPostVisible, function(err) {
if(err) {
callback(null, lastPostId);
} else {
callback(new Error('no-undeleted-pids-found')); callback(new Error('no-undeleted-pids-found'));
}
});
}); });
} }
}(exports)); }(exports));

@ -78,6 +78,8 @@ marked.setOptions({
var fav_data = results[0], var fav_data = results[0],
privileges = results[2]; privileges = results[2];
postData = posts.filterBannedPosts(postData);
for(var i=0; i<postData.length; ++i) { 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].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]['display_moderator_tools'] = (postData[i].uid == current_user || privileges.editable) ? 'show' : 'none';
@ -149,7 +151,9 @@ marked.setOptions({
Topics.getTopicsByTids(topicIds, uid, function(topicData) { Topics.getTopicsByTids(topicIds, uid, function(topicData) {
unreadTopics.topics = topicData; unreadTopics.topics = topicData;
unreadTopics.nextStart = start + tids.length; unreadTopics.nextStart = start + tids.length;
if(uid === 0) if(!topicData || topicData.length === 0)
unreadTopics.no_topics_message = 'show';
if(uid === 0 || topicData.length === 0)
unreadTopics.show_markallread_button = 'hidden'; unreadTopics.show_markallread_button = 'hidden';
callback(unreadTopics); callback(unreadTopics);
}); });
@ -192,9 +196,9 @@ marked.setOptions({
function getTopicInfo(topicData, callback) { function getTopicInfo(topicData, callback) {
function getUserName(next) { function getUserInfo(next) {
user.getUserField(topicData.uid, 'username', function(username) { user.getUserFields(topicData.uid, ['username', 'banned'], function(userData) {
next(null, username); next(null, userData);
}); });
} }
@ -217,24 +221,23 @@ marked.setOptions({
}); });
} }
async.parallel([getUserName, hasReadTopic, getTeaserInfo, getPrivileges], function(err, results) { async.parallel([getUserInfo, hasReadTopic, getTeaserInfo, getPrivileges], function(err, results) {
var username = results[0],
hasReadTopic = results[1],
teaserInfo = results[2],
privileges = results[3];
callback({ callback({
username: username, username: results[0].username,
hasread: hasReadTopic, userbanned: results[0].banned,
teaserInfo: teaserInfo, hasread: results[1],
privileges: privileges teaserInfo: results[2],
privileges: results[3]
}); });
}); });
} }
function isTopicVisible(topicData, topicInfo) { function isTopicVisible(topicData, topicInfo) {
var deleted = parseInt(topicData.deleted, 10) !== 0; var deleted = parseInt(topicData.deleted, 10) !== 0;
return !deleted || (deleted && topicInfo.privileges.view_deleted) || topicData.uid === current_user; var banned = false;
if(topicData.userbanned)
banned = parseInt(topicData.userbanned, 10) !== 0;
return !banned && (!deleted || (deleted && topicInfo.privileges.view_deleted) || topicData.uid === current_user);
} }
function loadTopic(tid, callback) { function loadTopic(tid, callback) {
@ -252,6 +255,7 @@ marked.setOptions({
topicData.relativeTime = utils.relativeTime(topicData.timestamp); topicData.relativeTime = utils.relativeTime(topicData.timestamp);
topicData.username = topicInfo.username; topicData.username = topicInfo.username;
topicData.userbanned = topicInfo.userbanned;
topicData.badgeclass = (topicInfo.hasread && current_user != 0) ? '' : 'badge-important'; topicData.badgeclass = (topicInfo.hasread && current_user != 0) ? '' : 'badge-important';
topicData.teaser_text = topicInfo.teaserInfo.text || '', topicData.teaser_text = topicInfo.teaserInfo.text || '',
topicData.teaser_username = topicInfo.teaserInfo.username || ''; topicData.teaser_username = topicInfo.teaserInfo.username || '';

@ -41,7 +41,7 @@ var utils = require('./../public/src/utils.js'),
} else next(); } else next();
} }
], function(err, results) { ], 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.incr('global:next_user_id', function(err, uid) {
RDB.handle(err); RDB.handle(err);
@ -67,6 +67,7 @@ var utils = require('./../public/src/utils.js'),
'postcount': 0, 'postcount': 0,
'lastposttime': 0, 'lastposttime': 0,
'administrator': (uid == 1) ? 1 : 0, 'administrator': (uid == 1) ? 1 : 0,
'banned': 0,
'showemail': 0 'showemail': 0
}); });
@ -127,6 +128,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) { User.getUserField = function(uid, field, callback) {
RDB.hget('user:' + uid, field, function(err, data) { RDB.hget('user:' + uid, field, function(err, data) {
if(err === null) { if(err === null) {
@ -190,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) { User.updateProfile = function(uid, data, callback) {
var fields = ['email', 'fullname', 'website', 'location', 'birthday', 'signature']; var fields = ['email', 'fullname', 'website', 'location', 'birthday', 'signature'];
@ -309,8 +324,8 @@ var utils = require('./../public/src/utils.js'),
}); });
} }
User.setUserField = function(uid, field, value) { User.setUserField = function(uid, field, value, callback) {
RDB.hset('user:' + uid, field, value); RDB.hset('user:' + uid, field, value, callback);
} }
User.setUserFields = function(uid, data) { User.setUserFields = function(uid, data) {
@ -345,7 +360,6 @@ var utils = require('./../public/src/utils.js'),
async.eachSeries(uids, iterator, function(err) { async.eachSeries(uids, iterator, function(err) {
callback(err, data); callback(err, data);
}); });
}); });
} }

@ -671,6 +671,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
if(err) { if(err) {
winston.err(err); winston.err(err);
} else { } else {
data = user.filterBannedUsers(data);
callback({users:data}); callback({users:data});
} }
}); });
@ -704,14 +705,27 @@ 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) { socket.on('api:admin.user.search', function(username) {
if(uid && uid > 0) { if(uid && uid > 0) {
user.search(username, function(data) { user.search(username, function(data) {
data = user.filterBannedUsers(data);
socket.emit('api:admin.user.search', data); socket.emit('api:admin.user.search', data);
}); });
} } else {
else
socket.emit('api:admin.user.search', null); socket.emit('api:admin.user.search', null);
}
}); });
socket.on('api:admin.themes.getInstalled', function(callback) { socket.on('api:admin.themes.getInstalled', function(callback) {

Loading…
Cancel
Save