add functions to delete media from specific local users

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
strawberry 2024-08-25 11:46:47 -04:00 committed by Jason Volk
parent a79ae7d1a2
commit 6b65a8fc86
2 changed files with 51 additions and 5 deletions

View file

@ -6,7 +6,7 @@ use conduit::{
Err, Error, Result,
};
use database::{Database, Map};
use ruma::{api::client::error::ErrorKind, http_headers::ContentDisposition, Mxc, UserId};
use ruma::{api::client::error::ErrorKind, http_headers::ContentDisposition, Mxc, OwnedMxcUri, UserId};
use super::preview::UrlPreviewData;
@ -176,6 +176,23 @@ impl Data {
})
}
/// Gets all the MXCs associated with a user
pub(super) fn get_all_user_mxcs(&self, user_id: &UserId) -> Vec<OwnedMxcUri> {
let user_id = user_id.as_bytes().to_vec();
self.mediaid_user
.iter()
.filter_map(|(key, user)| {
if *user == user_id {
let mxc_s = string_from_bytes(&key).ok()?;
Some(OwnedMxcUri::from(mxc_s))
} else {
None
}
})
.collect()
}
/// Gets all the media keys in our database (this includes all the metadata
/// associated with it such as width, height, content-type, etc)
pub(crate) fn get_all_media_keys(&self) -> Vec<Vec<u8>> { self.mediaid_file.iter().map(|(key, _)| key).collect() }

View file

@ -8,7 +8,11 @@ use std::{path::PathBuf, sync::Arc, time::SystemTime};
use async_trait::async_trait;
use base64::{engine::general_purpose, Engine as _};
use conduit::{debug, debug_error, err, error, trace, utils, utils::MutexMap, Err, Result, Server};
use conduit::{
debug, debug_error, debug_info, err, error, trace,
utils::{self, MutexMap},
warn, Err, Result, Server,
};
use data::{Data, Metadata};
use ruma::{http_headers::ContentDisposition, Mxc, OwnedMxcUri, UserId};
use tokio::{
@ -106,6 +110,31 @@ impl Service {
}
}
/// Deletes all media by the specified user
///
/// currently, this is only practical for local users
pub async fn delete_from_user(&self, user: &UserId, force: bool) -> Result<usize> {
let mxcs = self.db.get_all_user_mxcs(user);
let mut deletion_count: usize = 0;
for mxc in mxcs {
let mxc: Mxc<'_> = mxc.as_str().try_into()?;
debug_info!("Deleting MXC {mxc} by user {user} from database and filesystem");
if force {
_ = self
.delete(&mxc)
.await
.inspect_err(|e| warn!("Failed to delete {mxc} from user {user}, ignoring error: {e}"));
} else {
self.delete(&mxc).await?;
}
deletion_count = deletion_count.saturating_add(1);
}
Ok(deletion_count)
}
/// Downloads a file.
pub async fn get(&self, mxc: &Mxc<'_>) -> Result<Option<FileMeta>> {
if let Ok(Metadata {
@ -163,7 +192,7 @@ impl Service {
return Err!(Database("Parsed MXC URL unicode bytes from database but still is None"));
};
debug!("Parsed MXC key to URL: {mxc_s}");
debug_info!("Parsed MXC key to URL: {mxc_s}");
let mxc = OwnedMxcUri::from(mxc_s);
if mxc.server_name() == Ok(self.services.globals.server_name()) {
debug!("Ignoring local media MXC: {mxc}");
@ -206,11 +235,11 @@ impl Service {
return Err!(Database("Did not found any eligible MXCs to delete."));
}
debug!("Deleting media now in the past {user_duration:?}.");
debug_info!("Deleting media now in the past {user_duration:?}.");
let mut deletion_count: usize = 0;
for mxc in remote_mxcs {
let mxc: Mxc<'_> = mxc.as_str().try_into()?;
debug!("Deleting MXC {mxc} from database and filesystem");
debug_info!("Deleting MXC {mxc} from database and filesystem");
self.delete(&mxc).await?;
deletion_count = deletion_count.saturating_add(1);
}