feat: add admin channel wipe endpoint

This commit is contained in:
İspik
2026-06-13 11:33:23 +03:00
parent e48d92c635
commit 05bceb6d4a
8 changed files with 86 additions and 1 deletions

View File

@@ -282,6 +282,16 @@ pub enum EventV1 {
id: String,
},
/// Channel wiped
///
/// Clients should remove all associated data:
/// - Messages
/// - Unreads
/// - Voice States
ChannelWipe {
id: String,
},
/// User joins a group
ChannelGroupJoin {
id: String,

View File

@@ -762,6 +762,13 @@ impl Channel {
// - channels list / categories list on server
db.delete_channel(self).await
}
/// Wipe a channel's messages
pub async fn wipe(&self, db: &Database) -> Result<()> {
let id = self.id().to_string();
EventV1::ChannelWipe { id: id.clone() }.p(id).await;
db.wipe_channel(self).await
}
}
#[cfg(feature = "mongodb")]

View File

@@ -1,3 +1,4 @@
use bson::{doc, Bson};
use crate::{revolt_result::Result, Channel, FieldsChannel, PartialChannel};
use revolt_permissions::OverrideField;
@@ -48,5 +49,6 @@ pub trait AbstractChannels: Sync + Send {
async fn remove_user_from_group(&self, channel_id: &str, user_id: &str) -> Result<()>;
// Delete a channel
async fn delete_channel(&self, channel_id: &Channel) -> Result<()>;
async fn delete_channel(&self, channel_id: &Channel) -> Result<()>; // Wipe a channel's messages
async fn wipe_channel(&self, channel: &Channel) -> Result<()>;
}

View File

@@ -261,6 +261,23 @@ impl AbstractChannels for MongoDb {
// Delete the channel itself
query!(self, delete_one_by_id, COL, channel.id()).map(|_| ())
}
// Wipe a channel's messages
async fn wipe_channel(&self, channel: &Channel) -> Result<()> {
let id = channel.id().to_string();
// Delete invites and unreads.
self.delete_associated_channel_objects(Bson::String(id.to_string()))
.await?;
// Delete messages.
self.delete_bulk_messages(doc! {
"channel": &id
})
.await?;
Ok(())
}
}
impl MongoDb {

View File

@@ -151,4 +151,10 @@ impl AbstractChannels for ReferenceDb {
Err(create_error!(NotFound))
}
}
async fn wipe_channel(&self, channel: &Channel) -> Result<()> {
let mut messages = self.messages.lock().await;
messages.retain(|_, message| message.channel != channel.id());
Ok(())
}
}

View File

@@ -329,6 +329,7 @@ auto_derived! {
// Channels
DeleteChannel,
EditChannel,
WipeChannel
}
// Joiner payloads
@@ -380,6 +381,7 @@ impl AdminAuditItemActions {
AdminAuditItemActions::DisableAccount => true,
AdminAuditItemActions::DeleteChannel => true,
AdminAuditItemActions::EditChannel => true,
AdminAuditItemActions::WipeChannel => true,
}
}
}

View File

@@ -0,0 +1,40 @@
use rocket::State;
use rocket_empty::EmptyResponse;
use revolt_result::{create_error, Result};
use revolt_database::{AdminAuthorization, Database};
use revolt_database::util::reference::Reference;
use revolt_models::v0;
use crate::routes::admin::util::{create_audit_action, flatten_authorized_user, user_has_permission};
/// Wipe all the messages from a channel
#[openapi(tag = "Admin")]
#[delete("/admin/channels/<channel_id>/wipe?<case>")]
pub async fn admin_channel_wipe(
db: &State<Database>,
auth: AdminAuthorization,
channel_id: Reference<'_>,
case: Option<&str>
) -> Result<EmptyResponse> {
let admin = flatten_authorized_user(&auth);
if !user_has_permission(admin, v0::AdminUserPermissionFlags::ManageChannels) {
return Err(create_error!(MissingPermission {
permission: "ManageChannels".to_string()
}));
}
let mut channel = channel_id.as_channel(db).await?;
channel.wipe(db).await?;
create_audit_action(
&db,
&admin.id,
v0::AdminAuditItemActions::WipeChannel,
case,
Some(channel_id.id),
None,
)
.await?;
Ok(EmptyResponse)
}

View File

@@ -42,5 +42,6 @@ pub fn routes() -> (Vec<Route>, OpenApi) {
accounts::account_disable::admin_account_disable,
channels::actions::channel_delete::admin_delete_channel,
channels::actions::channel_edit::admin_channel_edit,
channels::actions::channel_wipe::admin_channel_wipe,
]
}