From 510b0db8698da650a5b9be1fd0985713bb0c60a2 Mon Sep 17 00:00:00 2001 From: Nutomic Date: Thu, 20 Feb 2025 17:46:36 +0000 Subject: [PATCH] Deleted user shouldnt break federation outbox (fixes #5441) (#5443) * Deleted user shouldnt break federation outbox (fixes #5441) * clippy --- .../apub/src/collections/community_outbox.rs | 14 +++-- crates/apub/src/http/community.rs | 52 ++++++++++++------- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/crates/apub/src/collections/community_outbox.rs b/crates/apub/src/collections/community_outbox.rs index c015dc591..3cab387ff 100644 --- a/crates/apub/src/collections/community_outbox.rs +++ b/crates/apub/src/collections/community_outbox.rs @@ -47,17 +47,21 @@ impl Collection for ApubCommunityOutbox { let mut ordered_items = vec![]; for post_view in post_views { - let create = CreateOrUpdatePage::new( + // ignore errors, in particular if post creator was deleted + if let Ok(create) = CreateOrUpdatePage::new( post_view.post.into(), &post_view.creator.into(), owner, CreateOrUpdateType::Create, data, ) - .await?; - let announcable = AnnouncableActivities::CreateOrUpdatePost(create); - let announce = AnnounceActivity::new(announcable.try_into()?, owner, data)?; - ordered_items.push(announce); + .await + { + let announcable = AnnouncableActivities::CreateOrUpdatePost(create); + if let Ok(announce) = AnnounceActivity::new(announcable.try_into()?, owner, data) { + ordered_items.push(announce); + } + } } Ok(GroupOutbox { diff --git a/crates/apub/src/http/community.rs b/crates/apub/src/http/community.rs index 8a6785a41..7121b453e 100644 --- a/crates/apub/src/http/community.rs +++ b/crates/apub/src/http/community.rs @@ -168,6 +168,8 @@ pub(crate) mod tests { instance::Instance, local_site::{LocalSite, LocalSiteInsertForm}, local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitInsertForm}, + person::{Person, PersonInsertForm}, + post::{Post, PostInsertForm}, site::{Site, SiteInsertForm}, }, traits::Crud, @@ -180,7 +182,7 @@ pub(crate) mod tests { deleted: bool, visibility: CommunityVisibility, context: &Data, - ) -> LemmyResult<(Instance, Community)> { + ) -> LemmyResult<(Instance, Community, Path)> { let instance = Instance::read_or_create(&mut context.pool(), "my_domain.tld".to_string()).await?; create_local_site(context, instance.id).await?; @@ -196,7 +198,11 @@ pub(crate) mod tests { ) }; let community = Community::create(&mut context.pool(), &community_form).await?; - Ok((instance, community)) + let path: Path = CommunityPath { + community_name: community.name.clone(), + } + .into(); + Ok((instance, community, path)) } /// Necessary for the community outbox fetching @@ -226,7 +232,7 @@ pub(crate) mod tests { #[serial] async fn test_get_community() -> LemmyResult<()> { let context = LemmyContext::init_test_context().await; - let (instance, community) = init(false, CommunityVisibility::Public, &context).await?; + let (instance, community, path) = init(false, CommunityVisibility::Public, &context).await?; let request = TestRequest::default().to_http_request(); // fetch invalid community @@ -237,9 +243,6 @@ pub(crate) mod tests { assert!(res.is_err()); // fetch valid community - let path = CommunityPath { - community_name: community.name.clone(), - }; let res = get_apub_community_http(path.clone().into(), context.reset_request_count()).await?; assert_eq!(200, res.status()); let res_group: Group = decode_response(res).await?; @@ -266,8 +269,7 @@ pub(crate) mod tests { let res = get_apub_community_moderators(path.clone().into(), context.reset_request_count()).await?; assert_eq!(200, res.status()); - let res = - get_apub_community_outbox(path.into(), context.reset_request_count(), request).await?; + let res = get_apub_community_outbox(path, context.reset_request_count(), request).await?; assert_eq!(200, res.status()); Instance::delete(&mut context.pool(), instance.id).await?; @@ -278,14 +280,10 @@ pub(crate) mod tests { #[serial] async fn test_get_deleted_community() -> LemmyResult<()> { let context = LemmyContext::init_test_context().await; - let (instance, community) = init(true, CommunityVisibility::LocalOnly, &context).await?; + let (instance, _, path) = init(true, CommunityVisibility::LocalOnly, &context).await?; let request = TestRequest::default().to_http_request(); // should return tombstone - let path: Path = CommunityPath { - community_name: community.name.clone(), - } - .into(); let res = get_apub_community_http(path.clone().into(), context.reset_request_count()).await?; assert_eq!(410, res.status()); let res_tombstone = decode_response::(res).await; @@ -322,13 +320,9 @@ pub(crate) mod tests { #[serial] async fn test_get_local_only_community() -> LemmyResult<()> { let context = LemmyContext::init_test_context().await; - let (instance, community) = init(false, CommunityVisibility::LocalOnly, &context).await?; + let (instance, _, path) = init(false, CommunityVisibility::LocalOnly, &context).await?; let request = TestRequest::default().to_http_request(); - let path: Path = CommunityPath { - community_name: community.name.clone(), - } - .into(); let res = get_apub_community_http(path.clone().into(), context.reset_request_count()).await; assert!(res.is_err()); let res = get_apub_community_featured( @@ -356,4 +350,26 @@ pub(crate) mod tests { Instance::delete(&mut context.pool(), instance.id).await?; Ok(()) } + + #[tokio::test] + #[serial] + async fn test_outbox_deleted_user() -> LemmyResult<()> { + let context = LemmyContext::init_test_context().await; + let (instance, community, path) = init(false, CommunityVisibility::Public, &context).await?; + let request = TestRequest::default().to_http_request(); + + // post from deleted user shouldnt break outbox + let mut form = PersonInsertForm::new("jerry".to_string(), String::new(), instance.id); + form.deleted = Some(true); + let person = Person::create(&mut context.pool(), &form).await?; + + let form = PostInsertForm::new("title".to_string(), person.id, community.id); + Post::create(&mut context.pool(), &form).await?; + + let res = get_apub_community_outbox(path, context.reset_request_count(), request).await?; + assert_eq!(200, res.status()); + + Instance::delete(&mut context.pool(), instance.id).await?; + Ok(()) + } }