From ada8f1ba8e7948e97877762ac8dc5452739a9e93 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Wed, 18 Dec 2024 11:52:17 +0100 Subject: [PATCH] site icon/banner --- api_tests/run-federation-test.sh | 2 +- crates/api_common/src/community.rs | 6 ---- crates/api_common/src/request.rs | 35 +++--------------- crates/api_common/src/site.rs | 10 ------ crates/api_common/src/utils.rs | 25 ------------- crates/api_crud/src/community/update.rs | 14 +------- crates/api_crud/src/site/create.rs | 11 +----- crates/api_crud/src/site/update.rs | 14 +------- crates/routes/src/images/upload.rs | 47 +++++++++++++++++++++++-- src/api_routes_v4.rs | 6 +++- 10 files changed, 58 insertions(+), 112 deletions(-) diff --git a/api_tests/run-federation-test.sh b/api_tests/run-federation-test.sh index f9eab5039..969a95b3e 100755 --- a/api_tests/run-federation-test.sh +++ b/api_tests/run-federation-test.sh @@ -11,7 +11,7 @@ killall -s1 lemmy_server || true popd pnpm i -pnpm api-test-image || true +pnpm api-test || true killall -s1 lemmy_server || true killall -s1 pict-rs || true diff --git a/crates/api_common/src/community.rs b/crates/api_common/src/community.rs index 898767b34..9105c6f84 100644 --- a/crates/api_common/src/community.rs +++ b/crates/api_common/src/community.rs @@ -177,12 +177,6 @@ pub struct EditCommunity { /// A shorter, one line description of your community. #[cfg_attr(feature = "full", ts(optional))] pub description: Option, - /// An icon URL. - #[cfg_attr(feature = "full", ts(optional))] - pub icon: Option, - /// A banner URL. - #[cfg_attr(feature = "full", ts(optional))] - pub banner: Option, /// Whether its an NSFW community. #[cfg_attr(feature = "full", ts(optional))] pub nsfw: Option, diff --git a/crates/api_common/src/request.rs b/crates/api_common/src/request.rs index a03e6598f..1691b93de 100644 --- a/crates/api_common/src/request.rs +++ b/crates/api_common/src/request.rs @@ -9,13 +9,10 @@ use activitypub_federation::config::Data; use chrono::{DateTime, Utc}; use encoding_rs::{Encoding, UTF_8}; use futures::StreamExt; -use lemmy_db_schema::{ - newtypes::DbUrl, - source::{ - images::{ImageDetailsForm, LocalImage, LocalImageForm}, - post::{Post, PostUpdateForm}, - site::Site, - }, +use lemmy_db_schema::source::{ + images::{ImageDetailsForm, LocalImage, LocalImageForm}, + post::{Post, PostUpdateForm}, + site::Site, }; use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult}, @@ -472,30 +469,6 @@ async fn is_image_content_type(client: &ClientWithMiddleware, url: &Url) -> Lemm } } -/// When adding a new avatar, banner or similar image, delete the old one. -/// TODO: remove this function -pub async fn replace_image( - new_image: &Option>, - old_image: &Option, - context: &Data, -) -> LemmyResult<()> { - if let (Some(Some(new_image)), Some(old_image)) = (new_image, old_image) { - // Note: Oftentimes front ends will include the current image in the form. - // In this case, deleting `old_image` would also be deletion of `new_image`, - // so the deletion must be skipped for the image to be kept. - if new_image != old_image { - // Ignore errors because image may be stored externally. - let image = LocalImage::delete_by_url(&mut context.pool(), old_image) - .await - .ok(); - if let Some(image) = image { - delete_image_from_pictrs(&image.pictrs_alias, &image.pictrs_delete_token, context).await?; - } - } - } - Ok(()) -} - #[cfg(test)] mod tests { diff --git a/crates/api_common/src/site.rs b/crates/api_common/src/site.rs index 0b1fb2200..7ccf06ef5 100644 --- a/crates/api_common/src/site.rs +++ b/crates/api_common/src/site.rs @@ -201,10 +201,6 @@ pub struct CreateSite { #[cfg_attr(feature = "full", ts(optional))] pub description: Option, #[cfg_attr(feature = "full", ts(optional))] - pub icon: Option, - #[cfg_attr(feature = "full", ts(optional))] - pub banner: Option, - #[cfg_attr(feature = "full", ts(optional))] pub enable_nsfw: Option, #[cfg_attr(feature = "full", ts(optional))] pub community_creation_admin_only: Option, @@ -298,12 +294,6 @@ pub struct EditSite { /// A shorter, one line description of your site. #[cfg_attr(feature = "full", ts(optional))] pub description: Option, - /// A url for your site's icon. - #[cfg_attr(feature = "full", ts(optional))] - pub icon: Option, - /// A url for your site's banner. - #[cfg_attr(feature = "full", ts(optional))] - pub banner: Option, /// Whether to enable NSFW. #[cfg_attr(feature = "full", ts(optional))] pub enable_nsfw: Option, diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index 27b7ad531..8b73fb6e8 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -1131,31 +1131,6 @@ pub async fn proxy_image_link(link: Url, context: &LemmyContext) -> LemmyResult< proxy_image_link_internal(link, context.settings().pictrs()?.image_mode(), context).await } -pub async fn proxy_image_link_opt_api( - link: Option>, - context: &LemmyContext, -) -> LemmyResult>> { - if let Some(Some(link)) = link { - proxy_image_link(link.into(), context) - .await - .map(Some) - .map(Some) - } else { - Ok(link) - } -} - -pub async fn proxy_image_link_api( - link: Option, - context: &LemmyContext, -) -> LemmyResult> { - if let Some(link) = link { - proxy_image_link(link.into(), context).await.map(Some) - } else { - Ok(link) - } -} - pub async fn proxy_image_link_opt_apub( link: Option, context: &LemmyContext, diff --git a/crates/api_crud/src/community/update.rs b/crates/api_crud/src/community/update.rs index d9c062c53..944f5bade 100644 --- a/crates/api_crud/src/community/update.rs +++ b/crates/api_crud/src/community/update.rs @@ -6,14 +6,12 @@ use lemmy_api_common::{ build_response::build_community_response, community::{CommunityResponse, EditCommunity}, context::LemmyContext, - request::replace_image, send_activity::{ActivityChannel, SendActivityData}, utils::{ check_community_mod_action, get_url_blocklist, local_site_to_slur_regex, process_markdown_opt, - proxy_image_link_opt_api, }, }; use lemmy_db_schema::{ @@ -23,7 +21,7 @@ use lemmy_db_schema::{ local_site::LocalSite, }, traits::Crud, - utils::{diesel_string_update, diesel_url_update}, + utils::diesel_string_update, }; use lemmy_db_views::structs::LocalUserView; use lemmy_utils::{ @@ -58,14 +56,6 @@ pub async fn update_community( let old_community = Community::read(&mut context.pool(), data.community_id).await?; - let icon = diesel_url_update(data.icon.as_deref())?; - replace_image(&icon, &old_community.icon, &context).await?; - let icon = proxy_image_link_opt_api(icon, &context).await?; - - let banner = diesel_url_update(data.banner.as_deref())?; - replace_image(&banner, &old_community.banner, &context).await?; - let banner = proxy_image_link_opt_api(banner, &context).await?; - // Verify its a mod (only mods can edit it) check_community_mod_action( &local_user_view.person, @@ -91,8 +81,6 @@ pub async fn update_community( title: data.title.clone(), sidebar, description, - icon, - banner, nsfw: data.nsfw, posting_restricted_to_mods: data.posting_restricted_to_mods, visibility: data.visibility, diff --git a/crates/api_crud/src/site/create.rs b/crates/api_crud/src/site/create.rs index c8140cc28..34965742d 100644 --- a/crates/api_crud/src/site/create.rs +++ b/crates/api_crud/src/site/create.rs @@ -13,7 +13,6 @@ use lemmy_api_common::{ local_site_rate_limit_to_rate_limit_config, local_site_to_slur_regex, process_markdown_opt, - proxy_image_link_api, }, }; use lemmy_db_schema::{ @@ -24,7 +23,7 @@ use lemmy_db_schema::{ site::{Site, SiteUpdateForm}, }, traits::Crud, - utils::{diesel_string_update, diesel_url_create}, + utils::diesel_string_update, }; use lemmy_db_views::structs::{LocalUserView, SiteView}; use lemmy_utils::{ @@ -63,18 +62,10 @@ pub async fn create_site( let url_blocklist = get_url_blocklist(&context).await?; let sidebar = process_markdown_opt(&data.sidebar, &slur_regex, &url_blocklist, &context).await?; - let icon = diesel_url_create(data.icon.as_deref())?; - let icon = proxy_image_link_api(icon, &context).await?; - - let banner = diesel_url_create(data.banner.as_deref())?; - let banner = proxy_image_link_api(banner, &context).await?; - let site_form = SiteUpdateForm { name: Some(data.name.clone()), sidebar: diesel_string_update(sidebar.as_deref()), description: diesel_string_update(data.description.as_deref()), - icon: Some(icon), - banner: Some(banner), actor_id: Some(actor_id), last_refreshed_at: Some(Utc::now()), inbox_url, diff --git a/crates/api_crud/src/site/update.rs b/crates/api_crud/src/site/update.rs index d2585ea43..40b51208e 100644 --- a/crates/api_crud/src/site/update.rs +++ b/crates/api_crud/src/site/update.rs @@ -5,7 +5,6 @@ use actix_web::web::Json; use chrono::Utc; use lemmy_api_common::{ context::LemmyContext, - request::replace_image, site::{EditSite, SiteResponse}, utils::{ get_url_blocklist, @@ -13,7 +12,6 @@ use lemmy_api_common::{ local_site_rate_limit_to_rate_limit_config, local_site_to_slur_regex, process_markdown_opt, - proxy_image_link_opt_api, }, }; use lemmy_db_schema::{ @@ -26,7 +24,7 @@ use lemmy_db_schema::{ site::{Site, SiteUpdateForm}, }, traits::Crud, - utils::{diesel_string_update, diesel_url_update}, + utils::diesel_string_update, RegistrationMode, }; use lemmy_db_views::structs::{LocalUserView, SiteView}; @@ -72,20 +70,10 @@ pub async fn update_site( .as_deref(), ); - let icon = diesel_url_update(data.icon.as_deref())?; - replace_image(&icon, &site.icon, &context).await?; - let icon = proxy_image_link_opt_api(icon, &context).await?; - - let banner = diesel_url_update(data.banner.as_deref())?; - replace_image(&banner, &site.banner, &context).await?; - let banner = proxy_image_link_opt_api(banner, &context).await?; - let site_form = SiteUpdateForm { name: data.name.clone(), sidebar, description: diesel_string_update(data.description.as_deref()), - icon, - banner, content_warning: diesel_string_update(data.content_warning.as_deref()), updated: Some(Some(Utc::now())), ..Default::default() diff --git a/crates/routes/src/images/upload.rs b/crates/routes/src/images/upload.rs index 877421641..9fd20b3ef 100644 --- a/crates/routes/src/images/upload.rs +++ b/crates/routes/src/images/upload.rs @@ -4,7 +4,7 @@ use lemmy_api_common::{ context::LemmyContext, image::{CommunityIdQuery, UploadImageResponse}, request::PictrsResponse, - utils::is_mod_or_admin, + utils::{is_admin, is_mod_or_admin}, LemmyErrorType, SuccessResponse, }; @@ -13,6 +13,7 @@ use lemmy_db_schema::{ community::{Community, CommunityUpdateForm}, images::{LocalImage, LocalImageForm}, person::{Person, PersonUpdateForm}, + site::{Site, SiteUpdateForm}, }, traits::Crud, }; @@ -112,7 +113,7 @@ pub async fn upload_community_banner( is_mod_or_admin(&mut context.pool(), &local_user_view.person, community.id).await?; let image = do_upload_image(req, body, Banner, &local_user_view, &context).await?; - delete_old_image(&community.icon, &context).await?; + delete_old_image(&community.banner, &context).await?; let form = CommunityUpdateForm { banner: Some(Some(image.image_url.into())), @@ -123,6 +124,48 @@ pub async fn upload_community_banner( Ok(Json(SuccessResponse::default())) } +pub async fn upload_site_icon( + req: HttpRequest, + body: Payload, + local_user_view: LocalUserView, + context: Data, +) -> LemmyResult> { + is_admin(&local_user_view)?; + let site = Site::read_local(&mut context.pool()).await?; + + let image = do_upload_image(req, body, Avatar, &local_user_view, &context).await?; + delete_old_image(&site.icon, &context).await?; + + let form = SiteUpdateForm { + icon: Some(Some(image.image_url.into())), + ..Default::default() + }; + Site::update(&mut context.pool(), site.id, &form).await?; + + Ok(Json(SuccessResponse::default())) +} + +pub async fn upload_site_banner( + req: HttpRequest, + body: Payload, + local_user_view: LocalUserView, + context: Data, +) -> LemmyResult> { + is_admin(&local_user_view)?; + let site = Site::read_local(&mut context.pool()).await?; + + let image = do_upload_image(req, body, Banner, &local_user_view, &context).await?; + delete_old_image(&site.banner, &context).await?; + + let form = SiteUpdateForm { + banner: Some(Some(image.image_url.into())), + ..Default::default() + }; + Site::update(&mut context.pool(), site.id, &form).await?; + + Ok(Json(SuccessResponse::default())) +} + pub async fn do_upload_image( req: HttpRequest, body: Payload, diff --git a/src/api_routes_v4.rs b/src/api_routes_v4.rs index c7f0dd354..86b35312a 100644 --- a/src/api_routes_v4.rs +++ b/src/api_routes_v4.rs @@ -166,6 +166,8 @@ use lemmy_routes::images::{ upload_community_banner, upload_community_icon, upload_image, + upload_site_banner, + upload_site_icon, upload_user_avatar, upload_user_banner, }, @@ -181,7 +183,9 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) { scope("/site") .route("", get().to(get_site_v4)) .route("", post().to(create_site)) - .route("", put().to(update_site)), + .route("", put().to(update_site)) + .route("/icon", post().to(upload_site_icon)) + .route("/banner", post().to(upload_site_banner)), ) .route("/modlog", get().to(get_mod_log)) .service(