From: Nutomic Date: Thu, 1 Dec 2022 20:52:49 +0000 (+0000) Subject: Use audience field to federate items in groups (fixes #2464) (#2584) X-Git-Url: http://these/git/%7B%60%24%7BghostArchiveUrl%7D/static/%7Bthis.state.thumbnail%7D?a=commitdiff_plain;h=bcf5c91f81f54c3a3fda7bdf6b24a077a45413be;p=lemmy.git Use audience field to federate items in groups (fixes #2464) (#2584) --- diff --git a/crates/api/src/post/lock.rs b/crates/api/src/post/lock.rs index d47088e8..ae726ee9 100644 --- a/crates/api/src/post/lock.rs +++ b/crates/api/src/post/lock.rs @@ -11,7 +11,7 @@ use lemmy_api_common::{ }; use lemmy_apub::{ objects::post::ApubPost, - protocol::activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType}, + protocol::activities::{create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType}, }; use lemmy_db_schema::{ source::{ @@ -76,7 +76,7 @@ impl Perform for LockPost { ModLockPost::create(context.pool(), &form).await?; // apub updates - CreateOrUpdatePost::send( + CreateOrUpdatePage::send( updated_post, &local_user_view.person.clone().into(), CreateOrUpdateType::Update, diff --git a/crates/api/src/post/sticky.rs b/crates/api/src/post/sticky.rs index ec4c39a8..384ba52d 100644 --- a/crates/api/src/post/sticky.rs +++ b/crates/api/src/post/sticky.rs @@ -11,7 +11,7 @@ use lemmy_api_common::{ }; use lemmy_apub::{ objects::post::ApubPost, - protocol::activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType}, + protocol::activities::{create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType}, }; use lemmy_db_schema::{ source::{ @@ -78,7 +78,7 @@ impl Perform for StickyPost { // Apub updates // TODO stickied should pry work like locked for ease of use - CreateOrUpdatePost::send( + CreateOrUpdatePage::send( updated_post, &local_user_view.person.clone().into(), CreateOrUpdateType::Update, diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 5e067b18..f027b0fe 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -14,7 +14,7 @@ use lemmy_api_common::{ use lemmy_apub::{ generate_local_apub_endpoint, objects::comment::ApubComment, - protocol::activities::{create_or_update::comment::CreateOrUpdateComment, CreateOrUpdateType}, + protocol::activities::{create_or_update::note::CreateOrUpdateNote, CreateOrUpdateType}, EndpointType, }; use lemmy_db_schema::{ @@ -158,7 +158,7 @@ impl PerformCrud for CreateComment { .map_err(|e| LemmyError::from_error_message(e, "couldnt_like_comment"))?; let apub_comment: ApubComment = updated_comment.into(); - CreateOrUpdateComment::send( + CreateOrUpdateNote::send( apub_comment.clone(), &local_user_view.person.clone().into(), CreateOrUpdateType::Create, diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index d9415295..0d89acc2 100644 --- a/crates/api_crud/src/comment/update.rs +++ b/crates/api_crud/src/comment/update.rs @@ -12,7 +12,7 @@ use lemmy_api_common::{ }, }; use lemmy_apub::protocol::activities::{ - create_or_update::comment::CreateOrUpdateComment, + create_or_update::note::CreateOrUpdateNote, CreateOrUpdateType, }; use lemmy_db_schema::{ @@ -115,7 +115,7 @@ impl PerformCrud for EditComment { .await?; // Send the apub update - CreateOrUpdateComment::send( + CreateOrUpdateNote::send( updated_comment.into(), &local_user_view.person.into(), CreateOrUpdateType::Update, diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 20d32b12..cad8b28e 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -15,7 +15,7 @@ use lemmy_api_common::{ use lemmy_apub::{ generate_local_apub_endpoint, objects::post::ApubPost, - protocol::activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType}, + protocol::activities::{create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType}, EndpointType, }; use lemmy_db_schema::{ @@ -174,7 +174,7 @@ impl PerformCrud for CreatePost { } let apub_post: ApubPost = updated_post.into(); - CreateOrUpdatePost::send( + CreateOrUpdatePage::send( apub_post.clone(), &local_user_view.person.clone().into(), CreateOrUpdateType::Create, diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index f6a2e084..11b566bc 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -11,7 +11,7 @@ use lemmy_api_common::{ }, }; use lemmy_apub::protocol::activities::{ - create_or_update::post::CreateOrUpdatePost, + create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType, }; use lemmy_db_schema::{ @@ -122,7 +122,7 @@ impl PerformCrud for EditPost { }; // Send apub update - CreateOrUpdatePost::send( + CreateOrUpdatePage::send( updated_post.into(), &local_user_view.person.clone().into(), CreateOrUpdateType::Update, diff --git a/crates/api_crud/src/private_message/create.rs b/crates/api_crud/src/private_message/create.rs index 84e747ff..35bc09e2 100644 --- a/crates/api_crud/src/private_message/create.rs +++ b/crates/api_crud/src/private_message/create.rs @@ -13,7 +13,7 @@ use lemmy_api_common::{ use lemmy_apub::{ generate_local_apub_endpoint, protocol::activities::{ - create_or_update::private_message::CreateOrUpdatePrivateMessage, + create_or_update::chat_message::CreateOrUpdateChatMessage, CreateOrUpdateType, }, EndpointType, @@ -85,7 +85,7 @@ impl PerformCrud for CreatePrivateMessage { .await .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_private_message"))?; - CreateOrUpdatePrivateMessage::send( + CreateOrUpdateChatMessage::send( updated_private_message.into(), &local_user_view.person.into(), CreateOrUpdateType::Create, diff --git a/crates/api_crud/src/private_message/update.rs b/crates/api_crud/src/private_message/update.rs index dfe06e8e..5f79735e 100644 --- a/crates/api_crud/src/private_message/update.rs +++ b/crates/api_crud/src/private_message/update.rs @@ -5,7 +5,7 @@ use lemmy_api_common::{ utils::{get_local_user_view_from_jwt, local_site_to_slur_regex}, }; use lemmy_apub::protocol::activities::{ - create_or_update::private_message::CreateOrUpdatePrivateMessage, + create_or_update::chat_message::CreateOrUpdateChatMessage, CreateOrUpdateType, }; use lemmy_db_schema::{ @@ -56,7 +56,7 @@ impl PerformCrud for EditPrivateMessage { .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_private_message"))?; // Send the apub update - CreateOrUpdatePrivateMessage::send( + CreateOrUpdateChatMessage::send( updated_private_message.into(), &local_user_view.person.into(), CreateOrUpdateType::Update, diff --git a/crates/apub/assets/lemmy/activities/block/block_user.json b/crates/apub/assets/lemmy/activities/block/block_user.json index f400fa50..ffe0504f 100644 --- a/crates/apub/assets/lemmy/activities/block/block_user.json +++ b/crates/apub/assets/lemmy/activities/block/block_user.json @@ -7,6 +7,7 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "target": "http://enterprise.lemmy.ml/c/main", "type": "Block", "removeData": true, diff --git a/crates/apub/assets/lemmy/activities/block/undo_block_user.json b/crates/apub/assets/lemmy/activities/block/undo_block_user.json index 99f90778..15ab22b2 100644 --- a/crates/apub/assets/lemmy/activities/block/undo_block_user.json +++ b/crates/apub/assets/lemmy/activities/block/undo_block_user.json @@ -12,6 +12,7 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "target": "http://enterprise.lemmy.ml/c/main", "type": "Block", "removeData": true, @@ -22,6 +23,7 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "type": "Undo", "id": "http://enterprise.lemmy.ml/activities/undo/06a20ffb-3e32-42fb-8f4c-674b36d7c557" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/community/add_mod.json b/crates/apub/assets/lemmy/activities/community/add_mod.json index d0eedd8b..69cfabc9 100644 --- a/crates/apub/assets/lemmy/activities/community/add_mod.json +++ b/crates/apub/assets/lemmy/activities/community/add_mod.json @@ -8,6 +8,7 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "type": "Add", "id": "http://enterprise.lemmy.ml/activities/add/ec069147-77c3-447f-88c8-0ef1df10403f" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/community/remove_mod.json b/crates/apub/assets/lemmy/activities/community/remove_mod.json index 2932fec3..0c6db155 100644 --- a/crates/apub/assets/lemmy/activities/community/remove_mod.json +++ b/crates/apub/assets/lemmy/activities/community/remove_mod.json @@ -9,5 +9,6 @@ ], "type": "Remove", "target": "http://enterprise.lemmy.ml/c/main/moderators", + "audience": "http://enterprise.lemmy.ml/u/main", "id": "http://enterprise.lemmy.ml/activities/remove/aab114f8-cfbd-4935-a5b7-e1a64603650d" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/community/report_page.json b/crates/apub/assets/lemmy/activities/community/report_page.json index bd1691b5..e58f656c 100644 --- a/crates/apub/assets/lemmy/activities/community/report_page.json +++ b/crates/apub/assets/lemmy/activities/community/report_page.json @@ -3,6 +3,7 @@ "to": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "object": "http://enterprise.lemmy.ml/post/7", "summary": "report this post", "type": "Flag", diff --git a/crates/apub/assets/lemmy/activities/community/update_community.json b/crates/apub/assets/lemmy/activities/community/update_community.json index 5ffe0fb9..3da15a06 100644 --- a/crates/apub/assets/lemmy/activities/community/update_community.json +++ b/crates/apub/assets/lemmy/activities/community/update_community.json @@ -43,6 +43,7 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "type": "Update", "id": "http://ds9.lemmy.ml/activities/update/d3717cf5-096d-473f-9530-5d52f9d51f5f" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/create_or_update/create_note.json b/crates/apub/assets/lemmy/activities/create_or_update/create_note.json index 33ce1cfd..6eecfcfc 100644 --- a/crates/apub/assets/lemmy/activities/create_or_update/create_note.json +++ b/crates/apub/assets/lemmy/activities/create_or_update/create_note.json @@ -10,6 +10,11 @@ "to": [ "https://www.w3.org/ns/activitystreams#Public" ], + "cc": [ + "http://enterprise.lemmy.ml/c/main", + "http://ds9.lemmy.ml/u/lemmy_alpha" + ], + "audience": "http://ds9.lemmy.ml/u/lemmy_alpha", "content": "hello", "mediaType": "text/html", "source": { @@ -23,6 +28,7 @@ "http://enterprise.lemmy.ml/c/main", "http://ds9.lemmy.ml/u/lemmy_alpha" ], + "audience": "http://ds9.lemmy.ml/u/lemmy_alpha", "tag": [ { "href": "http://ds9.lemmy.ml/u/lemmy_alpha", diff --git a/crates/apub/assets/lemmy/activities/create_or_update/create_page.json b/crates/apub/assets/lemmy/activities/create_or_update/create_page.json index 4fff07c8..907faa5c 100644 --- a/crates/apub/assets/lemmy/activities/create_or_update/create_page.json +++ b/crates/apub/assets/lemmy/activities/create_or_update/create_page.json @@ -11,6 +11,7 @@ "http://enterprise.lemmy.ml/c/main", "https://www.w3.org/ns/activitystreams#Public" ], + "audience": "https://enterprise.lemmy.ml/c/main", "name": "test post", "content": "

test body

\n", "mediaType": "text/html", @@ -37,6 +38,7 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "https://enterprise.lemmy.ml/c/main", "type": "Create", "id": "http://ds9.lemmy.ml/activities/create/eee6a57a-622f-464d-b560-73ae1fcd3ddf" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/create_or_update/update_page.json b/crates/apub/assets/lemmy/activities/create_or_update/update_page.json index 7cde6cdd..46cb0e2a 100644 --- a/crates/apub/assets/lemmy/activities/create_or_update/update_page.json +++ b/crates/apub/assets/lemmy/activities/create_or_update/update_page.json @@ -11,6 +11,7 @@ "http://enterprise.lemmy.ml/c/main", "https://www.w3.org/ns/activitystreams#Public" ], + "audience": "https://enterprise.lemmy.ml/c/main", "name": "test post 1", "content": "

test body

\n", "mediaType": "text/html", @@ -34,6 +35,7 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "https://enterprise.lemmy.ml/c/main", "type": "Update", "id": "http://ds9.lemmy.ml/activities/update/ab360117-e165-4de4-b7fc-906b62c98631" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/deletion/delete_page.json b/crates/apub/assets/lemmy/activities/deletion/delete_page.json index 8dd26a10..590db014 100644 --- a/crates/apub/assets/lemmy/activities/deletion/delete_page.json +++ b/crates/apub/assets/lemmy/activities/deletion/delete_page.json @@ -7,6 +7,7 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "type": "Delete", "id": "http://ds9.lemmy.ml/activities/delete/f2abee48-c7bb-41d5-9e27-8775ff32db12" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/deletion/delete_user.json b/crates/apub/assets/lemmy/activities/deletion/delete_user.json index 1e000c12..da93cdbe 100644 --- a/crates/apub/assets/lemmy/activities/deletion/delete_user.json +++ b/crates/apub/assets/lemmy/activities/deletion/delete_user.json @@ -4,9 +4,6 @@ "https://www.w3.org/ns/activitystreams#Public" ], "object": "http://ds9.lemmy.ml/u/lemmy_alpha", - "cc": [ - "http://enterprise.lemmy.ml/c/main" - ], "type": "Delete", "id": "http://ds9.lemmy.ml/activities/delete/f2abee48-c7bb-41d5-9e27-8775ff32db12" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/deletion/remove_note.json b/crates/apub/assets/lemmy/activities/deletion/remove_note.json index 8ea35404..29a29983 100644 --- a/crates/apub/assets/lemmy/activities/deletion/remove_note.json +++ b/crates/apub/assets/lemmy/activities/deletion/remove_note.json @@ -7,6 +7,7 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "type": "Delete", "summary": "bad comment", "id": "http://enterprise.lemmy.ml/activities/delete/42ca1a79-f99e-4518-a2ca-ba2df221eb5e" diff --git a/crates/apub/assets/lemmy/activities/deletion/undo_delete_page.json b/crates/apub/assets/lemmy/activities/deletion/undo_delete_page.json index 9f824fa1..2e7fbce4 100644 --- a/crates/apub/assets/lemmy/activities/deletion/undo_delete_page.json +++ b/crates/apub/assets/lemmy/activities/deletion/undo_delete_page.json @@ -12,12 +12,14 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "type": "Delete", "id": "http://ds9.lemmy.ml/activities/delete/b13cca96-7737-41e1-9769-8fbf972b3509" }, "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "type": "Undo", "id": "http://ds9.lemmy.ml/activities/undo/5e939cfb-b8a1-4de8-950f-9d684e9162b9" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/deletion/undo_remove_note.json b/crates/apub/assets/lemmy/activities/deletion/undo_remove_note.json index 413cf16b..6cabdaf2 100644 --- a/crates/apub/assets/lemmy/activities/deletion/undo_remove_note.json +++ b/crates/apub/assets/lemmy/activities/deletion/undo_remove_note.json @@ -12,6 +12,7 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "type": "Delete", "summary": "bad comment", "id": "http://enterprise.lemmy.ml/activities/delete/2598435c-87a3-49cd-81f3-a44b03b7af9d" @@ -19,6 +20,7 @@ "cc": [ "http://enterprise.lemmy.ml/c/main" ], + "audience": "http://enterprise.lemmy.ml/u/main", "type": "Undo", "id": "http://enterprise.lemmy.ml/activities/undo/a850cf21-3866-4b3a-b80b-56aa00997fee" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/voting/dislike_page.json b/crates/apub/assets/lemmy/activities/voting/dislike_page.json index 0917329e..3d11a51c 100644 --- a/crates/apub/assets/lemmy/activities/voting/dislike_page.json +++ b/crates/apub/assets/lemmy/activities/voting/dislike_page.json @@ -1,6 +1,7 @@ { "actor": "http://enterprise.lemmy.ml/u/lemmy_beta", "object": "http://ds9.lemmy.ml/post/1", + "audience": "https://enterprise.lemmy.ml/c/tenforward", "type": "Dislike", "id": "http://enterprise.lemmy.ml/activities/dislike/64d40d40-a829-43a5-8247-1fb595b3ca1c" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/voting/like_note.json b/crates/apub/assets/lemmy/activities/voting/like_note.json index 78ee5b12..e72fb5d9 100644 --- a/crates/apub/assets/lemmy/activities/voting/like_note.json +++ b/crates/apub/assets/lemmy/activities/voting/like_note.json @@ -1,6 +1,7 @@ { "actor": "http://ds9.lemmy.ml/u/lemmy_alpha", "object": "http://ds9.lemmy.ml/comment/1", + "audience": "https://enterprise.lemmy.ml/c/tenforward", "type": "Like", "id": "http://ds9.lemmy.ml/activities/like/fd61d070-7382-46a9-b2b7-6bb253732877" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/voting/undo_dislike_page.json b/crates/apub/assets/lemmy/activities/voting/undo_dislike_page.json index 54fc1903..098242db 100644 --- a/crates/apub/assets/lemmy/activities/voting/undo_dislike_page.json +++ b/crates/apub/assets/lemmy/activities/voting/undo_dislike_page.json @@ -3,9 +3,11 @@ "object": { "actor": "http://enterprise.lemmy.ml/u/lemmy_beta", "object": "http://ds9.lemmy.ml/post/1", + "audience": "https://enterprise.lemmy.ml/c/tenforward", "type": "Like", "id": "http://enterprise.lemmy.ml/activities/like/2227ab2c-79e2-4fca-a1d2-1d67dacf2457" }, + "audience": "https://enterprise.lemmy.ml/c/tenforward", "type": "Undo", "id": "http://enterprise.lemmy.ml/activities/undo/6cc6fb71-39fe-49ea-9506-f0423b101e98" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/activities/voting/undo_like_note.json b/crates/apub/assets/lemmy/activities/voting/undo_like_note.json index 65ed510e..b4d5d31a 100644 --- a/crates/apub/assets/lemmy/activities/voting/undo_like_note.json +++ b/crates/apub/assets/lemmy/activities/voting/undo_like_note.json @@ -3,9 +3,11 @@ "object": { "actor": "http://ds9.lemmy.ml/u/lemmy_alpha", "object": "http://ds9.lemmy.ml/comment/1", + "audience": "https://enterprise.lemmy.ml/c/tenforward", "type": "Like", "id": "http://ds9.lemmy.ml/activities/like/efcf7ae2-dfcc-4ff4-9ce4-6adf251ff004" }, + "audience": "https://enterprise.lemmy.ml/c/tenforward", "type": "Undo", "id": "http://ds9.lemmy.ml/activities/undo/3518565c-24a7-4d9e-8e0a-f7a2f45ac618" } \ No newline at end of file diff --git a/crates/apub/assets/lemmy/objects/note.json b/crates/apub/assets/lemmy/objects/note.json index 4fcb906a..2e50abcd 100644 --- a/crates/apub/assets/lemmy/objects/note.json +++ b/crates/apub/assets/lemmy/objects/note.json @@ -7,6 +7,7 @@ "https://enterprise.lemmy.ml/c/tenforward", "https://enterprise.lemmy.ml/u/picard" ], + "audience": "https://enterprise.lemmy.ml/c/tenforward", "inReplyTo": "https://enterprise.lemmy.ml/post/55143", "content": "

first comment!

\n", "mediaType": "text/html", diff --git a/crates/apub/assets/lemmy/objects/page.json b/crates/apub/assets/lemmy/objects/page.json index 816c3249..0f514bc0 100644 --- a/crates/apub/assets/lemmy/objects/page.json +++ b/crates/apub/assets/lemmy/objects/page.json @@ -6,6 +6,7 @@ "https://enterprise.lemmy.ml/c/tenforward", "https://www.w3.org/ns/activitystreams#Public" ], + "audience": "https://enterprise.lemmy.ml/c/tenforward", "name": "Post title", "content": "

This is a post in the /c/tenforward community

\n", "mediaType": "text/html", diff --git a/crates/apub/src/activities/block/block_user.rs b/crates/apub/src/activities/block/block_user.rs index a701f8d9..1d726e7c 100644 --- a/crates/apub/src/activities/block/block_user.rs +++ b/crates/apub/src/activities/block/block_user.rs @@ -1,7 +1,7 @@ use crate::{ activities::{ block::{generate_cc, SiteOrCommunity}, - community::{announce::GetCommunity, send_activity_in_community}, + community::send_activity_in_community, generate_activity_id, send_lemmy_activity, verify_is_public, @@ -10,7 +10,7 @@ use crate::{ }, activity_lists::AnnouncableActivities, local_instance, - objects::{community::ApubCommunity, instance::remote_instance_inboxes, person::ApubPerson}, + objects::{instance::remote_instance_inboxes, person::ApubPerson}, protocol::activities::block::block_user::BlockUser, ActorType, }; @@ -51,6 +51,11 @@ impl BlockUser { expires: Option, context: &LemmyContext, ) -> Result { + let audience = if let SiteOrCommunity::Community(c) = target { + Some(ObjectId::new(c.actor_id())) + } else { + None + }; Ok(BlockUser { actor: ObjectId::new(mod_.actor_id()), to: vec![public()], @@ -64,6 +69,7 @@ impl BlockUser { BlockType::Block, &context.settings().get_protocol_and_hostname(), )?, + audience, expires: expires.map(convert_datetime), }) } @@ -242,22 +248,3 @@ impl ActivityHandler for BlockUser { Ok(()) } } - -#[async_trait::async_trait(?Send)] -impl GetCommunity for BlockUser { - #[tracing::instrument(skip_all)] - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { - let target = self - .target - .dereference(context, local_instance(context).await, request_counter) - .await?; - match target { - SiteOrCommunity::Community(c) => Ok(c), - SiteOrCommunity::Site(_) => Err(anyhow!("Calling get_community() on site activity").into()), - } - } -} diff --git a/crates/apub/src/activities/block/undo_block_user.rs b/crates/apub/src/activities/block/undo_block_user.rs index ff76d914..eb54f5e4 100644 --- a/crates/apub/src/activities/block/undo_block_user.rs +++ b/crates/apub/src/activities/block/undo_block_user.rs @@ -1,14 +1,14 @@ use crate::{ activities::{ block::{generate_cc, SiteOrCommunity}, - community::{announce::GetCommunity, send_activity_in_community}, + community::send_activity_in_community, generate_activity_id, send_lemmy_activity, verify_is_public, }, activity_lists::AnnouncableActivities, local_instance, - objects::{community::ApubCommunity, instance::remote_instance_inboxes, person::ApubPerson}, + objects::{instance::remote_instance_inboxes, person::ApubPerson}, protocol::activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser}, ActorType, }; @@ -41,6 +41,11 @@ impl UndoBlockUser { context: &LemmyContext, ) -> Result<(), LemmyError> { let block = BlockUser::new(target, user, mod_, None, reason, None, context).await?; + let audience = if let SiteOrCommunity::Community(c) = target { + Some(ObjectId::new(c.actor_id())) + } else { + None + }; let id = generate_activity_id( UndoType::Undo, @@ -53,6 +58,7 @@ impl UndoBlockUser { cc: generate_cc(target, context.pool()).await?, kind: UndoType::Undo, id: id.clone(), + audience, }; let mut inboxes = vec![user.shared_inbox_or_inbox()]; @@ -162,15 +168,3 @@ impl ActivityHandler for UndoBlockUser { Ok(()) } } - -#[async_trait::async_trait(?Send)] -impl GetCommunity for UndoBlockUser { - #[tracing::instrument(skip_all)] - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { - self.object.get_community(context, request_counter).await - } -} diff --git a/crates/apub/src/activities/community/add_mod.rs b/crates/apub/src/activities/community/add_mod.rs index e863cf0d..c212cfe1 100644 --- a/crates/apub/src/activities/community/add_mod.rs +++ b/crates/apub/src/activities/community/add_mod.rs @@ -1,10 +1,6 @@ use crate::{ activities::{ - community::{ - announce::GetCommunity, - get_community_from_moderators_url, - send_activity_in_community, - }, + community::send_activity_in_community, generate_activity_id, verify_add_remove_moderator_target, verify_is_public, @@ -15,7 +11,7 @@ use crate::{ generate_moderators_url, local_instance, objects::{community::ApubCommunity, person::ApubPerson}, - protocol::activities::community::add_mod::AddMod, + protocol::{activities::community::add_mod::AddMod, InCommunity}, ActorType, }; use activitypub_federation::{ @@ -55,6 +51,7 @@ impl AddMod { cc: vec![community.actor_id()], kind: AddType::Add, id: id.clone(), + audience: Some(ObjectId::new(community.actor_id())), }; let activity = AnnouncableActivities::AddMod(add); @@ -83,7 +80,7 @@ impl ActivityHandler for AddMod { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to, &self.cc)?; - let community = self.get_community(context, request_counter).await?; + let community = self.community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_mod_action( &self.actor, @@ -103,7 +100,7 @@ impl ActivityHandler for AddMod { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let community = self.get_community(context, request_counter).await?; + let community = self.community(context, request_counter).await?; let new_mod = self .object .dereference(context, local_instance(context).await, request_counter) @@ -138,15 +135,3 @@ impl ActivityHandler for AddMod { Ok(()) } } - -#[async_trait::async_trait(?Send)] -impl GetCommunity for AddMod { - #[tracing::instrument(skip_all)] - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { - get_community_from_moderators_url(&self.target, context, request_counter).await - } -} diff --git a/crates/apub/src/activities/community/announce.rs b/crates/apub/src/activities/community/announce.rs index 9c1b752a..b6c31af5 100644 --- a/crates/apub/src/activities/community/announce.rs +++ b/crates/apub/src/activities/community/announce.rs @@ -12,6 +12,7 @@ use crate::{ activities::community::announce::{AnnounceActivity, RawAnnouncableActivities}, Id, IdOrNestedObject, + InCommunity, }, ActorType, }; @@ -56,7 +57,7 @@ impl ActivityHandler for RawAnnouncableActivities { if let AnnouncableActivities::Page(_) = activity { return Err(LemmyError::from_message("Cant receive page")); } - let community = activity.get_community(data, &mut 0).await?; + let community = activity.community(data, &mut 0).await?; let actor_id = ObjectId::new(activity.actor().clone()); // verify and receive activity @@ -72,15 +73,6 @@ impl ActivityHandler for RawAnnouncableActivities { } } -#[async_trait::async_trait(?Send)] -pub(crate) trait GetCommunity { - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result; -} - impl AnnounceActivity { pub(crate) fn new( object: RawAnnouncableActivities, diff --git a/crates/apub/src/activities/community/mod.rs b/crates/apub/src/activities/community/mod.rs index d05a3d66..a7b35595 100644 --- a/crates/apub/src/activities/community/mod.rs +++ b/crates/apub/src/activities/community/mod.rs @@ -64,7 +64,7 @@ pub(crate) async fn send_activity_in_community( } #[tracing::instrument(skip_all)] -async fn get_community_from_moderators_url( +pub(crate) async fn get_community_from_moderators_url( moderators: &Url, context: &LemmyContext, request_counter: &mut i32, diff --git a/crates/apub/src/activities/community/remove_mod.rs b/crates/apub/src/activities/community/remove_mod.rs index 6740d3f1..3934df3b 100644 --- a/crates/apub/src/activities/community/remove_mod.rs +++ b/crates/apub/src/activities/community/remove_mod.rs @@ -1,10 +1,6 @@ use crate::{ activities::{ - community::{ - announce::GetCommunity, - get_community_from_moderators_url, - send_activity_in_community, - }, + community::send_activity_in_community, generate_activity_id, verify_add_remove_moderator_target, verify_is_public, @@ -15,7 +11,7 @@ use crate::{ generate_moderators_url, local_instance, objects::{community::ApubCommunity, person::ApubPerson}, - protocol::activities::community::remove_mod::RemoveMod, + protocol::{activities::community::remove_mod::RemoveMod, InCommunity}, ActorType, }; use activitypub_federation::{ @@ -55,6 +51,7 @@ impl RemoveMod { id: id.clone(), cc: vec![community.actor_id()], kind: RemoveType::Remove, + audience: Some(ObjectId::new(community.actor_id())), }; let activity = AnnouncableActivities::RemoveMod(remove); @@ -83,7 +80,7 @@ impl ActivityHandler for RemoveMod { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to, &self.cc)?; - let community = self.get_community(context, request_counter).await?; + let community = self.community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_mod_action( &self.actor, @@ -103,7 +100,7 @@ impl ActivityHandler for RemoveMod { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let community = self.get_community(context, request_counter).await?; + let community = self.community(context, request_counter).await?; let remove_mod = self .object .dereference(context, local_instance(context).await, request_counter) @@ -132,15 +129,3 @@ impl ActivityHandler for RemoveMod { Ok(()) } } - -#[async_trait::async_trait(?Send)] -impl GetCommunity for RemoveMod { - #[tracing::instrument(skip_all)] - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { - get_community_from_moderators_url(&self.target, context, request_counter).await - } -} diff --git a/crates/apub/src/activities/community/report.rs b/crates/apub/src/activities/community/report.rs index 867307f5..440a8ebb 100644 --- a/crates/apub/src/activities/community/report.rs +++ b/crates/apub/src/activities/community/report.rs @@ -2,7 +2,7 @@ use crate::{ activities::{generate_activity_id, send_lemmy_activity, verify_person_in_community}, local_instance, objects::{community::ApubCommunity, person::ApubPerson}, - protocol::activities::community::report::Report, + protocol::{activities::community::report::Report, InCommunity}, ActorType, PostOrComment, }; @@ -47,6 +47,7 @@ impl Report { summary: reason, kind, id: id.clone(), + audience: Some(ObjectId::new(community.actor_id())), }; let inbox = vec![community.shared_inbox_or_inbox()]; @@ -73,9 +74,7 @@ impl ActivityHandler for Report { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let community = self.to[0] - .dereference(context, local_instance(context).await, request_counter) - .await?; + let community = self.community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; Ok(()) } diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index a4beccc0..f41f2d47 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -1,15 +1,14 @@ use crate::{ activities::{ - community::{announce::GetCommunity, send_activity_in_community}, + community::send_activity_in_community, generate_activity_id, verify_is_public, verify_mod_action, verify_person_in_community, }, activity_lists::AnnouncableActivities, - local_instance, objects::{community::ApubCommunity, person::ApubPerson}, - protocol::activities::community::update::UpdateCommunity, + protocol::{activities::community::update::UpdateCommunity, InCommunity}, ActorType, }; use activitypub_federation::{ @@ -41,6 +40,7 @@ impl UpdateCommunity { cc: vec![community.actor_id()], kind: UpdateType::Update, id: id.clone(), + audience: Some(ObjectId::new(community.actor_id())), }; let activity = AnnouncableActivities::UpdateCommunity(update); @@ -68,7 +68,7 @@ impl ActivityHandler for UpdateCommunity { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to, &self.cc)?; - let community = self.get_community(context, request_counter).await?; + let community = self.community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_mod_action( &self.actor, @@ -94,7 +94,7 @@ impl ActivityHandler for UpdateCommunity { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let community = self.get_community(context, request_counter).await?; + let community = self.community(context, request_counter).await?; let community_update_form = self.object.into_update_form(); @@ -112,18 +112,3 @@ impl ActivityHandler for UpdateCommunity { Ok(()) } } - -#[async_trait::async_trait(?Send)] -impl GetCommunity for UpdateCommunity { - #[tracing::instrument(skip_all)] - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { - let cid = ObjectId::new(self.object.id.clone()); - cid - .dereference(context, local_instance(context).await, request_counter) - .await - } -} diff --git a/crates/apub/src/activities/create_or_update/comment.rs b/crates/apub/src/activities/create_or_update/comment.rs index 59e9d4b4..a4b60ad4 100644 --- a/crates/apub/src/activities/create_or_update/comment.rs +++ b/crates/apub/src/activities/create_or_update/comment.rs @@ -1,7 +1,7 @@ use crate::{ activities::{ check_community_deleted_or_removed, - community::{announce::GetCommunity, send_activity_in_community}, + community::send_activity_in_community, create_or_update::get_comment_notif_recipients, generate_activity_id, verify_is_public, @@ -11,7 +11,10 @@ use crate::{ local_instance, mentions::MentionOrValue, objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson}, - protocol::activities::{create_or_update::comment::CreateOrUpdateComment, CreateOrUpdateType}, + protocol::{ + activities::{create_or_update::note::CreateOrUpdateNote, CreateOrUpdateType}, + InCommunity, + }, ActorType, }; use activitypub_federation::{ @@ -34,7 +37,7 @@ use lemmy_utils::error::LemmyError; use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud}; use url::Url; -impl CreateOrUpdateComment { +impl CreateOrUpdateNote { #[tracing::instrument(skip(comment, actor, kind, context))] pub async fn send( comment: ApubComment, @@ -55,7 +58,7 @@ impl CreateOrUpdateComment { )?; let note = comment.into_apub(context).await?; - let create_or_update = CreateOrUpdateComment { + let create_or_update = CreateOrUpdateNote { actor: ObjectId::new(actor.actor_id()), to: vec![public()], cc: note.cc.clone(), @@ -63,6 +66,7 @@ impl CreateOrUpdateComment { object: note, kind, id: id.clone(), + audience: Some(ObjectId::new(community.actor_id())), }; let tagged_users: Vec> = create_or_update @@ -92,7 +96,7 @@ impl CreateOrUpdateComment { } #[async_trait::async_trait(?Send)] -impl ActivityHandler for CreateOrUpdateComment { +impl ActivityHandler for CreateOrUpdateNote { type DataType = LemmyContext; type Error = LemmyError; @@ -112,7 +116,7 @@ impl ActivityHandler for CreateOrUpdateComment { ) -> Result<(), LemmyError> { verify_is_public(&self.to, &self.cc)?; let post = self.object.get_parents(context, request_counter).await?.0; - let community = self.get_community(context, request_counter).await?; + let community = self.community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_domains_match(self.actor.inner(), self.object.id.inner())?; @@ -160,17 +164,3 @@ impl ActivityHandler for CreateOrUpdateComment { Ok(()) } } - -#[async_trait::async_trait(?Send)] -impl GetCommunity for CreateOrUpdateComment { - #[tracing::instrument(skip_all)] - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { - let post = self.object.get_parents(context, request_counter).await?.0; - let community = Community::read(context.pool(), post.community_id).await?; - Ok(community.into()) - } -} diff --git a/crates/apub/src/activities/create_or_update/post.rs b/crates/apub/src/activities/create_or_update/post.rs index bff289d9..abe9be1a 100644 --- a/crates/apub/src/activities/create_or_update/post.rs +++ b/crates/apub/src/activities/create_or_update/post.rs @@ -1,7 +1,7 @@ use crate::{ activities::{ check_community_deleted_or_removed, - community::{announce::GetCommunity, send_activity_in_community}, + community::send_activity_in_community, generate_activity_id, verify_is_public, verify_mod_action, @@ -9,7 +9,10 @@ use crate::{ }, activity_lists::AnnouncableActivities, objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost}, - protocol::activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType}, + protocol::{ + activities::{create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType}, + InCommunity, + }, ActorType, }; use activitypub_federation::{ @@ -30,25 +33,26 @@ use lemmy_utils::error::LemmyError; use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud}; use url::Url; -impl CreateOrUpdatePost { +impl CreateOrUpdatePage { pub(crate) async fn new( post: ApubPost, actor: &ApubPerson, community: &ApubCommunity, kind: CreateOrUpdateType, context: &LemmyContext, - ) -> Result { + ) -> Result { let id = generate_activity_id( kind.clone(), &context.settings().get_protocol_and_hostname(), )?; - Ok(CreateOrUpdatePost { + Ok(CreateOrUpdatePage { actor: ObjectId::new(actor.actor_id()), to: vec![public()], object: post.into_apub(context).await?, cc: vec![community.actor_id()], kind, id: id.clone(), + audience: Some(ObjectId::new(community.actor_id())), }) } @@ -62,7 +66,7 @@ impl CreateOrUpdatePost { let community_id = post.community_id; let community: ApubCommunity = Community::read(context.pool(), community_id).await?.into(); - let create_or_update = CreateOrUpdatePost::new(post, actor, &community, kind, context).await?; + let create_or_update = CreateOrUpdatePage::new(post, actor, &community, kind, context).await?; let is_mod_action = create_or_update.object.is_mod_action(context).await?; let activity = AnnouncableActivities::CreateOrUpdatePost(create_or_update); send_activity_in_community(activity, actor, &community, vec![], is_mod_action, context).await?; @@ -71,7 +75,7 @@ impl CreateOrUpdatePost { } #[async_trait::async_trait(?Send)] -impl ActivityHandler for CreateOrUpdatePost { +impl ActivityHandler for CreateOrUpdatePage { type DataType = LemmyContext; type Error = LemmyError; @@ -90,7 +94,7 @@ impl ActivityHandler for CreateOrUpdatePost { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to, &self.cc)?; - let community = self.get_community(context, request_counter).await?; + let community = self.community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; check_community_deleted_or_removed(&community)?; @@ -155,18 +159,3 @@ impl ActivityHandler for CreateOrUpdatePost { Ok(()) } } - -#[async_trait::async_trait(?Send)] -impl GetCommunity for CreateOrUpdatePost { - #[tracing::instrument(skip_all)] - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { - self - .object - .extract_community(context, request_counter) - .await - } -} diff --git a/crates/apub/src/activities/create_or_update/private_message.rs b/crates/apub/src/activities/create_or_update/private_message.rs index e0766196..eb310ce9 100644 --- a/crates/apub/src/activities/create_or_update/private_message.rs +++ b/crates/apub/src/activities/create_or_update/private_message.rs @@ -2,7 +2,7 @@ use crate::{ activities::{generate_activity_id, send_lemmy_activity, verify_person}, objects::{person::ApubPerson, private_message::ApubPrivateMessage}, protocol::activities::{ - create_or_update::private_message::CreateOrUpdatePrivateMessage, + create_or_update::chat_message::CreateOrUpdateChatMessage, CreateOrUpdateType, }, ActorType, @@ -18,7 +18,7 @@ use lemmy_utils::error::LemmyError; use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud}; use url::Url; -impl CreateOrUpdatePrivateMessage { +impl CreateOrUpdateChatMessage { #[tracing::instrument(skip_all)] pub async fn send( private_message: ApubPrivateMessage, @@ -33,7 +33,7 @@ impl CreateOrUpdatePrivateMessage { kind.clone(), &context.settings().get_protocol_and_hostname(), )?; - let create_or_update = CreateOrUpdatePrivateMessage { + let create_or_update = CreateOrUpdateChatMessage { id: id.clone(), actor: ObjectId::new(actor.actor_id()), to: [ObjectId::new(recipient.actor_id())], @@ -46,7 +46,7 @@ impl CreateOrUpdatePrivateMessage { } #[async_trait::async_trait(?Send)] -impl ActivityHandler for CreateOrUpdatePrivateMessage { +impl ActivityHandler for CreateOrUpdateChatMessage { type DataType = LemmyContext; type Error = LemmyError; diff --git a/crates/apub/src/activities/deletion/delete.rs b/crates/apub/src/activities/deletion/delete.rs index 8d296332..8298a6fe 100644 --- a/crates/apub/src/activities/deletion/delete.rs +++ b/crates/apub/src/activities/deletion/delete.rs @@ -1,6 +1,5 @@ use crate::{ activities::{ - community::announce::GetCommunity, deletion::{receive_delete_action, verify_delete_activity, DeletableObjects}, generate_activity_id, }, @@ -10,7 +9,6 @@ use crate::{ }; use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler}; use activitystreams_kinds::activity::DeleteType; -use anyhow::anyhow; use lemmy_db_schema::{ source::{ comment::{Comment, CommentUpdateForm}, @@ -117,6 +115,7 @@ impl Delete { kind: DeleteType::Delete, summary, id, + audience: community.map(|c| ObjectId::::new(c.actor_id.clone())), }) } } @@ -191,27 +190,3 @@ pub(in crate::activities) async fn receive_remove_action( } Ok(()) } - -#[async_trait::async_trait(?Send)] -impl GetCommunity for Delete { - #[tracing::instrument(skip_all)] - async fn get_community( - &self, - context: &LemmyContext, - _request_counter: &mut i32, - ) -> Result { - let community_id = match DeletableObjects::read_from_db(self.object.id(), context).await? { - DeletableObjects::Community(c) => c.id, - DeletableObjects::Comment(c) => { - let post = Post::read(context.pool(), c.post_id).await?; - post.community_id - } - DeletableObjects::Post(p) => p.community_id, - DeletableObjects::PrivateMessage(_) => { - return Err(anyhow!("Private message is not part of community").into()) - } - }; - let community = Community::read(context.pool(), community_id).await?; - Ok(community.into()) - } -} diff --git a/crates/apub/src/activities/deletion/mod.rs b/crates/apub/src/activities/deletion/mod.rs index 5307e368..bf4b920a 100644 --- a/crates/apub/src/activities/deletion/mod.rs +++ b/crates/apub/src/activities/deletion/mod.rs @@ -1,6 +1,6 @@ use crate::{ activities::{ - community::{announce::GetCommunity, send_activity_in_community}, + community::send_activity_in_community, send_lemmy_activity, verify_is_public, verify_mod_action, @@ -16,7 +16,10 @@ use crate::{ post::ApubPost, private_message::ApubPrivateMessage, }, - protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete}, + protocol::{ + activities::deletion::{delete::Delete, undo_delete::UndoDelete}, + InCommunity, + }, ActorType, }; use activitypub_federation::{ @@ -175,7 +178,7 @@ pub(in crate::activities) async fn verify_delete_activity( verify_delete_post_or_comment( &activity.actor, &p.ap_id.clone().into(), - &activity.get_community(context, request_counter).await?, + &activity.community(context, request_counter).await?, is_mod_action, context, request_counter, @@ -187,7 +190,7 @@ pub(in crate::activities) async fn verify_delete_activity( verify_delete_post_or_comment( &activity.actor, &c.ap_id.clone().into(), - &activity.get_community(context, request_counter).await?, + &activity.community(context, request_counter).await?, is_mod_action, context, request_counter, diff --git a/crates/apub/src/activities/deletion/undo_delete.rs b/crates/apub/src/activities/deletion/undo_delete.rs index c3533ad5..8b845400 100644 --- a/crates/apub/src/activities/deletion/undo_delete.rs +++ b/crates/apub/src/activities/deletion/undo_delete.rs @@ -1,6 +1,5 @@ use crate::{ activities::{ - community::announce::GetCommunity, deletion::{receive_delete_action, verify_delete_activity, DeletableObjects}, generate_activity_id, }, @@ -117,6 +116,7 @@ impl UndoDelete { cc: cc.into_iter().collect(), kind: UndoType::Undo, id, + audience: community.map(|c| ObjectId::::new(c.actor_id.clone())), }) } @@ -187,15 +187,3 @@ impl UndoDelete { Ok(()) } } - -#[async_trait::async_trait(?Send)] -impl GetCommunity for UndoDelete { - #[tracing::instrument(skip_all)] - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { - self.object.get_community(context, request_counter).await - } -} diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 3cf9771e..c38eadcd 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -130,6 +130,16 @@ pub(crate) fn verify_is_public(to: &[Url], cc: &[Url]) -> Result<(), LemmyError> Ok(()) } +pub(crate) fn verify_community_matches( + a: &ApubCommunity, + b: CommunityId, +) -> Result<(), LemmyError> { + if a.id != b { + return Err(LemmyError::from_message("Invalid community")); + } + Ok(()) +} + pub(crate) fn check_community_deleted_or_removed(community: &Community) -> Result<(), LemmyError> { if community.deleted || community.removed { Err(LemmyError::from_message( diff --git a/crates/apub/src/activities/voting/undo_vote.rs b/crates/apub/src/activities/voting/undo_vote.rs index 2c1a1b2d..20c9432c 100644 --- a/crates/apub/src/activities/voting/undo_vote.rs +++ b/crates/apub/src/activities/voting/undo_vote.rs @@ -1,6 +1,6 @@ use crate::{ activities::{ - community::{announce::GetCommunity, send_activity_in_community}, + community::send_activity_in_community, generate_activity_id, verify_person_in_community, voting::{undo_vote_comment, undo_vote_post}, @@ -8,9 +8,12 @@ use crate::{ activity_lists::AnnouncableActivities, local_instance, objects::{community::ApubCommunity, person::ApubPerson}, - protocol::activities::voting::{ - undo_vote::UndoVote, - vote::{Vote, VoteType}, + protocol::{ + activities::voting::{ + undo_vote::UndoVote, + vote::{Vote, VoteType}, + }, + InCommunity, }, ActorType, PostOrComment, @@ -41,7 +44,7 @@ impl UndoVote { ) -> Result<(), LemmyError> { let community: ApubCommunity = Community::read(context.pool(), community_id).await?.into(); - let object = Vote::new(object, actor, kind.clone(), context)?; + let object = Vote::new(object, actor, &community, kind.clone(), context)?; let id = generate_activity_id( UndoType::Undo, &context.settings().get_protocol_and_hostname(), @@ -51,6 +54,7 @@ impl UndoVote { object, kind: UndoType::Undo, id: id.clone(), + audience: Some(ObjectId::new(community.actor_id())), }; let activity = AnnouncableActivities::UndoVote(undo_vote); send_activity_in_community(activity, actor, &community, vec![], false, context).await @@ -76,7 +80,7 @@ impl ActivityHandler for UndoVote { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let community = self.get_community(context, request_counter).await?; + let community = self.community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_urls_match(self.actor.inner(), self.object.actor.inner())?; self.object.verify(context, request_counter).await?; @@ -104,15 +108,3 @@ impl ActivityHandler for UndoVote { } } } - -#[async_trait::async_trait(?Send)] -impl GetCommunity for UndoVote { - #[tracing::instrument(skip_all)] - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { - self.object.get_community(context, request_counter).await - } -} diff --git a/crates/apub/src/activities/voting/vote.rs b/crates/apub/src/activities/voting/vote.rs index 2b60206a..f8d44ed9 100644 --- a/crates/apub/src/activities/voting/vote.rs +++ b/crates/apub/src/activities/voting/vote.rs @@ -1,6 +1,6 @@ use crate::{ activities::{ - community::{announce::GetCommunity, send_activity_in_community}, + community::send_activity_in_community, generate_activity_id, verify_person_in_community, voting::{vote_comment, vote_post}, @@ -8,7 +8,10 @@ use crate::{ activity_lists::AnnouncableActivities, local_instance, objects::{community::ApubCommunity, person::ApubPerson}, - protocol::activities::voting::vote::{Vote, VoteType}, + protocol::{ + activities::voting::vote::{Vote, VoteType}, + InCommunity, + }, ActorType, PostOrComment, }; @@ -16,7 +19,7 @@ use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::Acti use anyhow::anyhow; use lemmy_db_schema::{ newtypes::CommunityId, - source::{community::Community, local_site::LocalSite, post::Post}, + source::{community::Community, local_site::LocalSite}, traits::Crud, }; use lemmy_utils::error::LemmyError; @@ -29,6 +32,7 @@ impl Vote { pub(in crate::activities::voting) fn new( object: &PostOrComment, actor: &ApubPerson, + community: &ApubCommunity, kind: VoteType, context: &LemmyContext, ) -> Result { @@ -37,6 +41,7 @@ impl Vote { object: ObjectId::new(object.ap_id()), kind: kind.clone(), id: generate_activity_id(kind, &context.settings().get_protocol_and_hostname())?, + audience: Some(ObjectId::new(community.actor_id())), }) } @@ -49,7 +54,7 @@ impl Vote { context: &LemmyContext, ) -> Result<(), LemmyError> { let community = Community::read(context.pool(), community_id).await?.into(); - let vote = Vote::new(object, actor, kind, context)?; + let vote = Vote::new(object, actor, &community, kind, context)?; let activity = AnnouncableActivities::Vote(vote); send_activity_in_community(activity, actor, &community, vec![], false, context).await @@ -75,7 +80,7 @@ impl ActivityHandler for Vote { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let community = self.get_community(context, request_counter).await?; + let community = self.community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; let enable_downvotes = LocalSite::read(context.pool()) .await @@ -107,24 +112,3 @@ impl ActivityHandler for Vote { } } } - -#[async_trait::async_trait(?Send)] -impl GetCommunity for Vote { - #[tracing::instrument(skip_all)] - async fn get_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { - let object = self - .object - .dereference(context, local_instance(context).await, request_counter) - .await?; - let cid = match object { - PostOrComment::Post(p) => p.community_id, - PostOrComment::Comment(c) => Post::read(context.pool(), c.post_id).await?.community_id, - }; - let community = Community::read(context.pool(), cid).await?; - Ok(community.into()) - } -} diff --git a/crates/apub/src/activity_lists.rs b/crates/apub/src/activity_lists.rs index 242f26a1..fa8eece3 100644 --- a/crates/apub/src/activity_lists.rs +++ b/crates/apub/src/activity_lists.rs @@ -1,5 +1,4 @@ use crate::{ - activities::community::announce::GetCommunity, objects::community::ApubCommunity, protocol::{ activities::{ @@ -12,15 +11,16 @@ use crate::{ update::UpdateCommunity, }, create_or_update::{ - comment::CreateOrUpdateComment, - post::CreateOrUpdatePost, - private_message::CreateOrUpdatePrivateMessage, + chat_message::CreateOrUpdateChatMessage, + note::CreateOrUpdateNote, + page::CreateOrUpdatePage, }, deletion::{delete::Delete, delete_user::DeleteUser, undo_delete::UndoDelete}, following::{accept::AcceptFollow, follow::Follow, undo_follow::UndoFollow}, voting::{undo_vote::UndoVote, vote::Vote}, }, objects::page::Page, + InCommunity, }, }; use activitypub_federation::{data::Data, deser::context::WithContext, traits::ActivityHandler}; @@ -54,8 +54,7 @@ pub enum GroupInboxActivities { pub enum PersonInboxActivities { AcceptFollow(AcceptFollow), UndoFollow(UndoFollow), - FollowCommunity(Follow), - CreateOrUpdatePrivateMessage(CreateOrUpdatePrivateMessage), + CreateOrUpdatePrivateMessage(CreateOrUpdateChatMessage), Delete(Delete), UndoDelete(UndoDelete), AnnounceActivity(AnnounceActivity), @@ -76,8 +75,8 @@ pub enum PersonInboxActivitiesWithAnnouncable { #[serde(untagged)] #[enum_delegate::implement(ActivityHandler)] pub enum AnnouncableActivities { - CreateOrUpdateComment(CreateOrUpdateComment), - CreateOrUpdatePost(CreateOrUpdatePost), + CreateOrUpdateComment(CreateOrUpdateNote), + CreateOrUpdatePost(CreateOrUpdatePage), Vote(Vote), UndoVote(UndoVote), Delete(Delete), @@ -102,29 +101,28 @@ pub enum SiteInboxActivities { } #[async_trait::async_trait(?Send)] -impl GetCommunity for AnnouncableActivities { +impl InCommunity for AnnouncableActivities { #[tracing::instrument(skip(self, context))] - async fn get_community( + async fn community( &self, context: &LemmyContext, request_counter: &mut i32, ) -> Result { use AnnouncableActivities::*; - let community = match self { - CreateOrUpdateComment(a) => a.get_community(context, request_counter).await?, - CreateOrUpdatePost(a) => a.get_community(context, request_counter).await?, - Vote(a) => a.get_community(context, request_counter).await?, - UndoVote(a) => a.get_community(context, request_counter).await?, - Delete(a) => a.get_community(context, request_counter).await?, - UndoDelete(a) => a.get_community(context, request_counter).await?, - UpdateCommunity(a) => a.get_community(context, request_counter).await?, - BlockUser(a) => a.get_community(context, request_counter).await?, - UndoBlockUser(a) => a.get_community(context, request_counter).await?, - AddMod(a) => a.get_community(context, request_counter).await?, - RemoveMod(a) => a.get_community(context, request_counter).await?, + match self { + CreateOrUpdateComment(a) => a.community(context, request_counter).await, + CreateOrUpdatePost(a) => a.community(context, request_counter).await, + Vote(a) => a.community(context, request_counter).await, + UndoVote(a) => a.community(context, request_counter).await, + Delete(a) => a.community(context, request_counter).await, + UndoDelete(a) => a.community(context, request_counter).await, + UpdateCommunity(a) => a.community(context, request_counter).await, + BlockUser(a) => a.community(context, request_counter).await, + UndoBlockUser(a) => a.community(context, request_counter).await, + AddMod(a) => a.community(context, request_counter).await, + RemoveMod(a) => a.community(context, request_counter).await, Page(_) => unimplemented!(), - }; - Ok(community) + } } } diff --git a/crates/apub/src/collections/community_outbox.rs b/crates/apub/src/collections/community_outbox.rs index bc0a224c..c7742de7 100644 --- a/crates/apub/src/collections/community_outbox.rs +++ b/crates/apub/src/collections/community_outbox.rs @@ -6,7 +6,7 @@ use crate::{ protocol::{ activities::{ community::announce::AnnounceActivity, - create_or_update::post::CreateOrUpdatePost, + create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType, }, collections::group_outbox::GroupOutbox, @@ -70,7 +70,7 @@ impl ApubObject for ApubCommunityOutbox { for post in self.0 { let person = Person::read(data.1.pool(), post.creator_id).await?.into(); let create = - CreateOrUpdatePost::new(post, &person, &data.0, CreateOrUpdateType::Create, &data.1) + CreateOrUpdatePage::new(post, &person, &data.0, CreateOrUpdateType::Create, &data.1) .await?; let announcable = AnnouncableActivities::CreateOrUpdatePost(create); let announce = AnnounceActivity::new(announcable.try_into()?, &data.0, &data.1)?; diff --git a/crates/apub/src/fetcher/post_or_comment.rs b/crates/apub/src/fetcher/post_or_comment.rs index dc425e21..d2d0b91f 100644 --- a/crates/apub/src/fetcher/post_or_comment.rs +++ b/crates/apub/src/fetcher/post_or_comment.rs @@ -1,9 +1,16 @@ use crate::{ - objects::{comment::ApubComment, post::ApubPost}, - protocol::objects::{note::Note, page::Page}, + objects::{comment::ApubComment, community::ApubCommunity, post::ApubPost}, + protocol::{ + objects::{note::Note, page::Page}, + InCommunity, + }, }; use activitypub_federation::traits::ApubObject; use chrono::NaiveDateTime; +use lemmy_db_schema::{ + source::{community::Community, post::Post}, + traits::Crud, +}; use lemmy_utils::error::LemmyError; use lemmy_websocket::LemmyContext; use serde::Deserialize; @@ -99,3 +106,18 @@ impl PostOrComment { .into() } } + +#[async_trait::async_trait(?Send)] +impl InCommunity for PostOrComment { + async fn community( + &self, + context: &LemmyContext, + _: &mut i32, + ) -> Result { + let cid = match self { + PostOrComment::Post(p) => p.community_id, + PostOrComment::Comment(c) => Post::read(context.pool(), c.post_id).await?.community_id, + }; + Ok(Community::read(context.pool(), cid).await?.into()) + } +} diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs index ba3e518b..df20700f 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -7,6 +7,7 @@ use crate::{ objects::{read_from_string_or_source, verify_is_remote_object}, protocol::{ objects::{note::Note, LanguageTag}, + InCommunity, Source, }, PostOrComment, @@ -103,8 +104,13 @@ impl ApubObject for ApubComment { ObjectId::::new(post.ap_id) }; let language = LanguageTag::new_single(self.language_id, context.pool()).await?; - let maa = - collect_non_local_mentions(&self, ObjectId::new(community.actor_id), context, &mut 0).await?; + let maa = collect_non_local_mentions( + &self, + ObjectId::new(community.actor_id.clone()), + context, + &mut 0, + ) + .await?; let note = Note { r#type: NoteType::Note, @@ -121,6 +127,7 @@ impl ApubObject for ApubComment { tag: maa.tags, distinguished: Some(self.distinguished), language, + audience: Some(ObjectId::new(community.actor_id)), }; Ok(note) @@ -136,9 +143,7 @@ impl ApubObject for ApubComment { verify_domains_match(note.id.inner(), expected_domain)?; verify_domains_match(note.attributed_to.inner(), note.id.inner())?; verify_is_public(¬e.to, ¬e.cc)?; - let (post, _) = note.get_parents(context, request_counter).await?; - let community_id = post.community_id; - let community = Community::read(context.pool(), community_id).await?; + let community = note.community(context, request_counter).await?; let local_site_data = fetch_local_site_data(context.pool()).await?; check_apub_id_valid_with_strictness( @@ -148,13 +153,8 @@ impl ApubObject for ApubComment { context.settings(), )?; verify_is_remote_object(note.id.inner(), context.settings())?; - verify_person_in_community( - ¬e.attributed_to, - &community.into(), - context, - request_counter, - ) - .await?; + verify_person_in_community(¬e.attributed_to, &community, context, request_counter).await?; + let (post, _) = note.get_parents(context, request_counter).await?; if post.locked { return Err(LemmyError::from_message("Post is locked")); } diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index 01cb8581..b7d38e34 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -10,6 +10,7 @@ use crate::{ LanguageTag, }, ImageObject, + InCommunity, Source, }, }; @@ -102,7 +103,7 @@ impl ApubObject for ApubPost { kind: PageType::Page, id: ObjectId::new(self.ap_id.clone()), attributed_to: AttributedTo::Lemmy(ObjectId::new(creator.actor_id)), - to: vec![community.actor_id.into(), public()], + to: vec![community.actor_id.clone().into(), public()], cc: vec![], name: self.name.clone(), content: self.body.as_ref().map(|b| markdown_to_html(b)), @@ -117,6 +118,7 @@ impl ApubObject for ApubPost { language, published: Some(convert_datetime(self.published)), updated: self.updated.map(convert_datetime), + audience: Some(ObjectId::new(community.actor_id)), }; Ok(page) } @@ -137,7 +139,7 @@ impl ApubObject for ApubPost { let local_site_data = fetch_local_site_data(context.pool()).await?; - let community = page.extract_community(context, request_counter).await?; + let community = page.community(context, request_counter).await?; check_apub_id_valid_with_strictness( page.id.inner(), community.local, @@ -164,7 +166,7 @@ impl ApubObject for ApubPost { .creator()? .dereference(context, local_instance(context).await, request_counter) .await?; - let community = page.extract_community(context, request_counter).await?; + let community = page.community(context, request_counter).await?; let form = if !page.is_mod_action(context).await? { let first_attachment = page.attachment.into_iter().map(Attachment::url).next(); diff --git a/crates/apub/src/protocol/activities/block/block_user.rs b/crates/apub/src/protocol/activities/block/block_user.rs index 3925c55c..91467a96 100644 --- a/crates/apub/src/protocol/activities/block/block_user.rs +++ b/crates/apub/src/protocol/activities/block/block_user.rs @@ -1,10 +1,20 @@ -use crate::{activities::block::SiteOrCommunity, objects::person::ApubPerson}; +use crate::{ + activities::{block::SiteOrCommunity, verify_community_matches}, + local_instance, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::InCommunity, +}; use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many}; use activitystreams_kinds::activity::BlockType; +use anyhow::anyhow; use chrono::{DateTime, FixedOffset}; +use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; +use serde_with::skip_serializing_none; use url::Url; +#[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct BlockUser { @@ -18,6 +28,7 @@ pub struct BlockUser { #[serde(rename = "type")] pub(crate) kind: BlockType, pub(crate) id: Url, + pub(crate) audience: Option>, /// Quick and dirty solution. /// TODO: send a separate Delete activity instead @@ -26,3 +37,30 @@ pub struct BlockUser { pub(crate) summary: Option, pub(crate) expires: Option>, } + +#[async_trait::async_trait(?Send)] +impl InCommunity for BlockUser { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let target = self + .target + .dereference(context, local_instance(context).await, request_counter) + .await?; + let target_community = match target { + SiteOrCommunity::Community(c) => c, + SiteOrCommunity::Site(_) => return Err(anyhow!("activity is not in community").into()), + }; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance(context).await, request_counter) + .await?; + verify_community_matches(&audience, target_community.id)?; + Ok(audience) + } else { + Ok(target_community) + } + } +} diff --git a/crates/apub/src/protocol/activities/block/undo_block_user.rs b/crates/apub/src/protocol/activities/block/undo_block_user.rs index df161143..ade126ee 100644 --- a/crates/apub/src/protocol/activities/block/undo_block_user.rs +++ b/crates/apub/src/protocol/activities/block/undo_block_user.rs @@ -1,9 +1,18 @@ -use crate::{objects::person::ApubPerson, protocol::activities::block::block_user::BlockUser}; +use crate::{ + activities::verify_community_matches, + local_instance, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::{activities::block::block_user::BlockUser, InCommunity}, +}; use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many}; use activitystreams_kinds::activity::UndoType; +use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; +use serde_with::skip_serializing_none; use url::Url; +#[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct UndoBlockUser { @@ -16,4 +25,25 @@ pub struct UndoBlockUser { #[serde(rename = "type")] pub(crate) kind: UndoType, pub(crate) id: Url, + pub(crate) audience: Option>, +} + +#[async_trait::async_trait(?Send)] +impl InCommunity for UndoBlockUser { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let object_community = self.object.community(context, request_counter).await?; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance(context).await, request_counter) + .await?; + verify_community_matches(&audience, object_community.id)?; + Ok(audience) + } else { + Ok(object_community) + } + } } diff --git a/crates/apub/src/protocol/activities/community/add_mod.rs b/crates/apub/src/protocol/activities/community/add_mod.rs index b9ce2420..f23fcbae 100644 --- a/crates/apub/src/protocol/activities/community/add_mod.rs +++ b/crates/apub/src/protocol/activities/community/add_mod.rs @@ -1,6 +1,13 @@ -use crate::objects::person::ApubPerson; +use crate::{ + activities::{community::get_community_from_moderators_url, verify_community_matches}, + local_instance, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::InCommunity, +}; use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many}; use activitystreams_kinds::activity::AddType; +use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; use url::Url; @@ -17,4 +24,26 @@ pub struct AddMod { #[serde(rename = "type")] pub(crate) kind: AddType, pub(crate) id: Url, + pub(crate) audience: Option>, +} + +#[async_trait::async_trait(?Send)] +impl InCommunity for AddMod { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let mod_community = + get_community_from_moderators_url(&self.target, context, request_counter).await?; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance(context).await, request_counter) + .await?; + verify_community_matches(&audience, mod_community.id)?; + Ok(audience) + } else { + Ok(mod_community) + } + } } diff --git a/crates/apub/src/protocol/activities/community/remove_mod.rs b/crates/apub/src/protocol/activities/community/remove_mod.rs index 6fd20af4..2ee744b7 100644 --- a/crates/apub/src/protocol/activities/community/remove_mod.rs +++ b/crates/apub/src/protocol/activities/community/remove_mod.rs @@ -1,6 +1,13 @@ -use crate::objects::person::ApubPerson; +use crate::{ + activities::{community::get_community_from_moderators_url, verify_community_matches}, + local_instance, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::InCommunity, +}; use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many}; use activitystreams_kinds::activity::RemoveType; +use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; use url::Url; @@ -17,4 +24,26 @@ pub struct RemoveMod { pub(crate) kind: RemoveType, pub(crate) target: Url, pub(crate) id: Url, + pub(crate) audience: Option>, +} + +#[async_trait::async_trait(?Send)] +impl InCommunity for RemoveMod { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let mod_community = + get_community_from_moderators_url(&self.target, context, request_counter).await?; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance(context).await, request_counter) + .await?; + verify_community_matches(&audience, mod_community.id)?; + Ok(audience) + } else { + Ok(mod_community) + } + } } diff --git a/crates/apub/src/protocol/activities/community/report.rs b/crates/apub/src/protocol/activities/community/report.rs index f9830c85..34738c56 100644 --- a/crates/apub/src/protocol/activities/community/report.rs +++ b/crates/apub/src/protocol/activities/community/report.rs @@ -1,9 +1,14 @@ use crate::{ + activities::verify_community_matches, fetcher::post_or_comment::PostOrComment, + local_instance, objects::{community::ApubCommunity, person::ApubPerson}, + protocol::InCommunity, }; use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one}; use activitystreams_kinds::activity::FlagType; +use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; use url::Url; @@ -18,4 +23,27 @@ pub struct Report { #[serde(rename = "type")] pub(crate) kind: FlagType, pub(crate) id: Url, + pub(crate) audience: Option>, +} + +#[async_trait::async_trait(?Send)] +impl InCommunity for Report { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let to_community = self.to[0] + .dereference(context, local_instance(context).await, request_counter) + .await?; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance(context).await, request_counter) + .await?; + verify_community_matches(&audience, to_community.id)?; + Ok(audience) + } else { + Ok(to_community) + } + } } diff --git a/crates/apub/src/protocol/activities/community/update.rs b/crates/apub/src/protocol/activities/community/update.rs index f6ef99c0..f534f236 100644 --- a/crates/apub/src/protocol/activities/community/update.rs +++ b/crates/apub/src/protocol/activities/community/update.rs @@ -1,6 +1,13 @@ -use crate::{objects::person::ApubPerson, protocol::objects::group::Group}; +use crate::{ + activities::verify_community_matches, + local_instance, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::{objects::group::Group, InCommunity}, +}; use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many}; use activitystreams_kinds::activity::UpdateType; +use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; use url::Url; @@ -19,4 +26,27 @@ pub struct UpdateCommunity { #[serde(rename = "type")] pub(crate) kind: UpdateType, pub(crate) id: Url, + pub(crate) audience: Option>, +} + +#[async_trait::async_trait(?Send)] +impl InCommunity for UpdateCommunity { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let object_community: ApubCommunity = ObjectId::new(self.object.id.clone()) + .dereference(context, local_instance(context).await, request_counter) + .await?; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance(context).await, request_counter) + .await?; + verify_community_matches(&audience, object_community.id)?; + Ok(audience) + } else { + Ok(object_community) + } + } } diff --git a/crates/apub/src/protocol/activities/create_or_update/private_message.rs b/crates/apub/src/protocol/activities/create_or_update/chat_message.rs similarity index 93% rename from crates/apub/src/protocol/activities/create_or_update/private_message.rs rename to crates/apub/src/protocol/activities/create_or_update/chat_message.rs index 6a9b585b..07a71d25 100644 --- a/crates/apub/src/protocol/activities/create_or_update/private_message.rs +++ b/crates/apub/src/protocol/activities/create_or_update/chat_message.rs @@ -8,7 +8,7 @@ use url::Url; #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct CreateOrUpdatePrivateMessage { +pub struct CreateOrUpdateChatMessage { pub(crate) id: Url, pub(crate) actor: ObjectId, #[serde(deserialize_with = "deserialize_one")] diff --git a/crates/apub/src/protocol/activities/create_or_update/comment.rs b/crates/apub/src/protocol/activities/create_or_update/comment.rs deleted file mode 100644 index 3049b79c..00000000 --- a/crates/apub/src/protocol/activities/create_or_update/comment.rs +++ /dev/null @@ -1,24 +0,0 @@ -use crate::{ - mentions::MentionOrValue, - objects::person::ApubPerson, - protocol::{activities::CreateOrUpdateType, objects::note::Note}, -}; -use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many}; -use serde::{Deserialize, Serialize}; -use url::Url; - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct CreateOrUpdateComment { - pub(crate) actor: ObjectId, - #[serde(deserialize_with = "deserialize_one_or_many")] - pub(crate) to: Vec, - pub(crate) object: Note, - #[serde(deserialize_with = "deserialize_one_or_many")] - pub(crate) cc: Vec, - #[serde(default)] - pub(crate) tag: Vec, - #[serde(rename = "type")] - pub(crate) kind: CreateOrUpdateType, - pub(crate) id: Url, -} diff --git a/crates/apub/src/protocol/activities/create_or_update/mod.rs b/crates/apub/src/protocol/activities/create_or_update/mod.rs index 0d233ccf..9e41d57f 100644 --- a/crates/apub/src/protocol/activities/create_or_update/mod.rs +++ b/crates/apub/src/protocol/activities/create_or_update/mod.rs @@ -1,33 +1,33 @@ -pub mod comment; -pub mod post; -pub mod private_message; +pub mod chat_message; +pub mod note; +pub mod page; #[cfg(test)] mod tests { use crate::protocol::{ activities::create_or_update::{ - comment::CreateOrUpdateComment, - post::CreateOrUpdatePost, - private_message::CreateOrUpdatePrivateMessage, + chat_message::CreateOrUpdateChatMessage, + note::CreateOrUpdateNote, + page::CreateOrUpdatePage, }, tests::test_parse_lemmy_item, }; #[test] fn test_parse_lemmy_create_or_update() { - test_parse_lemmy_item::( + test_parse_lemmy_item::( "assets/lemmy/activities/create_or_update/create_page.json", ) .unwrap(); - test_parse_lemmy_item::( + test_parse_lemmy_item::( "assets/lemmy/activities/create_or_update/update_page.json", ) .unwrap(); - test_parse_lemmy_item::( + test_parse_lemmy_item::( "assets/lemmy/activities/create_or_update/create_note.json", ) .unwrap(); - test_parse_lemmy_item::( + test_parse_lemmy_item::( "assets/lemmy/activities/create_or_update/create_private_message.json", ) .unwrap(); diff --git a/crates/apub/src/protocol/activities/create_or_update/note.rs b/crates/apub/src/protocol/activities/create_or_update/note.rs new file mode 100644 index 00000000..0de7161f --- /dev/null +++ b/crates/apub/src/protocol/activities/create_or_update/note.rs @@ -0,0 +1,51 @@ +use crate::{ + activities::verify_community_matches, + local_instance, + mentions::MentionOrValue, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::{activities::CreateOrUpdateType, objects::note::Note, InCommunity}, +}; +use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many}; +use lemmy_db_schema::{source::community::Community, traits::Crud}; +use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; +use serde::{Deserialize, Serialize}; +use url::Url; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CreateOrUpdateNote { + pub(crate) actor: ObjectId, + #[serde(deserialize_with = "deserialize_one_or_many")] + pub(crate) to: Vec, + pub(crate) object: Note, + #[serde(deserialize_with = "deserialize_one_or_many")] + pub(crate) cc: Vec, + #[serde(default)] + pub(crate) tag: Vec, + #[serde(rename = "type")] + pub(crate) kind: CreateOrUpdateType, + pub(crate) id: Url, + pub(crate) audience: Option>, +} + +#[async_trait::async_trait(?Send)] +impl InCommunity for CreateOrUpdateNote { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let post = self.object.get_parents(context, request_counter).await?.0; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance(context).await, request_counter) + .await?; + verify_community_matches(&audience, post.community_id)?; + Ok(audience) + } else { + let community = Community::read(context.pool(), post.community_id).await?; + Ok(community.into()) + } + } +} diff --git a/crates/apub/src/protocol/activities/create_or_update/page.rs b/crates/apub/src/protocol/activities/create_or_update/page.rs new file mode 100644 index 00000000..b0311b5f --- /dev/null +++ b/crates/apub/src/protocol/activities/create_or_update/page.rs @@ -0,0 +1,46 @@ +use crate::{ + activities::verify_community_matches, + local_instance, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::{activities::CreateOrUpdateType, objects::page::Page, InCommunity}, +}; +use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many}; +use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; +use serde::{Deserialize, Serialize}; +use url::Url; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CreateOrUpdatePage { + pub(crate) actor: ObjectId, + #[serde(deserialize_with = "deserialize_one_or_many")] + pub(crate) to: Vec, + pub(crate) object: Page, + #[serde(deserialize_with = "deserialize_one_or_many")] + pub(crate) cc: Vec, + #[serde(rename = "type")] + pub(crate) kind: CreateOrUpdateType, + pub(crate) id: Url, + pub(crate) audience: Option>, +} + +#[async_trait::async_trait(?Send)] +impl InCommunity for CreateOrUpdatePage { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let object_community = self.object.community(context, request_counter).await?; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance(context).await, request_counter) + .await?; + verify_community_matches(&audience, object_community.id)?; + Ok(audience) + } else { + Ok(object_community) + } + } +} diff --git a/crates/apub/src/protocol/activities/create_or_update/post.rs b/crates/apub/src/protocol/activities/create_or_update/post.rs deleted file mode 100644 index 70b15677..00000000 --- a/crates/apub/src/protocol/activities/create_or_update/post.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::{ - objects::person::ApubPerson, - protocol::{activities::CreateOrUpdateType, objects::page::Page}, -}; -use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many}; -use serde::{Deserialize, Serialize}; -use url::Url; - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct CreateOrUpdatePost { - pub(crate) actor: ObjectId, - #[serde(deserialize_with = "deserialize_one_or_many")] - pub(crate) to: Vec, - pub(crate) object: Page, - #[serde(deserialize_with = "deserialize_one_or_many")] - pub(crate) cc: Vec, - #[serde(rename = "type")] - pub(crate) kind: CreateOrUpdateType, - pub(crate) id: Url, -} diff --git a/crates/apub/src/protocol/activities/deletion/delete.rs b/crates/apub/src/protocol/activities/deletion/delete.rs index d3dcaf57..f5ae40d8 100644 --- a/crates/apub/src/protocol/activities/deletion/delete.rs +++ b/crates/apub/src/protocol/activities/deletion/delete.rs @@ -1,9 +1,18 @@ use crate::{ - objects::person::ApubPerson, - protocol::{objects::tombstone::Tombstone, IdOrNestedObject}, + activities::{deletion::DeletableObjects, verify_community_matches}, + local_instance, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::{objects::tombstone::Tombstone, IdOrNestedObject, InCommunity}, }; use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many}; use activitystreams_kinds::activity::DeleteType; +use anyhow::anyhow; +use lemmy_db_schema::{ + source::{community::Community, post::Post}, + traits::Crud, +}; +use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; use url::Url; @@ -19,6 +28,7 @@ pub struct Delete { #[serde(rename = "type")] pub(crate) kind: DeleteType, pub(crate) id: Url, + pub(crate) audience: Option>, #[serde(deserialize_with = "deserialize_one_or_many")] #[serde(default)] @@ -28,3 +38,34 @@ pub struct Delete { /// deleting their own content. pub(crate) summary: Option, } + +#[async_trait::async_trait(?Send)] +impl InCommunity for Delete { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let community_id = match DeletableObjects::read_from_db(self.object.id(), context).await? { + DeletableObjects::Community(c) => c.id, + DeletableObjects::Comment(c) => { + let post = Post::read(context.pool(), c.post_id).await?; + post.community_id + } + DeletableObjects::Post(p) => p.community_id, + DeletableObjects::PrivateMessage(_) => { + return Err(anyhow!("Private message is not part of community").into()) + } + }; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance(context).await, request_counter) + .await?; + verify_community_matches(&audience, community_id)?; + Ok(audience) + } else { + let community = Community::read(context.pool(), community_id).await?; + Ok(community.into()) + } + } +} diff --git a/crates/apub/src/protocol/activities/deletion/undo_delete.rs b/crates/apub/src/protocol/activities/deletion/undo_delete.rs index 02cbf178..c4946850 100644 --- a/crates/apub/src/protocol/activities/deletion/undo_delete.rs +++ b/crates/apub/src/protocol/activities/deletion/undo_delete.rs @@ -1,9 +1,18 @@ -use crate::{objects::person::ApubPerson, protocol::activities::deletion::delete::Delete}; +use crate::{ + activities::verify_community_matches, + local_instance, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::{activities::deletion::delete::Delete, InCommunity}, +}; use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many}; use activitystreams_kinds::activity::UndoType; +use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; +use serde_with::skip_serializing_none; use url::Url; +#[skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct UndoDelete { @@ -14,8 +23,29 @@ pub struct UndoDelete { #[serde(rename = "type")] pub(crate) kind: UndoType, pub(crate) id: Url, + pub(crate) audience: Option>, #[serde(deserialize_with = "deserialize_one_or_many", default)] #[serde(skip_serializing_if = "Vec::is_empty")] pub(crate) cc: Vec, } + +#[async_trait::async_trait(?Send)] +impl InCommunity for UndoDelete { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let object_community = self.object.community(context, request_counter).await?; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance(context).await, request_counter) + .await?; + verify_community_matches(&audience, object_community.id)?; + Ok(audience) + } else { + Ok(object_community) + } + } +} diff --git a/crates/apub/src/protocol/activities/mod.rs b/crates/apub/src/protocol/activities/mod.rs index fcd3153c..670c4466 100644 --- a/crates/apub/src/protocol/activities/mod.rs +++ b/crates/apub/src/protocol/activities/mod.rs @@ -19,7 +19,7 @@ mod tests { use crate::protocol::{ activities::{ community::announce::AnnounceActivity, - create_or_update::{comment::CreateOrUpdateComment, post::CreateOrUpdatePost}, + create_or_update::{note::CreateOrUpdateNote, page::CreateOrUpdatePage}, deletion::delete::Delete, following::{follow::Follow, undo_follow::UndoFollow}, voting::{undo_vote::UndoVote, vote::Vote}, @@ -29,19 +29,19 @@ mod tests { #[test] fn test_parse_smithereen_activities() { - test_json::("assets/smithereen/activities/create_note.json").unwrap(); + test_json::("assets/smithereen/activities/create_note.json").unwrap(); } #[test] fn test_parse_pleroma_activities() { - test_json::("assets/pleroma/activities/create_note.json").unwrap(); + test_json::("assets/pleroma/activities/create_note.json").unwrap(); test_json::("assets/pleroma/activities/delete.json").unwrap(); test_json::("assets/pleroma/activities/follow.json").unwrap(); } #[test] fn test_parse_mastodon_activities() { - test_json::("assets/mastodon/activities/create_note.json").unwrap(); + test_json::("assets/mastodon/activities/create_note.json").unwrap(); test_json::("assets/mastodon/activities/delete.json").unwrap(); test_json::("assets/mastodon/activities/follow.json").unwrap(); test_json::("assets/mastodon/activities/undo_follow.json").unwrap(); @@ -51,17 +51,17 @@ mod tests { #[test] fn test_parse_lotide_activities() { - test_json::("assets/lotide/activities/create_page.json").unwrap(); - test_json::("assets/lotide/activities/create_page_image.json").unwrap(); - test_json::("assets/lotide/activities/create_note_reply.json").unwrap(); + test_json::("assets/lotide/activities/create_page.json").unwrap(); + test_json::("assets/lotide/activities/create_page_image.json").unwrap(); + test_json::("assets/lotide/activities/create_note_reply.json").unwrap(); } #[test] fn test_parse_friendica_activities() { - test_json::("assets/friendica/activities/create_page_1.json").unwrap(); - test_json::("assets/friendica/activities/create_page_2.json").unwrap(); - test_json::("assets/friendica/activities/create_note.json").unwrap(); - test_json::("assets/friendica/activities/update_note.json").unwrap(); + test_json::("assets/friendica/activities/create_page_1.json").unwrap(); + test_json::("assets/friendica/activities/create_page_2.json").unwrap(); + test_json::("assets/friendica/activities/create_note.json").unwrap(); + test_json::("assets/friendica/activities/update_note.json").unwrap(); test_json::("assets/friendica/activities/delete.json").unwrap(); test_json::("assets/friendica/activities/like_page.json").unwrap(); test_json::("assets/friendica/activities/dislike_page.json").unwrap(); @@ -70,8 +70,8 @@ mod tests { #[test] fn test_parse_gnusocial_activities() { - test_json::("assets/gnusocial/activities/create_page.json").unwrap(); - test_json::("assets/gnusocial/activities/create_note.json").unwrap(); + test_json::("assets/gnusocial/activities/create_page.json").unwrap(); + test_json::("assets/gnusocial/activities/create_note.json").unwrap(); test_json::("assets/gnusocial/activities/like_note.json").unwrap(); } diff --git a/crates/apub/src/protocol/activities/voting/undo_vote.rs b/crates/apub/src/protocol/activities/voting/undo_vote.rs index ee258539..1d17cf15 100644 --- a/crates/apub/src/protocol/activities/voting/undo_vote.rs +++ b/crates/apub/src/protocol/activities/voting/undo_vote.rs @@ -1,6 +1,13 @@ -use crate::{objects::person::ApubPerson, protocol::activities::voting::vote::Vote}; +use crate::{ + activities::verify_community_matches, + local_instance, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::{activities::voting::vote::Vote, InCommunity}, +}; use activitypub_federation::core::object_id::ObjectId; use activitystreams_kinds::activity::UndoType; +use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; use url::Url; @@ -12,4 +19,26 @@ pub struct UndoVote { #[serde(rename = "type")] pub(crate) kind: UndoType, pub(crate) id: Url, + pub(crate) audience: Option>, +} + +#[async_trait::async_trait(?Send)] +impl InCommunity for UndoVote { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let local_instance = local_instance(context).await; + let object_community = self.object.community(context, request_counter).await?; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance, request_counter) + .await?; + verify_community_matches(&audience, object_community.id)?; + Ok(audience) + } else { + Ok(object_community) + } + } } diff --git a/crates/apub/src/protocol/activities/voting/vote.rs b/crates/apub/src/protocol/activities/voting/vote.rs index 002d235c..5da9b791 100644 --- a/crates/apub/src/protocol/activities/voting/vote.rs +++ b/crates/apub/src/protocol/activities/voting/vote.rs @@ -1,6 +1,13 @@ -use crate::{fetcher::post_or_comment::PostOrComment, objects::person::ApubPerson}; +use crate::{ + activities::verify_community_matches, + fetcher::post_or_comment::PostOrComment, + local_instance, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::InCommunity, +}; use activitypub_federation::core::object_id::ObjectId; use lemmy_utils::error::LemmyError; +use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; use std::convert::TryFrom; use strum_macros::Display; @@ -14,6 +21,7 @@ pub struct Vote { #[serde(rename = "type")] pub(crate) kind: VoteType, pub(crate) id: Url, + pub(crate) audience: Option>, } #[derive(Clone, Debug, Display, Deserialize, Serialize, PartialEq, Eq)] @@ -42,3 +50,29 @@ impl From<&VoteType> for i16 { } } } + +#[async_trait::async_trait(?Send)] +impl InCommunity for Vote { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let local_instance = local_instance(context).await; + let object_community = self + .object + .dereference(context, local_instance, request_counter) + .await? + .community(context, request_counter) + .await?; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance, request_counter) + .await?; + verify_community_matches(&audience, object_community.id)?; + Ok(audience) + } else { + Ok(object_community) + } + } +} diff --git a/crates/apub/src/protocol/mod.rs b/crates/apub/src/protocol/mod.rs index c259a6e9..a65e74da 100644 --- a/crates/apub/src/protocol/mod.rs +++ b/crates/apub/src/protocol/mod.rs @@ -1,4 +1,4 @@ -use crate::local_instance; +use crate::{local_instance, objects::community::ApubCommunity}; use activitypub_federation::{deser::values::MediaTypeMarkdown, utils::fetch_object_http}; use activitystreams_kinds::object::ImageType; use lemmy_db_schema::newtypes::DbUrl; @@ -81,6 +81,17 @@ impl IdOrNestedObject { } } +#[async_trait::async_trait(?Send)] +pub trait InCommunity { + // TODO: after we use audience field and remove backwards compat, it should be possible to change + // this to simply `fn community(&self) -> Result, LemmyError>` + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result; +} + #[cfg(test)] pub(crate) mod tests { use activitypub_federation::deser::context::WithContext; diff --git a/crates/apub/src/protocol/objects/note.rs b/crates/apub/src/protocol/objects/note.rs index 727b9899..21f7bcf3 100644 --- a/crates/apub/src/protocol/objects/note.rs +++ b/crates/apub/src/protocol/objects/note.rs @@ -1,9 +1,10 @@ use crate::{ + activities::verify_community_matches, fetcher::post_or_comment::PostOrComment, local_instance, mentions::MentionOrValue, - objects::{comment::ApubComment, person::ApubPerson, post::ApubPost}, - protocol::{objects::LanguageTag, Source}, + objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost}, + protocol::{objects::LanguageTag, InCommunity, Source}, }; use activitypub_federation::{ core::object_id::ObjectId, @@ -14,7 +15,10 @@ use activitypub_federation::{ }; use activitystreams_kinds::object::NoteType; use chrono::{DateTime, FixedOffset}; -use lemmy_db_schema::{source::post::Post, traits::Crud}; +use lemmy_db_schema::{ + source::{community::Community, post::Post}, + traits::Crud, +}; use lemmy_utils::error::LemmyError; use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; @@ -46,6 +50,7 @@ pub struct Note { // lemmy extension pub(crate) distinguished: Option, pub(crate) language: Option, + pub(crate) audience: Option>, } impl Note { @@ -75,3 +80,24 @@ impl Note { } } } + +#[async_trait::async_trait(?Send)] +impl InCommunity for Note { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let (post, _) = self.get_parents(context, request_counter).await?; + let community_id = post.community_id; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, local_instance(context).await, request_counter) + .await?; + verify_community_matches(&audience, community_id)?; + Ok(audience) + } else { + Ok(Community::read(context.pool(), community_id).await?.into()) + } + } +} diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs index ba76f62f..b25e1d97 100644 --- a/crates/apub/src/protocol/objects/page.rs +++ b/crates/apub/src/protocol/objects/page.rs @@ -1,8 +1,9 @@ use crate::{ + activities::verify_community_matches, fetcher::user_or_community::{PersonOrGroupType, UserOrCommunity}, local_instance, objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost}, - protocol::{objects::LanguageTag, ImageObject, Source}, + protocol::{objects::LanguageTag, ImageObject, InCommunity, Source}, }; use activitypub_federation::{ core::object_id::ObjectId, @@ -67,6 +68,7 @@ pub struct Page { pub(crate) published: Option>, pub(crate) updated: Option>, pub(crate) language: Option, + pub(crate) audience: Option>, } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -169,39 +171,6 @@ impl Page { false } - pub(crate) async fn extract_community( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result { - match &self.attributed_to { - AttributedTo::Lemmy(_) => { - let mut iter = self.to.iter().merge(self.cc.iter()); - loop { - if let Some(cid) = iter.next() { - let cid = ObjectId::new(cid.clone()); - if let Ok(c) = cid - .dereference(context, local_instance(context).await, request_counter) - .await - { - break Ok(c); - } - } else { - return Err(LemmyError::from_message("No community found in cc")); - } - } - } - AttributedTo::Peertube(p) => { - p.iter() - .find(|a| a.kind == PersonOrGroupType::Group) - .map(|a| ObjectId::::new(a.id.clone().into_inner())) - .ok_or_else(|| LemmyError::from_message("page does not specify group"))? - .dereference(context, local_instance(context).await, request_counter) - .await - } - } - } - pub(crate) fn creator(&self) -> Result, LemmyError> { match &self.attributed_to { AttributedTo::Lemmy(l) => Ok(l.clone()), @@ -250,3 +219,46 @@ impl ActivityHandler for Page { Ok(()) } } + +#[async_trait::async_trait(?Send)] +impl InCommunity for Page { + async fn community( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let instance = local_instance(context).await; + let community = match &self.attributed_to { + AttributedTo::Lemmy(_) => { + let mut iter = self.to.iter().merge(self.cc.iter()); + loop { + if let Some(cid) = iter.next() { + let cid = ObjectId::new(cid.clone()); + if let Ok(c) = cid.dereference(context, instance, request_counter).await { + break c; + } + } else { + return Err(LemmyError::from_message("No community found in cc")); + } + } + } + AttributedTo::Peertube(p) => { + p.iter() + .find(|a| a.kind == PersonOrGroupType::Group) + .map(|a| ObjectId::::new(a.id.clone().into_inner())) + .ok_or_else(|| LemmyError::from_message("page does not specify group"))? + .dereference(context, instance, request_counter) + .await? + } + }; + if let Some(audience) = &self.audience { + let audience = audience + .dereference(context, instance, request_counter) + .await?; + verify_community_matches(&audience, community.id)?; + Ok(audience) + } else { + Ok(community) + } + } +}