mirror of
https://gitlab.computer.surgery/matrix/grapevine.git
synced 2025-12-17 07:41:23 +01:00
add admin command to delete all remote media files
This commit is contained in:
parent
d7087c66bb
commit
9d14c5d461
4 changed files with 98 additions and 2 deletions
|
|
@ -161,4 +161,27 @@ impl service::media::Data for KeyValueDatabase {
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn all_file_metadata(
|
||||||
|
&self,
|
||||||
|
) -> Box<
|
||||||
|
dyn Iterator<Item = Result<(OwnedMxcUri, FileMeta, MediaFileKey)>> + '_,
|
||||||
|
> {
|
||||||
|
Box::new(
|
||||||
|
self.mediaid_file
|
||||||
|
.iter()
|
||||||
|
.map(|(key, _)| {
|
||||||
|
let key = MediaFileKey::new(key);
|
||||||
|
|
||||||
|
let parts = MediaFileKeyParts::try_from(&key)?;
|
||||||
|
if parts.width != 0 && parts.height != 0 {
|
||||||
|
// Skip thumbnails
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some((parts.mxc, parts.meta, key)))
|
||||||
|
})
|
||||||
|
.filter_map(Result::transpose),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ use ruma::{
|
||||||
TimelineEventType,
|
TimelineEventType,
|
||||||
},
|
},
|
||||||
signatures::verify_json,
|
signatures::verify_json,
|
||||||
EventId, MilliSecondsSinceUnixEpoch, OwnedMxcUri, OwnedRoomId, RoomId,
|
EventId, MilliSecondsSinceUnixEpoch, OwnedMxcUri, OwnedRoomId,
|
||||||
RoomVersionId, ServerName, UserId,
|
OwnedServerName, RoomId, RoomVersionId, ServerName, UserId,
|
||||||
};
|
};
|
||||||
use serde_json::value::to_raw_value;
|
use serde_json::value::to_raw_value;
|
||||||
use tokio::sync::{mpsc, Mutex, RwLock};
|
use tokio::sync::{mpsc, Mutex, RwLock};
|
||||||
|
|
@ -185,6 +185,17 @@ enum AdminCommand {
|
||||||
mxc: OwnedMxcUri,
|
mxc: OwnedMxcUri,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Delete cached remote media from the database.
|
||||||
|
///
|
||||||
|
/// This media may still be fetched and cached again in the future.
|
||||||
|
DeleteRemoteMedia {
|
||||||
|
/// If specified, only delete remote media from this origin.
|
||||||
|
///
|
||||||
|
/// If not specified, all remote media will be deleted.
|
||||||
|
#[clap(long)]
|
||||||
|
origin: Option<OwnedServerName>,
|
||||||
|
},
|
||||||
|
|
||||||
/// Verify json signatures
|
/// Verify json signatures
|
||||||
/// [commandbody]()
|
/// [commandbody]()
|
||||||
/// # ```
|
/// # ```
|
||||||
|
|
@ -803,6 +814,50 @@ impl Service {
|
||||||
services().media.delete(mxc).await?;
|
services().media.delete(mxc).await?;
|
||||||
RoomMessageEventContent::text_plain("Media deleted.")
|
RoomMessageEventContent::text_plain("Media deleted.")
|
||||||
}
|
}
|
||||||
|
AdminCommand::DeleteRemoteMedia {
|
||||||
|
origin,
|
||||||
|
} => {
|
||||||
|
if origin.as_deref() == Some(services().globals.server_name()) {
|
||||||
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
|
"Specified origin is this server. Will not delete \
|
||||||
|
anything.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
// The `media.iter_all()` iterator is not `Send`, so spawn it in
|
||||||
|
// a separate thread and send the results over a channel.
|
||||||
|
let (tx, mut rx) = mpsc::channel(1);
|
||||||
|
tokio::task::spawn_blocking(move || {
|
||||||
|
for mxc in services().media.iter_all() {
|
||||||
|
if tx.blocking_send(mxc).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
while let Some(mxc) = rx.recv().await {
|
||||||
|
let mxc = mxc?;
|
||||||
|
let server_name = mxc.server_name();
|
||||||
|
|
||||||
|
if server_name == Ok(services().globals.server_name()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(origin) = &origin {
|
||||||
|
if server_name != Ok(origin) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count += 1;
|
||||||
|
services().media.delete(mxc).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomMessageEventContent::text_plain(format!(
|
||||||
|
"{count} media objects deleted."
|
||||||
|
))
|
||||||
|
}
|
||||||
AdminCommand::DeactivateUser {
|
AdminCommand::DeactivateUser {
|
||||||
leave_rooms,
|
leave_rooms,
|
||||||
user_id,
|
user_id,
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,15 @@ impl Service {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// List all media stored in the database.
|
||||||
|
///
|
||||||
|
/// Each MXC is list once. Thumbnails are not included separately from the
|
||||||
|
/// original media.
|
||||||
|
#[tracing::instrument(skip(self))]
|
||||||
|
pub(crate) fn iter_all(&self) -> impl Iterator<Item = Result<OwnedMxcUri>> {
|
||||||
|
self.db.all_file_metadata().map(|media| media.map(|(mxc, ..)| mxc))
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns width, height of the thumbnail and whether it should be cropped.
|
/// Returns width, height of the thumbnail and whether it should be cropped.
|
||||||
/// Returns None when the server should send the original file.
|
/// Returns None when the server should send the original file.
|
||||||
fn thumbnail_properties(
|
fn thumbnail_properties(
|
||||||
|
|
|
||||||
|
|
@ -29,4 +29,13 @@ pub(crate) trait Data: Send + Sync {
|
||||||
&self,
|
&self,
|
||||||
mxc: OwnedMxcUri,
|
mxc: OwnedMxcUri,
|
||||||
) -> Result<Vec<(FileMeta, MediaFileKey)>>;
|
) -> Result<Vec<(FileMeta, MediaFileKey)>>;
|
||||||
|
|
||||||
|
/// Returns an iterator over metadata for all media.
|
||||||
|
///
|
||||||
|
/// Thumbnails are not included.
|
||||||
|
fn all_file_metadata(
|
||||||
|
&self,
|
||||||
|
) -> Box<
|
||||||
|
dyn Iterator<Item = Result<(OwnedMxcUri, FileMeta, MediaFileKey)>> + '_,
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue