feat: closes #12491, add unban & unmute history

to account/info page
This commit is contained in:
Barış Soner Uşaklı
2024-04-23 11:16:04 -04:00
parent bde9136b92
commit 985663faae
10 changed files with 176 additions and 85 deletions

View File

@@ -252,7 +252,8 @@ usersAPI.unban = async function (caller, data) {
throw new Error('[[error:no-privileges]]');
}
await user.bans.unban(data.uid);
const unbanData = await user.bans.unban(data.uid, data.reason);
await db.setObjectField(`uid:${data.uid}:unban:${unbanData.timestamp}`, 'fromUid', caller.uid);
sockets.in(`uid_${data.uid}`).emit('event:unbanned');
@@ -283,6 +284,7 @@ usersAPI.mute = async function (caller, data) {
const now = Date.now();
const muteKey = `uid:${data.uid}:mute:${now}`;
const muteData = {
type: 'mute',
fromUid: caller.uid,
uid: data.uid,
timestamp: now,
@@ -315,7 +317,19 @@ usersAPI.unmute = async function (caller, data) {
}
await db.deleteObjectFields(`user:${data.uid}`, ['mutedUntil', 'mutedReason']);
const now = Date.now();
const unmuteKey = `uid:${data.uid}:unmute:${now}`;
const unmuteData = {
type: 'unmute',
fromUid: caller.uid,
uid: data.uid,
timestamp: now,
};
if (data.reason) {
unmuteData.reason = data.reason;
}
await db.sortedSetAdd(`uid:${data.uid}:unmutes:timestamp`, now, unmuteKey);
await db.setObject(unmuteKey, unmuteData);
await events.log({
type: 'user-unmute',
uid: caller.uid,

View File

@@ -26,6 +26,7 @@ module.exports = function (User) {
const banKey = `uid:${uid}:ban:${now}`;
const banData = {
type: 'ban',
uid: uid,
timestamp: now,
expire: until > now ? until : 0,
@@ -63,24 +64,39 @@ module.exports = function (User) {
return banData;
};
User.bans.unban = async function (uids) {
uids = Array.isArray(uids) ? uids : [uids];
User.bans.unban = async function (uids, reason = '') {
const isArray = Array.isArray(uids);
uids = isArray ? uids : [uids];
const userData = await User.getUsersFields(uids, ['email:confirmed']);
await db.setObject(uids.map(uid => `user:${uid}`), { 'banned:expire': 0 });
const now = Date.now();
const unbanDataArray = [];
/* 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);
const unbanKey = `uid:${user.uid}:unban:${now}`;
const unbanData = {
type: 'unban',
uid: user.uid,
reason,
timestamp: now,
};
await Promise.all([
db.sortedSetAdd(`uid:${user.uid}:unbans:timestamp`, now, unbanKey),
db.setObject(unbanKey, unbanData),
groups.leave(groups.BANNED_USERS, user.uid),
// An unbanned user would lost its previous "Global Moderator" status
groups.join(systemGroupsToJoin, user.uid),
]);
unbanDataArray.push(unbanData);
}
await db.sortedSetRemove(['users:banned', 'users:banned:expire'], uids);
return isArray ? unbanDataArray : unbanDataArray[0];
};
User.bans.isBanned = async function (uids) {

View File

@@ -258,7 +258,7 @@ module.exports = function (User) {
user.banned_until = unban ? 0 : user['banned:expire'];
user.banned_until_readable = user.banned_until && !unban ? utils.toISOString(user.banned_until) : 'Not Banned';
if (unban) {
await User.bans.unban(user.uid);
await User.bans.unban(user.uid, '[[user:info.ban-expired]]');
user.banned = false;
}
}

View File

@@ -32,8 +32,12 @@ module.exports = function (User) {
User.getModerationHistory = async function (uid) {
let [flags, bans, mutes] = await Promise.all([
db.getSortedSetRevRangeWithScores(`flags:byTargetUid:${uid}`, 0, 19),
db.getSortedSetRevRange(`uid:${uid}:bans:timestamp`, 0, 19),
db.getSortedSetRevRange(`uid:${uid}:mutes:timestamp`, 0, 19),
db.getSortedSetRevRange([
`uid:${uid}:bans:timestamp`, `uid:${uid}:unbans:timestamp`,
], 0, 19),
db.getSortedSetRevRange([
`uid:${uid}:mutes:timestamp`, `uid:${uid}:unmutes:timestamp`,
], 0, 19),
]);
// Get pids from flag objects

View File

@@ -0,0 +1,10 @@
<form class="form">
<div class="row">
<div class="col-12">
<div class="mb-3">
<label class="form-label" for="reason">[[admin/manage/users:temp-ban.reason]]</label>
<input type="text" class="form-control" id="reason" name="reason" />
</div>
</div>
</div>
</form>

View File

@@ -0,0 +1,10 @@
<form class="form">
<div class="row">
<div class="col-12">
<div class="mb-3">
<label class="form-label" for="reason">[[admin/manage/users:temp-ban.reason]]</label>
<input type="text" class="form-control" id="reason" name="reason" />
</div>
</div>
</div>
</form>