disable legacy media compat by default; cleanse directory when disabled

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-07-30 02:06:15 +00:00
parent f632b06e6d
commit a0a002b17f
3 changed files with 40 additions and 7 deletions

View file

@ -287,7 +287,7 @@ pub struct Config {
#[serde(default = "true_fn")] #[serde(default = "true_fn")]
pub media_startup_check: bool, pub media_startup_check: bool,
#[serde(default = "true_fn")] #[serde(default)]
pub media_compat_file_link: bool, pub media_compat_file_link: bool,
#[serde(default = "Vec::new")] #[serde(default = "Vec::new")]
pub prevent_media_downloads_from: Vec<OwnedServerName>, pub prevent_media_downloads_from: Vec<OwnedServerName>,

View file

@ -743,6 +743,7 @@ async fn db_lt_13(services: &Services) -> Result<()> {
/// again. /// again.
async fn migrate_sha256_media(services: &Services) -> Result<()> { async fn migrate_sha256_media(services: &Services) -> Result<()> {
let db = &services.db; let db = &services.db;
let config = &services.server.config;
warn!("Migrating legacy base64 file names to sha256 file names"); warn!("Migrating legacy base64 file names to sha256 file names");
let mediaid_file = &db["mediaid_file"]; let mediaid_file = &db["mediaid_file"];
@ -759,7 +760,9 @@ async fn migrate_sha256_media(services: &Services) -> Result<()> {
for (old_path, path) in changes { for (old_path, path) in changes {
if old_path.exists() { if old_path.exists() {
tokio::fs::rename(&old_path, &path).await?; tokio::fs::rename(&old_path, &path).await?;
tokio::fs::symlink(&path, &old_path).await?; if config.media_compat_file_link {
tokio::fs::symlink(&path, &old_path).await?;
}
} }
} }
@ -822,8 +825,14 @@ async fn handle_media_check(
let (mediaid_file, mediaid_user) = dbs; let (mediaid_file, mediaid_user) = dbs;
let old_exists = files.contains(old_path);
let new_exists = files.contains(new_path); let new_exists = files.contains(new_path);
let old_exists = files.contains(old_path);
let old_is_symlink = || async {
tokio::fs::symlink_metadata(old_path)
.await
.map_or(false, |md| md.is_symlink())
};
if !old_exists && !new_exists { if !old_exists && !new_exists {
error!( error!(
media_id = ?encode_key(key), ?new_path, ?old_path, media_id = ?encode_key(key), ?new_path, ?old_path,
@ -849,10 +858,29 @@ async fn handle_media_check(
"Legacy media found without sha256 migration. Fixing..." "Legacy media found without sha256 migration. Fixing..."
); );
debug_assert!(
old_is_symlink().await,
"Legacy media not expected to be a symlink without an existing sha256 migration."
);
tokio::fs::rename(&old_path, &new_path).await?; tokio::fs::rename(&old_path, &new_path).await?;
tokio::fs::symlink(&new_path, &old_path).await?; tokio::fs::symlink(&new_path, &old_path).await?;
} }
if !config.media_compat_file_link && old_exists && old_is_symlink().await {
debug_warn!(
media_id = ?encode_key(key), ?new_path, ?old_path,
"Legacy link found but compat disabled. Cleansing symlink..."
);
debug_assert!(
new_exists,
"sha256 migration into new file expected prior to cleaning legacy symlink here."
);
tokio::fs::remove_file(&old_path).await?;
}
Ok(()) Ok(())
} }

View file

@ -6,7 +6,7 @@ use std::{path::PathBuf, sync::Arc, time::SystemTime};
use async_trait::async_trait; use async_trait::async_trait;
use base64::{engine::general_purpose, Engine as _}; use base64::{engine::general_purpose, Engine as _};
use conduit::{debug, debug_error, err, error, utils, utils::MutexMap, Err, Result, Server}; use conduit::{debug, debug_error, err, error, trace, utils, utils::MutexMap, Err, Result, Server};
use data::{Data, Metadata}; use data::{Data, Metadata};
use ruma::{OwnedMxcUri, OwnedUserId}; use ruma::{OwnedMxcUri, OwnedUserId};
use serde::Serialize; use serde::Serialize;
@ -99,10 +99,15 @@ impl Service {
pub async fn delete(&self, mxc: &str) -> Result<()> { pub async fn delete(&self, mxc: &str) -> Result<()> {
if let Ok(keys) = self.db.search_mxc_metadata_prefix(mxc) { if let Ok(keys) = self.db.search_mxc_metadata_prefix(mxc) {
for key in keys { for key in keys {
self.remove_media_file(&key).await?; trace!(?mxc, ?key, "Deleting from filesystem");
if let Err(e) = self.remove_media_file(&key).await {
error!(?mxc, ?key, "Failed to remove media file: {e}");
}
debug!("Deleting MXC {mxc} from database"); trace!(?mxc, ?key, "Deleting from database");
self.db.delete_file_mxc(mxc)?; if let Err(e) = self.db.delete_file_mxc(mxc) {
error!(?mxc, ?key, "Failed to remove media from database: {e}");
}
} }
Ok(()) Ok(())