From 929282a2f7e335d6bb831cb712009331e7f921be Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Wed, 14 Aug 2013 13:32:07 -0400 Subject: [PATCH] ban users, closes #125, banning a user hides all posts topics of a user and their profile page becomes inaccessible --- public/src/forum/admin/users.js | 43 ++++++++++++++++++++++++++++++++ public/templates/admin/users.tpl | 5 +++- src/admin/user.js | 35 ++++++++++++++++++++++++-- src/categories.js | 13 +++++----- src/posts.js | 15 ++++++++--- src/routes/authentication.js | 6 ++--- src/routes/user.js | 19 ++++++++++---- src/threadTools.js | 35 +++++++++++++++++++------- src/topics.js | 34 ++++++++++++++----------- src/user.js | 22 +++++++++++++--- src/websockets.js | 18 +++++++++++-- 11 files changed, 194 insertions(+), 51 deletions(-) diff --git a/public/src/forum/admin/users.js b/public/src/forum/admin/users.js index 212358ec9d..088cf2fa43 100644 --- a/public/src/forum/admin/users.js +++ b/public/src/forum/admin/users.js @@ -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; + }); } diff --git a/public/templates/admin/users.tpl b/public/templates/admin/users.tpl index 17fa914b12..8d21f86c97 100644 --- a/public/templates/admin/users.tpl +++ b/public/templates/admin/users.tpl @@ -16,7 +16,7 @@ diff --git a/src/admin/user.js b/src/admin/user.js index 8350af24ec..88ee02f467 100644 --- a/src/admin/user.js +++ b/src/admin/user.js @@ -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 + }); + }); + } }); }; diff --git a/src/categories.js b/src/categories.js index c6a04e3108..417920b634 100644 --- a/src/categories.js +++ b/src/categories.js @@ -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); }); }); } diff --git a/src/posts.js b/src/posts.js index 77c983b891..12d6d95c49 100644 --- a/src/posts.js +++ b/src/posts.js @@ -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) { diff --git a/src/routes/authentication.js b/src/routes/authentication.js index 04fab0035f..2191ca13c7 100644 --- a/src/routes/authentication.js +++ b/src/routes/authentication.js @@ -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() { diff --git a/src/routes/user.js b/src/routes/user.js index 45b13ba0ae..1c13c1e5dc 100644 --- a/src/routes/user.js +++ b/src/routes/user.js @@ -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 }); }); } diff --git a/src/threadTools.js b/src/threadTools.js index 1f1746d3f5..a717d6c723 100644 --- a/src/threadTools.js +++ b/src/threadTools.js @@ -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)); \ No newline at end of file diff --git a/src/topics.js b/src/topics.js index 6a2a812de7..79e0436956 100644 --- a/src/topics.js +++ b/src/topics.js @@ -78,6 +78,8 @@ marked.setOptions({ var fav_data = results[0], privileges = results[2]; + postData = posts.filterBannedPosts(postData); + for(var i=0; i 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) {