mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-07-08 14:23:04 +02:00
feat: banned-users group
This commit is contained in:
@@ -5,10 +5,14 @@ const winston = require('winston');
|
||||
const meta = require('../meta');
|
||||
const emailer = require('../emailer');
|
||||
const db = require('../database');
|
||||
const groups = require('../groups');
|
||||
const privileges = require('../privileges');
|
||||
|
||||
module.exports = function (User) {
|
||||
User.bans = {};
|
||||
|
||||
const systemGroups = groups.systemGroups.filter(group => group !== groups.BANNED_USERS);
|
||||
|
||||
User.bans.ban = async function (uid, until, reason) {
|
||||
// "until" (optional) is unix timestamp in milliseconds
|
||||
// "reason" (optional) is a string
|
||||
@@ -32,7 +36,9 @@ module.exports = function (User) {
|
||||
banData.reason = reason;
|
||||
}
|
||||
|
||||
await User.setUserField(uid, 'banned', 1);
|
||||
// Leaving all other system groups to have privileges constrained to the "banned-users" group
|
||||
await groups.leave(systemGroups, uid);
|
||||
await groups.join(groups.BANNED_USERS, uid);
|
||||
await db.sortedSetAdd('users:banned', now, uid);
|
||||
await db.sortedSetAdd('uid:' + uid + ':bans:timestamp', now, banKey);
|
||||
await db.setObject(banKey, banData);
|
||||
@@ -59,10 +65,20 @@ module.exports = function (User) {
|
||||
};
|
||||
|
||||
User.bans.unban = async function (uids) {
|
||||
if (Array.isArray(uids)) {
|
||||
await db.setObject(uids.map(uid => 'user:' + uid), { banned: 0, 'banned:expire': 0 });
|
||||
} else {
|
||||
await User.setUserFields(uids, { banned: 0, 'banned:expire': 0 });
|
||||
uids = Array.isArray(uids) ? uids : [uids];
|
||||
const userData = await User.getUsersFields(uids, ['email:confirmed']);
|
||||
|
||||
await db.setObject(uids.map(uid => 'user:' + uid), { 'banned:expire': 0 });
|
||||
|
||||
/* eslint-disable no-await-in-loop */
|
||||
for (const user of userData) {
|
||||
const systemGroupsToJoin = [
|
||||
'registered-users',
|
||||
(parseInt(user['email:confirmed'], 10) === 1 ? 'verified-users' : 'unverified-users'),
|
||||
];
|
||||
await groups.leave(groups.BANNED_USERS, user.uid);
|
||||
// An unbanned user would lost its previous "Global Moderator" status
|
||||
await groups.join(systemGroupsToJoin, user.uid);
|
||||
}
|
||||
|
||||
await db.sortedSetRemove(['users:banned', 'users:banned:expire'], uids);
|
||||
@@ -75,22 +91,39 @@ module.exports = function (User) {
|
||||
return isArray ? result.map(r => r.banned) : result[0].banned;
|
||||
};
|
||||
|
||||
User.bans.canLoginIfBanned = async function (uid) {
|
||||
let canLogin = true;
|
||||
|
||||
const banned = (await User.bans.unbanIfExpired([uid]))[0].banned;
|
||||
// Group privilege overshadows individual one
|
||||
if (banned) {
|
||||
canLogin = await privileges.global.canGroup('local:login', groups.BANNED_USERS);
|
||||
}
|
||||
if (banned && !canLogin) {
|
||||
// Checking a single privilege of user
|
||||
canLogin = await groups.isMember(uid, 'cid:0:privileges:local:login');
|
||||
}
|
||||
|
||||
return canLogin;
|
||||
};
|
||||
|
||||
User.bans.unbanIfExpired = async function (uids) {
|
||||
// loading user data will unban if it has expired -barisu
|
||||
const userData = await User.getUsersFields(uids, ['banned', 'banned:expire']);
|
||||
const userData = await User.getUsersFields(uids, ['banned:expire']);
|
||||
return User.bans.calcExpiredFromUserData(userData);
|
||||
};
|
||||
|
||||
User.bans.calcExpiredFromUserData = function (userData) {
|
||||
User.bans.calcExpiredFromUserData = async function (userData) {
|
||||
const isArray = Array.isArray(userData);
|
||||
userData = isArray ? userData : [userData];
|
||||
userData = userData.map(function (userData) {
|
||||
userData = await Promise.all(userData.map(async function (userData) {
|
||||
const banned = await groups.isMember(userData.uid, groups.BANNED_USERS);
|
||||
return {
|
||||
banned: userData && !!userData.banned,
|
||||
banned: banned,
|
||||
'banned:expire': userData && userData['banned:expire'],
|
||||
banExpired: userData && userData['banned:expire'] <= Date.now() && userData['banned:expire'] !== 0,
|
||||
};
|
||||
});
|
||||
}));
|
||||
return isArray ? userData : userData[0];
|
||||
};
|
||||
|
||||
|
||||
@@ -219,7 +219,8 @@ module.exports = function (User) {
|
||||
}
|
||||
|
||||
if (user.hasOwnProperty('banned') || user.hasOwnProperty('banned:expire')) {
|
||||
const result = User.bans.calcExpiredFromUserData(user);
|
||||
const result = await User.bans.calcExpiredFromUserData(user);
|
||||
user.banned = result.banned;
|
||||
const unban = result.banned && result.banExpired;
|
||||
user.banned_until = unban ? 0 : user['banned:expire'];
|
||||
user.banned_until_readable = user.banned_until && !unban ? utils.toISOString(user.banned_until) : 'Not Banned';
|
||||
|
||||
@@ -12,8 +12,6 @@ const utils = require('../utils');
|
||||
module.exports = function (User) {
|
||||
const filterFnMap = {
|
||||
online: user => user.status !== 'offline' && (Date.now() - user.lastonline < 300000),
|
||||
banned: user => user.banned,
|
||||
notbanned: user => !user.banned,
|
||||
flagged: user => parseInt(user.flags, 10) > 0,
|
||||
verified: user => !!user['email:confirmed'],
|
||||
unverified: user => !user['email:confirmed'],
|
||||
@@ -21,8 +19,6 @@ module.exports = function (User) {
|
||||
|
||||
const filterFieldMap = {
|
||||
online: ['status', 'lastonline'],
|
||||
banned: ['banned'],
|
||||
notbanned: ['banned'],
|
||||
flagged: ['flags'],
|
||||
verified: ['email:confirmed'],
|
||||
unverified: ['email:confirmed'],
|
||||
@@ -111,6 +107,12 @@ module.exports = function (User) {
|
||||
return uids;
|
||||
}
|
||||
|
||||
if (filters.includes('banned') || filters.includes('notbanned')) {
|
||||
const isMembersOfBanned = await groups.isMembers(uids, groups.BANNED_USERS);
|
||||
const checkBanned = filters.includes('banned');
|
||||
uids = uids.filter((uid, index) => (checkBanned ? isMembersOfBanned[index] : !isMembersOfBanned[index]));
|
||||
}
|
||||
|
||||
fields.push('uid');
|
||||
let userData = await User.getUsersFields(uids, fields);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user