From b0ed202c6aad9b5e5d1ade10a0948cb36bf341b9 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Thu, 28 Dec 2023 22:25:14 -0500 Subject: [PATCH] update weight cover image in update endpoint --- .../model_weights/edit/update_weight.rs | 30 +++++++----- .../endpoints/weights/update_weight.rs | 46 +++++++++++++++---- 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/crates/lib/mysql_queries/src/queries/model_weights/edit/update_weight.rs b/crates/lib/mysql_queries/src/queries/model_weights/edit/update_weight.rs index cc9c050264..3291c21692 100644 --- a/crates/lib/mysql_queries/src/queries/model_weights/edit/update_weight.rs +++ b/crates/lib/mysql_queries/src/queries/model_weights/edit/update_weight.rs @@ -3,26 +3,31 @@ use sqlx::{MySql, MySqlPool, QueryBuilder}; use enums::common::visibility::Visibility; use errors::AnyhowResult; +use tokens::tokens::media_files::MediaFileToken; use tokens::tokens::model_weights::ModelWeightToken; pub struct UpdateWeightArgs<'a> { pub weight_token: &'a ModelWeightToken, pub title: Option<&'a str>, + pub cover_image: Option>, pub maybe_description_markdown: Option<&'a str>, pub maybe_description_rendered_html: Option<&'a str>, pub creator_set_visibility: Option<&'a Visibility>, - pub weights_type: Option, - pub weights_category: Option, pub mysql_pool: &'a MySqlPool, } +pub enum CoverImageOption<'a> { + ClearCoverImage, + SetCoverImage(&'a MediaFileToken), +} + pub async fn update_weights(args: UpdateWeightArgs<'_>) -> AnyhowResult<()> { if args.title.is_none() && args.maybe_description_markdown.is_none() && args.maybe_description_rendered_html.is_none() && args.creator_set_visibility.is_none() - && args.weights_type.is_none() - && args.weights_category.is_none(){ + && args.cover_image.is_none() + { return Err(anyhow!("No fields to update")); } @@ -51,13 +56,16 @@ SET separated.push("creator_set_visibility = "); separated.push_bind_unseparated(creator_set_visibility.to_str()); } - if let Some(weights_type) = args.weights_type { - separated.push("weights_type = "); - separated.push_bind_unseparated(weights_type); - } - if let Some(weights_category) = args.weights_category { - separated.push("weights_category = "); - separated.push_bind_unseparated(weights_category); + if let Some(cover_image_option) = args.cover_image { + match cover_image_option { + CoverImageOption::ClearCoverImage => { + separated.push(" maybe_cover_image_media_file_token = NULL "); + } + CoverImageOption::SetCoverImage(media_file_token) => { + separated.push("maybe_cover_image_media_file_token = "); + separated.push_bind_unseparated(media_file_token.as_str()); + } + } } separated.push("version = version + 1"); diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/weights/update_weight.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/weights/update_weight.rs index 1fb7b4d011..c501e7e428 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/weights/update_weight.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/weights/update_weight.rs @@ -7,28 +7,32 @@ use actix_web::http::StatusCode; use actix_web::web::Path; use log::warn; use utoipa::ToSchema; +use enums::by_table::media_files::media_file_type::MediaFileType; use enums::common::visibility::Visibility; use http_server_common::response::response_success_helpers::simple_json_success; use http_server_common::response::serialize_as_json_error::serialize_as_json_error; -use mysql_queries::queries::model_weights::edit::update_weight::{update_weights, UpdateWeightArgs}; +use mysql_queries::queries::media_files::get_media_file::get_media_file; +use mysql_queries::queries::model_weights::edit::update_weight::{CoverImageOption, update_weights, UpdateWeightArgs}; use mysql_queries::queries::model_weights::get_weight::get_weight_by_token; +use tokens::tokens::media_files::MediaFileToken; use tokens::tokens::model_weights::ModelWeightToken; use user_input_common::check_for_slurs::contains_slurs; use user_input_common::markdown_to_html::markdown_to_html; use crate::server_state::ServerState; -/// TODO will eventually be polymorphic +// TODO will eventually be polymorphic +/// **IMPORTANT**: This endpoint handles sparse (by-field) updates rather than wholesale updates. +/// That is, if a field is absent, we do not update it (as opposed to clearing it). #[derive(Deserialize, ToSchema)] pub struct UpdateWeightRequest { pub title: Option, pub description_markdown: Option, - // KS: We should probably remove this - // Users have to update markdown, not html directly - pub description_rendered_html: Option, - pub weight_type: Option, - pub weight_category: Option, + + /// The media file token of the *image* media file. + /// Set to *empty string* to clear the cover image. + pub cover_image_media_file_token: Option, pub visibility: Option, } @@ -144,10 +148,10 @@ pub async fn update_weight_handler( } let mut weight_title = None; + let mut cover_image = None; let mut description_markdown = None; let mut description_rendered_html = None; - if let Some(title) = &request.title { if (contains_slurs(title)) { return Err(UpdateWeightError::BadInput("Title contains slurs".to_string())); @@ -155,6 +159,29 @@ pub async fn update_weight_handler( weight_title = Some(title.trim().to_string()); } + if let Some(media_file_token) = &request.cover_image_media_file_token { + if media_file_token.as_str().trim().is_empty() { + cover_image = Some(CoverImageOption::ClearCoverImage); + } else { + let maybe_media_file = get_media_file( + media_file_token, + false, // NB: Even mods shouldn't set deleted media files. + &server_state.mysql_pool + ).await.map_err(|err| { + warn!("Error looking up media file: {:?}", err); + UpdateWeightError::ServerError + })?; + + let maybe_media_file_type = maybe_media_file.map(|media_file| media_file.media_type); + + match maybe_media_file_type { + Some(MediaFileType::Image) => cover_image = Some(CoverImageOption::SetCoverImage(media_file_token)), + None => return Err(UpdateWeightError::BadInput("Media file does not exist".to_string())), + _ => return Err(UpdateWeightError::BadInput("Media file is the wrong type".to_string())), + } + } + } + if let Some(markdown) = &request.description_markdown { if (contains_slurs(markdown)) { return Err(UpdateWeightError::BadInput("Description contains slurs".to_string())); @@ -169,11 +196,10 @@ pub async fn update_weight_handler( weight_token: &ModelWeightToken::new(path.weight_token.clone()), mysql_pool: &server_state.mysql_pool, title: weight_title.as_deref(), + cover_image, maybe_description_markdown: description_markdown.as_deref(), maybe_description_rendered_html: description_rendered_html.as_deref(), creator_set_visibility: request.visibility.as_ref(), - weights_type: request.weight_type.as_deref().map(|s| s.to_string()), - weights_category: request.weight_category.as_deref().map(|s| s.to_string()), }).await; match query_result {