From f916309df827c19d0df1cc930dde508515687a5c Mon Sep 17 00:00:00 2001 From: Nutomic Date: Tue, 12 Nov 2024 20:52:39 +0100 Subject: [PATCH] Always assign default language before checking if language is allowed (#5132) * Always assign default language before checking if language is allowed (fixes #5131) * handle all logic in same fn * fix test * rename --- crates/api_crud/src/comment/create.rs | 25 +++------ crates/api_crud/src/comment/update.rs | 19 ++++--- crates/api_crud/src/post/create.rs | 27 +++------- crates/api_crud/src/post/update.rs | 19 ++++--- crates/db_schema/src/impls/actor_language.rs | 56 ++++++++++++-------- 5 files changed, 68 insertions(+), 78 deletions(-) diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 65aa1f612..edcf7db30 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -16,9 +16,8 @@ use lemmy_api_common::{ }, }; use lemmy_db_schema::{ - impls::actor_language::default_post_language, + impls::actor_language::validate_post_language, source::{ - actor_language::CommunityLanguage, comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm}, comment_reply::{CommentReply, CommentReplyUpdateForm}, local_site::LocalSite, @@ -93,21 +92,13 @@ pub async fn create_comment( check_comment_depth(parent)?; } - // attempt to set default language if none was provided - let language_id = match data.language_id { - Some(lid) => lid, - None => { - default_post_language( - &mut context.pool(), - community_id, - local_user_view.local_user.id, - ) - .await? - } - }; - - CommunityLanguage::is_allowed_community_language(&mut context.pool(), language_id, community_id) - .await?; + let language_id = validate_post_language( + &mut context.pool(), + data.language_id, + community_id, + local_user_view.local_user.id, + ) + .await?; let comment_form = CommentInsertForm { language_id: Some(language_id), diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index 95cc85fe4..85ee9bff0 100644 --- a/crates/api_crud/src/comment/update.rs +++ b/crates/api_crud/src/comment/update.rs @@ -13,8 +13,8 @@ use lemmy_api_common::{ }, }; use lemmy_db_schema::{ + impls::actor_language::validate_post_language, source::{ - actor_language::CommunityLanguage, comment::{Comment, CommentUpdateForm}, local_site::LocalSite, }, @@ -55,14 +55,13 @@ pub async fn update_comment( Err(LemmyErrorType::NoCommentEditAllowed)? } - if let Some(language_id) = data.language_id { - CommunityLanguage::is_allowed_community_language( - &mut context.pool(), - language_id, - orig_comment.community.id, - ) - .await?; - } + let language_id = validate_post_language( + &mut context.pool(), + data.language_id, + orig_comment.community.id, + local_user_view.local_user.id, + ) + .await?; let slur_regex = local_site_to_slur_regex(&local_site); let url_blocklist = get_url_blocklist(&context).await?; @@ -74,7 +73,7 @@ pub async fn update_comment( let comment_id = data.comment_id; let form = CommentUpdateForm { content, - language_id: data.language_id, + language_id: Some(language_id), updated: Some(Some(naive_now())), ..Default::default() }; diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 16932cacb..5dee5e21c 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -17,9 +17,8 @@ use lemmy_api_common::{ }, }; use lemmy_db_schema::{ - impls::actor_language::default_post_language, + impls::actor_language::validate_post_language, source::{ - actor_language::CommunityLanguage, community::Community, local_site::LocalSite, post::{Post, PostInsertForm, PostLike, PostLikeForm}, @@ -98,23 +97,13 @@ pub async fn create_post( .await?; } - // attempt to set default language if none was provided - let language_id = match data.language_id { - Some(lid) => lid, - None => { - default_post_language( - &mut context.pool(), - community.id, - local_user_view.local_user.id, - ) - .await? - } - }; - - // Only need to check if language is allowed in case user set it explicitly. When using default - // language, it already only returns allowed languages. - CommunityLanguage::is_allowed_community_language(&mut context.pool(), language_id, community.id) - .await?; + let language_id = validate_post_language( + &mut context.pool(), + data.language_id, + data.community_id, + local_user_view.local_user.id, + ) + .await?; let scheduled_publish_time = convert_published_time(data.scheduled_publish_time, &local_user_view, &context).await?; diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index fc23e7d9e..217a6cc24 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -15,8 +15,8 @@ use lemmy_api_common::{ }, }; use lemmy_db_schema::{ + impls::actor_language::validate_post_language, source::{ - actor_language::CommunityLanguage, community::Community, local_site::LocalSite, post::{Post, PostUpdateForm}, @@ -101,14 +101,13 @@ pub async fn update_post( Err(LemmyErrorType::NoPostEditAllowed)? } - if let Some(language_id) = data.language_id { - CommunityLanguage::is_allowed_community_language( - &mut context.pool(), - language_id, - orig_post.community.id, - ) - .await?; - } + let language_id = validate_post_language( + &mut context.pool(), + data.language_id, + orig_post.post.community_id, + local_user_view.local_user.id, + ) + .await?; // handle changes to scheduled_publish_time let scheduled_publish_time = match ( @@ -131,7 +130,7 @@ pub async fn update_post( body, alt_text, nsfw: data.nsfw, - language_id: data.language_id, + language_id: Some(language_id), updated: Some(Some(naive_now())), scheduled_publish_time, ..Default::default() diff --git a/crates/db_schema/src/impls/actor_language.rs b/crates/db_schema/src/impls/actor_language.rs index b4ad0d347..8d4c471be 100644 --- a/crates/db_schema/src/impls/actor_language.rs +++ b/crates/db_schema/src/impls/actor_language.rs @@ -197,7 +197,7 @@ impl SiteLanguage { impl CommunityLanguage { /// Returns true if the given language is one of configured languages for given community - pub async fn is_allowed_community_language( + async fn is_allowed_community_language( pool: &mut DbPool<'_>, for_language_id: LanguageId, for_community_id: CommunityId, @@ -319,29 +319,38 @@ impl CommunityLanguage { } } -pub async fn default_post_language( +pub async fn validate_post_language( pool: &mut DbPool<'_>, + language_id: Option, community_id: CommunityId, local_user_id: LocalUserId, -) -> Result { +) -> LemmyResult { use crate::schema::{community_language::dsl as cl, local_user_language::dsl as ul}; let conn = &mut get_conn(pool).await?; - let mut intersection = ul::local_user_language - .inner_join(cl::community_language.on(ul::language_id.eq(cl::language_id))) - .filter(ul::local_user_id.eq(local_user_id)) - .filter(cl::community_id.eq(community_id)) - .select(cl::language_id) - .get_results::(conn) - .await?; + let language_id = match language_id { + None | Some(LanguageId(0)) => { + let mut intersection = ul::local_user_language + .inner_join(cl::community_language.on(ul::language_id.eq(cl::language_id))) + .filter(ul::local_user_id.eq(local_user_id)) + .filter(cl::community_id.eq(community_id)) + .select(cl::language_id) + .get_results::(conn) + .await?; - if intersection.len() == 1 { - Ok(intersection.pop().unwrap_or(UNDETERMINED_ID)) - } else if intersection.len() == 2 && intersection.contains(&UNDETERMINED_ID) { - intersection.retain(|i| i != &UNDETERMINED_ID); - Ok(intersection.pop().unwrap_or(UNDETERMINED_ID)) - } else { - Ok(UNDETERMINED_ID) - } + if intersection.len() == 1 { + intersection.pop().unwrap_or(UNDETERMINED_ID) + } else if intersection.len() == 2 && intersection.contains(&UNDETERMINED_ID) { + intersection.retain(|i| i != &UNDETERMINED_ID); + intersection.pop().unwrap_or(UNDETERMINED_ID) + } else { + UNDETERMINED_ID + } + } + Some(lid) => lid, + }; + + CommunityLanguage::is_allowed_community_language(pool, language_id, community_id).await?; + Ok(language_id) } /// If no language is given, set all languages @@ -590,7 +599,7 @@ mod tests { #[tokio::test] #[serial] - async fn test_default_post_language() -> Result<(), Error> { + async fn test_validate_post_language() -> LemmyResult<()> { let pool = &build_db_pool_for_tests(); let pool = &mut pool.into(); let (site, instance) = create_test_site(pool).await?; @@ -613,8 +622,11 @@ mod tests { LocalUserLanguage::update(pool, test_langs2, local_user.id).await?; // no overlap in user/community languages, so defaults to undetermined - let def1 = default_post_language(pool, community.id, local_user.id).await?; - assert_eq!(UNDETERMINED_ID, def1); + let def1 = validate_post_language(pool, None, community.id, local_user.id).await; + assert_eq!( + Some(LemmyErrorType::LanguageNotAllowed), + def1.err().map(|e| e.error_type) + ); let ru = Language::read_id_from_code(pool, "ru").await?; let test_langs3 = vec![ @@ -626,7 +638,7 @@ mod tests { LocalUserLanguage::update(pool, test_langs3, local_user.id).await?; // this time, both have ru as common lang - let def2 = default_post_language(pool, community.id, local_user.id).await?; + let def2 = validate_post_language(pool, None, community.id, local_user.id).await?; assert_eq!(ru, def2); Person::delete(pool, person.id).await?;