diff --git a/components/pages/inspector/UserActions.tsx b/components/pages/inspector/UserActions.tsx index 3cb1aa6..ed4f383 100644 --- a/components/pages/inspector/UserActions.tsx +++ b/components/pages/inspector/UserActions.tsx @@ -30,6 +30,7 @@ import { unsuspendUser, updateBotDiscoverability, updateUserBadges, + wipeUser, wipeUserProfile, } from "@/lib/actions"; import { useRef, useState } from "react"; @@ -264,6 +265,51 @@ export function UserActions({ user, bot }: { user: User; bot?: Bot }) { + + + + + + + + Are you sure you want to wipe this user's messages? + + + All messages sent by this user will be deleted immediately. +
+ + This action is irreversible and{" "} + will not publish any events! + +
+
+ + Cancel + + wipeUser(user._id, 0, true) + .then(() => { + setUserDraft((user) => ({ ...user, flags: 4 })); + toast({ title: "Wiped user's messages" }); + }) + .catch((err) => + toast({ + title: "Failed to wipe user's messages!", + description: String(err), + variant: "destructive", + }) + ) + } + > + Ban + + +
+
+ @@ -424,29 +470,37 @@ export function UserActions({ user, bot }: { user: User; bot?: Bot }) { - + Reset token - Re-roll this bot's authentication token. This will not disconnect active connections. + Re-roll this bot's authentication token. This will + not disconnect active connections. Cancel resetBotToken(user._id) - .then(() => toast({ - title: "Reset bot token", - })) - .catch((e) => toast({ - title: "Failed to reset token", - description: String(e), - variant: "destructive", - })) + onClick={() => + resetBotToken(user._id) + .then(() => + toast({ + title: "Reset bot token", + }) + ) + .catch((e) => + toast({ + title: "Failed to reset token", + description: String(e), + variant: "destructive", + }) + ) } > Reset @@ -457,18 +511,16 @@ export function UserActions({ user, bot }: { user: User; bot?: Bot }) { - + Transfer bot - - Transfer this bot to a new owner. - - + Transfer this bot to a new owner. + setTransferResetToken(!!e)} @@ -481,19 +533,28 @@ export function UserActions({ user, bot }: { user: User; bot?: Bot }) { Cancel transferBot(user._id, transferTarget!._id, transferResetToken) - .then(() => toast({ - title: "Reset bot token", - })) - .catch((e) => toast({ - title: "Failed to reset token", - description: String(e), - variant: "destructive", - })) - .finally(() => { - setTransferResetToken(true); - setTransferTarget(null); - }) + onClick={() => + transferBot( + user._id, + transferTarget!._id, + transferResetToken + ) + .then(() => + toast({ + title: "Reset bot token", + }) + ) + .catch((e) => + toast({ + title: "Failed to reset token", + description: String(e), + variant: "destructive", + }) + ) + .finally(() => { + setTransferResetToken(true); + setTransferTarget(null); + }) } > Transfer diff --git a/lib/actions.ts b/lib/actions.ts index 05be383..8da25cb 100644 --- a/lib/actions.ts +++ b/lib/actions.ts @@ -446,15 +446,21 @@ export async function updateUserBadges(userId: string, badges: number) { } } -export async function wipeUser(userId: string, flags = 4) { +export async function wipeUser( + userId: string, + flags = 4, + onlyMessages = false +) { if (RESTRICT_ACCESS_LIST.includes(userId)) throw "restricted access"; await checkPermission("users/action/wipe", userId, { flags }); - const user = await mongo() - .db("revolt") - .collection("users") - .findOne({ _id: userId }); + const user = onlyMessages + ? null + : await mongo() + .db("revolt") + .collection("users") + .findOne({ _id: userId }); const messages = await mongo() .db("revolt") @@ -462,24 +468,28 @@ export async function wipeUser(userId: string, flags = 4) { .find({ author: userId }, { sort: { _id: -1 } }) .toArray(); - const dms = await mongo() - .db("revolt") - .collection("channels") - .find({ - channel_type: "DirectMessage", - recipients: userId, - }) - .toArray(); + const dms = onlyMessages + ? null + : await mongo() + .db("revolt") + .collection("channels") + .find({ + channel_type: "DirectMessage", + recipients: userId, + }) + .toArray(); - const memberships = await mongo() - .db("revolt") - .collection<{ _id: { user: string; server: string } }>("server_members") - .find({ "_id.user": userId }) - .toArray(); + const memberships = onlyMessages + ? null + : await mongo() + .db("revolt") + .collection<{ _id: { user: string; server: string } }>("server_members") + .find({ "_id.user": userId }) + .toArray(); // retrieve messages, dm channels, relationships, server memberships const backup = { - _event: "wipe", + _event: onlyMessages ? "messages" : "wipe", user, messages, dms, @@ -499,12 +509,14 @@ export async function wipeUser(userId: string, flags = 4) { .filter((attachment) => attachment) .map((attachment) => attachment!._id); - if (backup.user?.avatar) { - attachmentIds.push(backup.user.avatar._id); - } + if (!onlyMessages) { + if (backup.user?.avatar) { + attachmentIds.push(backup.user.avatar._id); + } - if (backup.user?.profile?.background) { - attachmentIds.push(backup.user.profile.background._id); + if (backup.user?.profile?.background) { + attachmentIds.push(backup.user.profile.background._id); + } } if (attachmentIds.length) { @@ -527,44 +539,46 @@ export async function wipeUser(userId: string, flags = 4) { author: userId, }); - // delete server memberships - await mongo().db("revolt").collection("server_members").deleteMany({ - "_id.user": userId, - }); - - // disable account - await disableAccount(userId); - - // clear user profile - await mongo() - .db("revolt") - .collection("users") - .updateOne( - { - _id: userId, - }, - { - $set: { - flags, - }, - $unset: { - avatar: 1, - profile: 1, - status: 1, - }, - } - ); - - // broadcast wipe event - for (const topic of [ - ...backup.dms.map((x) => x._id), - ...backup.memberships.map((x) => x._id.server), - ]) { - await publishMessage(topic, { - type: "UserPlatformWipe", - user_id: userId, - flags, + if (!onlyMessages) { + // delete server memberships + await mongo().db("revolt").collection("server_members").deleteMany({ + "_id.user": userId, }); + + // disable account + await disableAccount(userId); + + // clear user profile + await mongo() + .db("revolt") + .collection("users") + .updateOne( + { + _id: userId, + }, + { + $set: { + flags, + }, + $unset: { + avatar: 1, + profile: 1, + status: 1, + }, + } + ); + + // broadcast wipe event + for (const topic of [ + ...backup.dms!.map((x) => x._id), + ...backup.memberships!.map((x) => x._id.server), + ]) { + await publishMessage(topic, { + type: "UserPlatformWipe", + user_id: userId, + flags, + }); + } } }