helper function, also delete old community/site icons

This commit is contained in:
Felix Ableitner 2024-03-26 15:10:21 +01:00
parent 160d558dd9
commit 8414b58662
5 changed files with 39 additions and 21 deletions

View file

@ -1,8 +1,9 @@
use actix_web::web::{Data, Json}; use activitypub_federation::config::Data;
use actix_web::web::Json;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::SaveUserSettings, person::SaveUserSettings,
request::delete_image_from_pictrs, request::replace_image,
utils::{ utils::{
get_url_blocklist, get_url_blocklist,
local_site_to_slur_regex, local_site_to_slur_regex,
@ -15,7 +16,6 @@ use lemmy_api_common::{
use lemmy_db_schema::{ use lemmy_db_schema::{
source::{ source::{
actor_language::LocalUserLanguage, actor_language::LocalUserLanguage,
images::LocalImage,
local_user::{LocalUser, LocalUserUpdateForm}, local_user::{LocalUser, LocalUserUpdateForm},
local_user_vote_display_mode::{LocalUserVoteDisplayMode, LocalUserVoteDisplayModeUpdateForm}, local_user_vote_display_mode::{LocalUserVoteDisplayMode, LocalUserVoteDisplayModeUpdateForm},
person::{Person, PersonUpdateForm}, person::{Person, PersonUpdateForm},
@ -42,17 +42,8 @@ pub async fn save_user_settings(
let bio = diesel_option_overwrite( let bio = diesel_option_overwrite(
process_markdown_opt(&data.bio, &slur_regex, &url_blocklist, &context).await?, process_markdown_opt(&data.bio, &slur_regex, &url_blocklist, &context).await?,
); );
if data.avatar.is_some() { replace_image(&data.avatar, &local_user_view.person.avatar, &context).await?;
// Ignore errors because image may be stored externally. replace_image(&data.banner, &local_user_view.person.banner, &context).await?;
if let Some(avatar) = &local_user_view.person.avatar {
let image = LocalImage::delete_by_url(&mut context.pool(), &avatar)
.await
.ok();
if let Some(image) = image {
delete_image_from_pictrs(&image.pictrs_alias, &image.pictrs_delete_token, &context).await?;
}
}
}
let avatar = proxy_image_link_opt_api(&data.avatar, &context).await?; let avatar = proxy_image_link_opt_api(&data.avatar, &context).await?;
let banner = proxy_image_link_opt_api(&data.banner, &context).await?; let banner = proxy_image_link_opt_api(&data.banner, &context).await?;

View file

@ -3,6 +3,7 @@ use crate::{
post::{LinkMetadata, OpenGraphData}, post::{LinkMetadata, OpenGraphData},
utils::proxy_image_link, utils::proxy_image_link,
}; };
use activitypub_federation::config::Data;
use encoding::{all::encodings, DecoderTrap}; use encoding::{all::encodings, DecoderTrap};
use lemmy_db_schema::{ use lemmy_db_schema::{
newtypes::DbUrl, newtypes::DbUrl,
@ -312,6 +313,26 @@ async fn is_image_content_type(client: &ClientWithMiddleware, url: &Url) -> Resu
} }
} }
/// When adding a new avatar or similar image, delete the old one.
pub async fn replace_image(
new_image: &Option<String>,
old_image: &Option<DbUrl>,
context: &Data<LemmyContext>,
) -> Result<(), LemmyError> {
if new_image.is_some() {
// Ignore errors because image may be stored externally.
if let Some(avatar) = &old_image {
let image = LocalImage::delete_by_url(&mut context.pool(), &avatar)
.await
.ok();
if let Some(image) = image {
delete_image_from_pictrs(&image.pictrs_alias, &image.pictrs_delete_token, &context).await?;
}
}
}
Ok(())
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#![allow(clippy::unwrap_used)] #![allow(clippy::unwrap_used)]

View file

@ -4,6 +4,7 @@ use lemmy_api_common::{
build_response::build_community_response, build_response::build_community_response,
community::{CommunityResponse, EditCommunity}, community::{CommunityResponse, EditCommunity},
context::LemmyContext, context::LemmyContext,
request::replace_image,
send_activity::{ActivityChannel, SendActivityData}, send_activity::{ActivityChannel, SendActivityData},
utils::{ utils::{
check_community_mod_action, check_community_mod_action,
@ -42,6 +43,9 @@ pub async fn update_community(
let description = let description =
process_markdown_opt(&data.description, &slur_regex, &url_blocklist, &context).await?; process_markdown_opt(&data.description, &slur_regex, &url_blocklist, &context).await?;
is_valid_body_field(&data.description, false)?; is_valid_body_field(&data.description, false)?;
let old_community = Community::read(&mut context.pool(), data.community_id).await?;
replace_image(&data.icon, &old_community.icon, &context).await?;
replace_image(&data.banner, &old_community.banner, &context).await?;
let description = diesel_option_overwrite(description); let description = diesel_option_overwrite(description);
let icon = proxy_image_link_opt_api(&data.icon, &context).await?; let icon = proxy_image_link_opt_api(&data.icon, &context).await?;

View file

@ -1,7 +1,9 @@
use crate::site::{application_question_check, site_default_post_listing_type_check}; use crate::site::{application_question_check, site_default_post_listing_type_check};
use actix_web::web::{Data, Json}; use activitypub_federation::config::Data;
use actix_web::web::Json;
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
request::replace_image,
site::{EditSite, SiteResponse}, site::{EditSite, SiteResponse},
utils::{ utils::{
get_url_blocklist, get_url_blocklist,
@ -63,6 +65,9 @@ pub async fn update_site(
SiteLanguage::update(&mut context.pool(), discussion_languages.clone(), &site).await?; SiteLanguage::update(&mut context.pool(), discussion_languages.clone(), &site).await?;
} }
replace_image(&data.icon, &site.icon, &context).await?;
replace_image(&data.banner, &site.banner, &context).await?;
let slur_regex = local_site_to_slur_regex(&local_site); let slur_regex = local_site_to_slur_regex(&local_site);
let url_blocklist = get_url_blocklist(&context).await?; let url_blocklist = get_url_blocklist(&context).await?;
let sidebar = process_markdown_opt(&data.sidebar, &slur_regex, &url_blocklist, &context).await?; let sidebar = process_markdown_opt(&data.sidebar, &slur_regex, &url_blocklist, &context).await?;

View file

@ -74,19 +74,16 @@ impl LocalImage {
query.load::<LocalImage>(conn).await query.load::<LocalImage>(conn).await
} }
pub async fn delete_by_alias(pool: &mut DbPool<'_>, alias: &str) -> Result<usize, Error> { pub async fn delete_by_alias(pool: &mut DbPool<'_>, alias: &str) -> Result<Self, Error> {
let conn = &mut get_conn(pool).await?; let conn = &mut get_conn(pool).await?;
diesel::delete(local_image::table.filter(local_image::pictrs_alias.eq(alias))) diesel::delete(local_image::table.filter(local_image::pictrs_alias.eq(alias)))
.execute(conn) .get_result(conn)
.await .await
} }
pub async fn delete_by_url(pool: &mut DbPool<'_>, url: &DbUrl) -> Result<Self, Error> { pub async fn delete_by_url(pool: &mut DbPool<'_>, url: &DbUrl) -> Result<Self, Error> {
let conn = &mut get_conn(pool).await?;
let alias = url.as_str().split('/').last().ok_or(NotFound)?; let alias = url.as_str().split('/').last().ok_or(NotFound)?;
diesel::delete(local_image::table.filter(local_image::pictrs_alias.eq(alias))) Self::delete_by_alias(pool, alias).await
.get_result(conn)
.await
} }
} }