From 8b9edf77012714b349638f82689af657f2b5f623 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Tue, 22 Oct 2024 14:49:04 +0200 Subject: [PATCH 1/2] Always assign default language before checking if language is allowed (fixes #5131) --- crates/api_crud/src/comment/create.rs | 18 ++++------- crates/api_crud/src/comment/update.rs | 9 ++++-- crates/api_crud/src/post/create.rs | 18 ++++------- crates/api_crud/src/post/update.rs | 9 ++++-- crates/db_schema/src/impls/actor_language.rs | 34 ++++++++++++-------- 5 files changed, 48 insertions(+), 40 deletions(-) diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index f85a4d9290..192035c583 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -89,17 +89,13 @@ pub async fn create_comment( } // 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? - } - }; + let language_id = default_post_language( + &mut context.pool(), + data.language_id, + community_id, + local_user_view.local_user.id, + ) + .await?; CommunityLanguage::is_allowed_community_language(&mut context.pool(), language_id, community_id) .await?; diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index 51f65aa670..a86b375a03 100644 --- a/crates/api_crud/src/comment/update.rs +++ b/crates/api_crud/src/comment/update.rs @@ -55,14 +55,19 @@ pub async fn update_comment( Err(LemmyErrorType::NoCommentEditAllowed)? } - if let Some(language_id) = data.language_id { + let language_id = default_post_language( + &mut context.pool(), + data.language_id, + community_id, + local_user_view.local_user.id, + ) + .await?; CommunityLanguage::is_allowed_community_language( &mut context.pool(), language_id, orig_comment.community.id, ) .await?; - } let slur_regex = local_site_to_slur_regex(&local_site); let url_blocklist = get_url_blocklist(&context).await?; diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 90c68bdbd9..86b20cb5cd 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -105,17 +105,13 @@ pub async fn create_post( } // 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? - } - }; + let language_id = default_post_language( + &mut context.pool(), + data.language_id, + 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. diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index cef8bfea8e..1c59d73c3f 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -101,14 +101,19 @@ pub async fn update_post( Err(LemmyErrorType::NoPostEditAllowed)? } - if let Some(language_id) = data.language_id { + let language_id = default_post_language( + &mut context.pool(), + data.language_id, + community_id, + local_user_view.local_user.id, + ) + .await?; CommunityLanguage::is_allowed_community_language( &mut context.pool(), language_id, orig_post.community_id, ) .await?; - } // handle changes to scheduled_publish_time let scheduled_publish_time = match ( diff --git a/crates/db_schema/src/impls/actor_language.rs b/crates/db_schema/src/impls/actor_language.rs index bff729f41c..9644961229 100644 --- a/crates/db_schema/src/impls/actor_language.rs +++ b/crates/db_schema/src/impls/actor_language.rs @@ -321,26 +321,32 @@ impl CommunityLanguage { pub async fn default_post_language( pool: &mut DbPool<'_>, + language_id: Option, community_id: CommunityId, local_user_id: LocalUserId, ) -> Result { 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?; + 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 { + 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) + } + } + Some(lid) => Ok(lid), } } From c8098196a756b54ae4fffcda182935244a3453dd Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Tue, 22 Oct 2024 14:57:28 +0200 Subject: [PATCH 2/2] handle all logic in same fn --- crates/api_crud/src/comment/create.rs | 5 ---- crates/api_crud/src/comment/update.rs | 24 +++++++------------ crates/api_crud/src/post/create.rs | 7 ------ crates/api_crud/src/post/update.rs | 24 +++++++------------ crates/db_schema/src/impls/actor_language.rs | 25 +++++++++++--------- 5 files changed, 32 insertions(+), 53 deletions(-) diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 192035c583..7f7a0441a2 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -18,7 +18,6 @@ use lemmy_api_common::{ use lemmy_db_schema::{ impls::actor_language::default_post_language, source::{ - actor_language::CommunityLanguage, comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm}, comment_reply::{CommentReply, CommentReplyUpdateForm}, local_site::LocalSite, @@ -88,7 +87,6 @@ pub async fn create_comment( check_comment_depth(parent)?; } - // attempt to set default language if none was provided let language_id = default_post_language( &mut context.pool(), data.language_id, @@ -97,9 +95,6 @@ pub async fn create_comment( ) .await?; - CommunityLanguage::is_allowed_community_language(&mut context.pool(), language_id, community_id) - .await?; - let comment_form = CommentInsertForm { language_id: Some(language_id), ..CommentInsertForm::new(local_user_view.person.id, data.post_id, content.clone()) diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index a86b375a03..6e320b2dbf 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::default_post_language, source::{ - actor_language::CommunityLanguage, comment::{Comment, CommentUpdateForm}, local_site::LocalSite, }, @@ -55,19 +55,13 @@ pub async fn update_comment( Err(LemmyErrorType::NoCommentEditAllowed)? } - let language_id = default_post_language( - &mut context.pool(), - data.language_id, - community_id, - local_user_view.local_user.id, - ) - .await?; - CommunityLanguage::is_allowed_community_language( - &mut context.pool(), - language_id, - orig_comment.community.id, - ) - .await?; + let language_id = default_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?; @@ -79,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 86b20cb5cd..f8fdc592e4 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -19,7 +19,6 @@ use lemmy_api_common::{ use lemmy_db_schema::{ impls::actor_language::default_post_language, source::{ - actor_language::CommunityLanguage, community::Community, local_site::LocalSite, post::{Post, PostInsertForm, PostLike, PostLikeForm}, @@ -104,7 +103,6 @@ pub async fn create_post( .await?; } - // attempt to set default language if none was provided let language_id = default_post_language( &mut context.pool(), data.language_id, @@ -113,11 +111,6 @@ pub async fn create_post( ) .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 scheduled_publish_time = convert_published_time(data.scheduled_publish_time, &local_user_view, &context).await?; let post_form = PostInsertForm { diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index 1c59d73c3f..e047126646 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::default_post_language, source::{ - actor_language::CommunityLanguage, community::Community, local_site::LocalSite, post::{Post, PostUpdateForm}, @@ -101,19 +101,13 @@ pub async fn update_post( Err(LemmyErrorType::NoPostEditAllowed)? } - let language_id = default_post_language( - &mut context.pool(), - data.language_id, - community_id, - local_user_view.local_user.id, - ) - .await?; - CommunityLanguage::is_allowed_community_language( - &mut context.pool(), - language_id, - orig_post.community_id, - ) - .await?; + let language_id = default_post_language( + &mut context.pool(), + data.language_id, + orig_post.community_id, + local_user_view.local_user.id, + ) + .await?; // handle changes to scheduled_publish_time let scheduled_publish_time = match ( @@ -136,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 9644961229..dc0f6f48ce 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, @@ -324,10 +324,10 @@ pub async fn default_post_language( 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?; - match language_id { + 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))) @@ -338,16 +338,19 @@ pub async fn default_post_language( .await?; if intersection.len() == 1 { - Ok(intersection.pop().unwrap_or(UNDETERMINED_ID)) + 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)) + intersection.pop().unwrap_or(UNDETERMINED_ID) } else { - Ok(UNDETERMINED_ID) + UNDETERMINED_ID } } - Some(lid) => Ok(lid), - } + 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 @@ -596,7 +599,7 @@ mod tests { #[tokio::test] #[serial] - async fn test_default_post_language() -> Result<(), Error> { + async fn test_default_post_language() -> LemmyResult<()> { let pool = &build_db_pool_for_tests().await; let pool = &mut pool.into(); let (site, instance) = create_test_site(pool).await?; @@ -619,7 +622,7 @@ 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?; + let def1 = default_post_language(pool, None, community.id, local_user.id).await?; assert_eq!(UNDETERMINED_ID, def1); let ru = Language::read_id_from_code(pool, "ru").await?; @@ -632,7 +635,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 = default_post_language(pool, None, community.id, local_user.id).await?; assert_eq!(ru, def2); Person::delete(pool, person.id).await?;