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");
}
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,6 +93,30 @@
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">
<!-- 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,6 +37,9 @@
<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>

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

@ -55,7 +55,8 @@ var RDB = require('./redis.js'),
}
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);
});
}
@ -66,7 +67,6 @@ var RDB = require('./redis.js'),
categoryData.moderators = moderators;
categoryData.show_sidebar = 'hidden';
categoryData.no_topics_message = 'show';
callback(null, categoryData);
});
} else {
@ -200,11 +200,12 @@ 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) {
postData = posts.filterBannedPosts(postData);
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) {
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) {

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

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

@ -290,16 +290,33 @@ 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);
return;
posts = posts.reverse();
lastPostId = 0;
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;
}
});
} else {
next(null);
}
}
// If we got here, nothing was found...
callback(new Error('no-undeleted-pids-found'));
});
async.eachSeries(posts, isPostVisible, function(err) {
if(err) {
callback(null, lastPostId);
} else {
callback(new Error('no-undeleted-pids-found'));
}
});
});
}
}(exports));

@ -78,6 +78,8 @@ marked.setOptions({
var fav_data = results[0],
privileges = results[2];
postData = posts.filterBannedPosts(postData);
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';
@ -149,7 +151,9 @@ marked.setOptions({
Topics.getTopicsByTids(topicIds, uid, function(topicData) {
unreadTopics.topics = topicData;
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';
callback(unreadTopics);
});
@ -192,9 +196,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', 'banned'], function(userData) {
next(null, userData);
});
}
@ -217,24 +221,23 @@ 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]
});
});
}
function isTopicVisible(topicData, topicInfo) {
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) {
@ -252,6 +255,7 @@ marked.setOptions({
topicData.relativeTime = utils.relativeTime(topicData.timestamp);
topicData.username = topicInfo.username;
topicData.userbanned = topicInfo.userbanned;
topicData.badgeclass = (topicInfo.hasread && current_user != 0) ? '' : 'badge-important';
topicData.teaser_text = topicInfo.teaserInfo.text || '',
topicData.teaser_username = topicInfo.teaserInfo.username || '';

@ -41,7 +41,7 @@ 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);
@ -67,6 +67,7 @@ var utils = require('./../public/src/utils.js'),
'postcount': 0,
'lastposttime': 0,
'administrator': (uid == 1) ? 1 : 0,
'banned': 0,
'showemail': 0
});
@ -126,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) {
@ -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) {
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) {
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) {
@ -345,7 +360,6 @@ var utils = require('./../public/src/utils.js'),
async.eachSeries(uids, iterator, function(err) {
callback(err, data);
});
});
}

@ -671,6 +671,7 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
if(err) {
winston.err(err);
} else {
data = user.filterBannedUsers(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) {
if(uid && uid > 0) {
user.search(username, function(data) {
data = user.filterBannedUsers(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) {

Loading…
Cancel
Save