From 969a7f2d1b3cdc85e1f8438ba2261212b5774a6d Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Wed, 3 Nov 2021 17:26:09 +0100 Subject: [PATCH 01/10] Refactoring apub code --- .../activities/comment/create_or_update.rs | 2 +- .../src/activities/post/create_or_update.rs | 4 ++-- .../private_message/create_or_update.rs | 2 +- crates/apub/src/objects/comment.rs | 8 +++++--- crates/apub/src/objects/community.rs | 2 +- crates/apub/src/objects/person.rs | 7 ++++--- crates/apub/src/objects/post.rs | 13 ++++++------- crates/apub/src/objects/private_message.rs | 6 ++++-- .../apub/src/protocol/objects/chat_message.rs | 19 +++++++------------ crates/apub/src/protocol/objects/group.rs | 8 ++++---- crates/apub/src/protocol/objects/note.rs | 17 +++-------------- crates/apub/src/protocol/objects/page.rs | 12 ++---------- crates/apub/src/protocol/objects/person.rs | 8 ++++++-- 13 files changed, 46 insertions(+), 62 deletions(-) diff --git a/crates/apub/src/activities/comment/create_or_update.rs b/crates/apub/src/activities/comment/create_or_update.rs index a9c1a9ee8..10666932e 100644 --- a/crates/apub/src/activities/comment/create_or_update.rs +++ b/crates/apub/src/activities/comment/create_or_update.rs @@ -83,7 +83,7 @@ impl ActivityHandler for CreateOrUpdateComment { verify_activity(self, &context.settings())?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; - verify_domains_match(self.actor.inner(), self.object.id_unchecked())?; + verify_domains_match(self.actor.inner(), self.object.id.inner())?; check_community_deleted_or_removed(&community)?; check_post_deleted_or_removed(&post)?; diff --git a/crates/apub/src/activities/post/create_or_update.rs b/crates/apub/src/activities/post/create_or_update.rs index 41590493c..677ce2dc1 100644 --- a/crates/apub/src/activities/post/create_or_update.rs +++ b/crates/apub/src/activities/post/create_or_update.rs @@ -84,7 +84,7 @@ impl ActivityHandler for CreateOrUpdatePost { match self.kind { CreateOrUpdateType::Create => { - verify_domains_match(self.actor.inner(), self.object.id_unchecked())?; + verify_domains_match(self.actor.inner(), self.object.id.inner())?; verify_urls_match(self.actor(), self.object.attributed_to.inner())?; // Check that the post isnt locked or stickied, as that isnt possible for newly created posts. // However, when fetching a remote post we generate a new create activity with the current @@ -101,7 +101,7 @@ impl ActivityHandler for CreateOrUpdatePost { if is_mod_action { verify_mod_action(&self.actor, &community, context, request_counter).await?; } else { - verify_domains_match(self.actor.inner(), self.object.id_unchecked())?; + verify_domains_match(self.actor.inner(), self.object.id.inner())?; verify_urls_match(self.actor(), self.object.attributed_to.inner())?; } } diff --git a/crates/apub/src/activities/private_message/create_or_update.rs b/crates/apub/src/activities/private_message/create_or_update.rs index cfd7c8bcf..e441718ab 100644 --- a/crates/apub/src/activities/private_message/create_or_update.rs +++ b/crates/apub/src/activities/private_message/create_or_update.rs @@ -56,7 +56,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage { ) -> Result<(), LemmyError> { verify_activity(self, &context.settings())?; verify_person(&self.actor, context, request_counter).await?; - verify_domains_match(self.actor.inner(), self.object.id_unchecked())?; + verify_domains_match(self.actor.inner(), self.object.id.inner())?; self.object.verify(context, request_counter).await?; Ok(()) } diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs index 08a55bf9c..68240728a 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -39,6 +39,7 @@ use crate::{ }, PostOrComment, }; +use lemmy_apub_lib::verify::verify_domains_match; use lemmy_utils::utils::markdown_to_html; #[derive(Clone, Debug)] @@ -107,7 +108,7 @@ impl ApubObject for ApubComment { let note = Note { r#type: NoteType::Note, - id: self.ap_id.to_owned().into_inner(), + id: ObjectId::new(self.ap_id.to_owned()), attributed_to: ObjectId::new(creator.actor_id), to: vec![public()], content: markdown_to_html(&self.content), @@ -141,7 +142,8 @@ impl ApubObject for ApubComment { expected_domain: &Url, request_counter: &mut i32, ) -> Result { - let ap_id = Some(note.id(expected_domain)?.clone().into()); + verify_domains_match(note.id.inner(), expected_domain)?; + let ap_id = Some(note.id.clone().into()); let creator = note .attributed_to .dereference(context, request_counter) @@ -152,7 +154,7 @@ impl ApubObject for ApubComment { Community::read(conn, community_id) }) .await??; - check_is_apub_id_valid(¬e.id, community.local, &context.settings())?; + check_is_apub_id_valid(note.id.inner(), community.local, &context.settings())?; verify_person_in_community( ¬e.attributed_to, &community.into(), diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index 0947ebf37..8fd245dc2 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -96,7 +96,7 @@ impl ApubObject for ApubCommunity { let group = Group { kind: GroupType::Group, - id: self.actor_id(), + id: ObjectId::new(self.actor_id()), preferred_username: self.name.clone(), name: self.title.clone(), summary: self.description.as_ref().map(|b| markdown_to_html(b)), diff --git a/crates/apub/src/objects/person.rs b/crates/apub/src/objects/person.rs index 18522e569..652ef6220 100644 --- a/crates/apub/src/objects/person.rs +++ b/crates/apub/src/objects/person.rs @@ -1,5 +1,6 @@ use crate::{ check_is_apub_id_valid, + fetcher::object_id::ObjectId, generate_outbox_url, objects::get_summary_from_string_or_source, protocol::{ @@ -96,7 +97,7 @@ impl ApubObject for ApubPerson { let person = Person { kind, - id: self.actor_id.to_owned().into_inner(), + id: ObjectId::new(self.actor_id.clone()), preferred_username: self.name.clone(), name: self.display_name.clone(), summary: self.bio.as_ref().map(|b| markdown_to_html(b)), @@ -128,7 +129,7 @@ impl ApubObject for ApubPerson { expected_domain: &Url, _request_counter: &mut i32, ) -> Result { - verify_domains_match(&person.id, expected_domain)?; + verify_domains_match(person.id.inner(), expected_domain)?; let actor_id = Some(person.id.clone().into()); let name = person.preferred_username.clone(); let display_name: Option = person.name.clone(); @@ -144,7 +145,7 @@ impl ApubObject for ApubPerson { check_slurs_opt(&display_name, slur_regex)?; check_slurs_opt(&bio, slur_regex)?; - check_is_apub_id_valid(&person.id, false, &context.settings())?; + check_is_apub_id_valid(person.id.inner(), false, &context.settings())?; let person_form = PersonForm { name, diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index b835f812e..b29bdb801 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -17,6 +17,7 @@ use lemmy_api_common::blocking; use lemmy_apub_lib::{ traits::ApubObject, values::{MediaTypeHtml, MediaTypeMarkdown}, + verify::verify_domains_match, }; use lemmy_db_schema::{ self, @@ -106,7 +107,7 @@ impl ApubObject for ApubPost { let page = Page { r#type: PageType::Page, - id: self.ap_id.clone().into(), + id: ObjectId::new(self.ap_id.clone()), attributed_to: ObjectId::new(creator.actor_id), to: vec![community.actor_id.into(), public()], name: self.name.clone(), @@ -140,18 +141,16 @@ impl ApubObject for ApubPost { ) -> Result { // We can't verify the domain in case of mod action, because the mod may be on a different // instance from the post author. - let ap_id = if page.is_mod_action(context).await? { - page.id_unchecked() - } else { - page.id(expected_domain)? + if !page.is_mod_action(context).await? { + verify_domains_match(page.id.inner(), expected_domain)?; }; - let ap_id = Some(ap_id.clone().into()); + let ap_id = Some(page.id.clone().into()); let creator = page .attributed_to .dereference(context, request_counter) .await?; let community = page.extract_community(context, request_counter).await?; - check_is_apub_id_valid(&page.id, community.local, &context.settings())?; + check_is_apub_id_valid(page.id.inner(), community.local, &context.settings())?; verify_person_in_community(&page.attributed_to, &community, context, request_counter).await?; let thumbnail_url: Option = page.image.clone().map(|i| i.url); diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs index 81615fdc9..5c4befb05 100644 --- a/crates/apub/src/objects/private_message.rs +++ b/crates/apub/src/objects/private_message.rs @@ -11,6 +11,7 @@ use lemmy_api_common::blocking; use lemmy_apub_lib::{ traits::ApubObject, values::{MediaTypeHtml, MediaTypeMarkdown}, + verify::verify_domains_match, }; use lemmy_db_schema::{ source::{ @@ -81,7 +82,7 @@ impl ApubObject for ApubPrivateMessage { let note = ChatMessage { r#type: ChatMessageType::ChatMessage, - id: self.ap_id.clone().into(), + id: ObjectId::new(self.ap_id.clone()), attributed_to: ObjectId::new(creator.actor_id), to: [ObjectId::new(recipient.actor_id)], content: markdown_to_html(&self.content), @@ -107,7 +108,8 @@ impl ApubObject for ApubPrivateMessage { expected_domain: &Url, request_counter: &mut i32, ) -> Result { - let ap_id = Some(note.id(expected_domain)?.clone().into()); + verify_domains_match(note.id.inner(), expected_domain)?; + let ap_id = Some(note.id.clone().into()); let creator = note .attributed_to .dereference(context, request_counter) diff --git a/crates/apub/src/protocol/objects/chat_message.rs b/crates/apub/src/protocol/objects/chat_message.rs index 038af4edf..e9677758c 100644 --- a/crates/apub/src/protocol/objects/chat_message.rs +++ b/crates/apub/src/protocol/objects/chat_message.rs @@ -1,4 +1,8 @@ -use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson, protocol::Source}; +use crate::{ + fetcher::object_id::ObjectId, + objects::{person::ApubPerson, private_message::ApubPrivateMessage}, + protocol::Source, +}; use activitystreams::{ chrono::{DateTime, FixedOffset}, unparsed::Unparsed, @@ -9,14 +13,13 @@ use lemmy_utils::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 ChatMessage { pub(crate) r#type: ChatMessageType, - pub(crate) id: Url, + pub(crate) id: ObjectId, pub(crate) attributed_to: ObjectId, pub(crate) to: [ObjectId; 1], pub(crate) content: String, @@ -35,20 +38,12 @@ pub enum ChatMessageType { } impl ChatMessage { - pub(crate) fn id_unchecked(&self) -> &Url { - &self.id - } - pub(crate) fn id(&self, expected_domain: &Url) -> Result<&Url, LemmyError> { - verify_domains_match(&self.id, expected_domain)?; - Ok(&self.id) - } - pub(crate) async fn verify( &self, context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_domains_match(self.attributed_to.inner(), &self.id)?; + verify_domains_match(self.attributed_to.inner(), self.id.inner())?; let person = self .attributed_to .dereference(context, request_counter) diff --git a/crates/apub/src/protocol/objects/group.rs b/crates/apub/src/protocol/objects/group.rs index 4da987a25..921a5dc8d 100644 --- a/crates/apub/src/protocol/objects/group.rs +++ b/crates/apub/src/protocol/objects/group.rs @@ -5,7 +5,7 @@ use crate::{ community_outbox::ApubCommunityOutbox, }, fetcher::object_id::ObjectId, - objects::get_summary_from_string_or_source, + objects::{community::ApubCommunity, get_summary_from_string_or_source}, protocol::{ImageObject, Source}, }; use activitystreams::{ @@ -30,7 +30,7 @@ use url::Url; pub struct Group { #[serde(rename = "type")] pub(crate) kind: GroupType, - pub(crate) id: Url, + pub(crate) id: ObjectId, /// username, set at account creation and can never be changed pub(crate) preferred_username: String, /// title (can be changed at any time) @@ -61,8 +61,8 @@ impl Group { expected_domain: &Url, settings: &Settings, ) -> Result { - check_is_apub_id_valid(&group.id, true, settings)?; - verify_domains_match(expected_domain, &group.id)?; + check_is_apub_id_valid(group.id.inner(), true, settings)?; + verify_domains_match(expected_domain, group.id.inner())?; let name = group.preferred_username.clone(); let title = group.name.clone(); let description = get_summary_from_string_or_source(&group.summary, &group.source); diff --git a/crates/apub/src/protocol/objects/note.rs b/crates/apub/src/protocol/objects/note.rs index bdc4da66b..58b164a7d 100644 --- a/crates/apub/src/protocol/objects/note.rs +++ b/crates/apub/src/protocol/objects/note.rs @@ -1,7 +1,7 @@ use crate::{ activities::{verify_is_public, verify_person_in_community}, fetcher::{object_id::ObjectId, post_or_comment::PostOrComment}, - objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost}, + objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost}, protocol::Source, }; use activitystreams::{object::kind::NoteType, unparsed::Unparsed}; @@ -26,11 +26,8 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct Note { pub(crate) r#type: NoteType, - pub(crate) id: Url, + pub(crate) id: ObjectId, pub(crate) attributed_to: ObjectId, - /// Indicates that the object is publicly readable. Unlike [`Post.to`], this one doesn't contain - /// the community ID, as it would be incompatible with Pleroma (and we can get the community from - /// the post in [`in_reply_to`]). pub(crate) to: Vec, pub(crate) content: String, pub(crate) media_type: Option, @@ -52,14 +49,6 @@ pub(crate) enum SourceCompat { } impl Note { - pub(crate) fn id_unchecked(&self) -> &Url { - &self.id - } - pub(crate) fn id(&self, expected_domain: &Url) -> Result<&Url, LemmyError> { - verify_domains_match(&self.id, expected_domain)?; - Ok(&self.id) - } - pub(crate) async fn get_parents( &self, context: &LemmyContext, @@ -104,7 +93,7 @@ impl Note { if post.locked { return Err(anyhow!("Post is locked").into()); } - verify_domains_match(self.attributed_to.inner(), &self.id)?; + verify_domains_match(self.attributed_to.inner(), self.id.inner())?; verify_person_in_community(&self.attributed_to, &community, context, request_counter).await?; verify_is_public(&self.to)?; Ok(()) diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs index 7887f19c1..0cd004799 100644 --- a/crates/apub/src/protocol/objects/page.rs +++ b/crates/apub/src/protocol/objects/page.rs @@ -19,7 +19,7 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct Page { pub(crate) r#type: PageType, - pub(crate) id: Url, + pub(crate) id: ObjectId, pub(crate) attributed_to: ObjectId, pub(crate) to: Vec, pub(crate) name: String, @@ -38,14 +38,6 @@ pub struct Page { } impl Page { - pub(crate) fn id_unchecked(&self) -> &Url { - &self.id - } - pub(crate) fn id(&self, expected_domain: &Url) -> Result<&Url, LemmyError> { - verify_domains_match(&self.id, expected_domain)?; - Ok(&self.id) - } - /// Only mods can change the post's stickied/locked status. So if either of these is changed from /// the current value, it is a mod action and needs to be verified as such. /// @@ -71,7 +63,7 @@ impl Page { let community = self.extract_community(context, request_counter).await?; check_slurs(&self.name, &context.settings().slur_regex())?; - verify_domains_match(self.attributed_to.inner(), &self.id.clone())?; + verify_domains_match(self.attributed_to.inner(), self.id.inner())?; verify_person_in_community(&self.attributed_to, &community, context, request_counter).await?; verify_is_public(&self.to.clone())?; Ok(()) diff --git a/crates/apub/src/protocol/objects/person.rs b/crates/apub/src/protocol/objects/person.rs index 2aecf945e..720e7de00 100644 --- a/crates/apub/src/protocol/objects/person.rs +++ b/crates/apub/src/protocol/objects/person.rs @@ -1,4 +1,8 @@ -use crate::protocol::{ImageObject, Source}; +use crate::{ + fetcher::object_id::ObjectId, + objects::person::ApubPerson, + protocol::{ImageObject, Source}, +}; use activitystreams::{actor::Endpoints, unparsed::Unparsed, url::Url}; use chrono::{DateTime, FixedOffset}; use lemmy_apub_lib::signatures::PublicKey; @@ -17,7 +21,7 @@ pub enum UserTypes { pub struct Person { #[serde(rename = "type")] pub(crate) kind: UserTypes, - pub(crate) id: Url, + pub(crate) id: ObjectId, /// username, set at account creation and can never be changed pub(crate) preferred_username: String, /// displayname (can be changed at any time) From bd3352423a792bb8a6c14c1970a9a4822a27546a Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Wed, 3 Nov 2021 18:33:51 +0100 Subject: [PATCH 02/10] Remove ActivityFields trait, deserialize into another struct instead --- .../activities/comment/create_or_update.rs | 30 +++-- .../apub/src/activities/community/add_mod.rs | 2 +- .../apub/src/activities/community/announce.rs | 14 ++- .../src/activities/community/block_user.rs | 2 +- .../src/activities/community/remove_mod.rs | 2 +- .../apub/src/activities/community/report.rs | 28 ++--- .../activities/community/undo_block_user.rs | 2 +- .../apub/src/activities/community/update.rs | 2 +- crates/apub/src/activities/deletion/delete.rs | 38 +++--- crates/apub/src/activities/deletion/mod.rs | 38 +++--- .../src/activities/deletion/undo_delete.rs | 36 +++--- .../apub/src/activities/following/accept.rs | 8 +- .../apub/src/activities/following/follow.rs | 2 +- .../src/activities/following/undo_follow.rs | 6 +- crates/apub/src/activities/mod.rs | 8 +- .../src/activities/post/create_or_update.rs | 30 +++-- .../private_message/create_or_update.rs | 2 +- .../src/activities/private_message/delete.rs | 2 +- .../activities/private_message/undo_delete.rs | 8 +- .../apub/src/activities/voting/undo_vote.rs | 29 ++--- crates/apub/src/activities/voting/vote.rs | 33 +++-- crates/apub/src/activity_lists.rs | 10 +- crates/apub/src/fetcher/mod.rs | 32 +---- crates/apub/src/fetcher/post_or_comment.rs | 30 ++--- crates/apub/src/fetcher/user_or_community.rs | 113 ++++++++++++++++++ crates/apub/src/http/community.rs | 11 +- crates/apub/src/http/mod.rs | 44 ++++--- crates/apub/src/http/person.rs | 7 +- .../protocol/activities/community/add_mod.rs | 3 +- .../protocol/activities/community/announce.rs | 3 +- .../activities/community/block_user.rs | 3 +- .../activities/community/remove_mod.rs | 3 +- .../protocol/activities/community/report.rs | 3 +- .../activities/community/undo_block_user.rs | 3 +- .../protocol/activities/community/update.rs | 3 +- .../activities/create_or_update/comment.rs | 3 +- .../activities/create_or_update/post.rs | 3 +- .../protocol/activities/deletion/delete.rs | 3 +- .../activities/deletion/undo_delete.rs | 11 +- .../protocol/activities/following/accept.rs | 3 +- .../protocol/activities/following/follow.rs | 3 +- .../activities/following/undo_follow.rs | 3 +- .../private_message/create_or_update.rs | 3 +- .../activities/private_message/delete.rs | 3 +- .../activities/private_message/undo_delete.rs | 3 +- .../protocol/activities/voting/undo_vote.rs | 11 +- .../src/protocol/activities/voting/vote.rs | 3 +- crates/apub_lib/src/traits.rs | 5 - crates/apub_lib_derive/src/lib.rs | 37 ------ 49 files changed, 344 insertions(+), 340 deletions(-) create mode 100644 crates/apub/src/fetcher/user_or_community.rs diff --git a/crates/apub/src/activities/comment/create_or_update.rs b/crates/apub/src/activities/comment/create_or_update.rs index 10666932e..84f6d3f28 100644 --- a/crates/apub/src/activities/comment/create_or_update.rs +++ b/crates/apub/src/activities/comment/create_or_update.rs @@ -1,18 +1,3 @@ -use activitystreams::public; - -use lemmy_api_common::{blocking, check_post_deleted_or_removed}; -use lemmy_apub_lib::{ - data::Data, - traits::{ActivityHandler, ActorType, ApubObject}, - verify::verify_domains_match, -}; -use lemmy_db_schema::{ - source::{community::Community, post::Post}, - traits::Crud, -}; -use lemmy_utils::LemmyError; -use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud}; - use crate::{ activities::{ check_community_deleted_or_removed, @@ -28,6 +13,19 @@ use crate::{ objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson}, protocol::activities::{create_or_update::comment::CreateOrUpdateComment, CreateOrUpdateType}, }; +use activitystreams::public; +use lemmy_api_common::{blocking, check_post_deleted_or_removed}; +use lemmy_apub_lib::{ + data::Data, + traits::{ActivityHandler, ActorType, ApubObject}, + verify::verify_domains_match, +}; +use lemmy_db_schema::{ + source::{community::Community, post::Post}, + traits::Crud, +}; +use lemmy_utils::LemmyError; +use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud}; impl CreateOrUpdateComment { pub async fn send( @@ -81,7 +79,7 @@ impl ActivityHandler for CreateOrUpdateComment { let post = self.object.get_parents(context, request_counter).await?.0; let community = self.get_community(context, request_counter).await?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_domains_match(self.actor.inner(), self.object.id.inner())?; check_community_deleted_or_removed(&community)?; diff --git a/crates/apub/src/activities/community/add_mod.rs b/crates/apub/src/activities/community/add_mod.rs index b18e50ada..11dc5a0b9 100644 --- a/crates/apub/src/activities/community/add_mod.rs +++ b/crates/apub/src/activities/community/add_mod.rs @@ -65,7 +65,7 @@ impl ActivityHandler for AddMod { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to)?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_mod_action(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/community/announce.rs b/crates/apub/src/activities/community/announce.rs index f560b09f6..b245a1b88 100644 --- a/crates/apub/src/activities/community/announce.rs +++ b/crates/apub/src/activities/community/announce.rs @@ -2,7 +2,7 @@ use crate::{ activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_is_public}, activity_lists::AnnouncableActivities, fetcher::object_id::ObjectId, - http::is_activity_already_known, + http::{is_activity_already_known, ActivityCommonFields}, insert_activity, objects::community::ApubCommunity, protocol::activities::community::announce::AnnounceActivity, @@ -10,7 +10,7 @@ use crate::{ use activitystreams::{activity::kind::AnnounceType, public}; use lemmy_apub_lib::{ data::Data, - traits::{ActivityFields, ActivityHandler, ActorType}, + traits::{ActivityHandler, ActorType}, }; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; @@ -60,7 +60,7 @@ impl ActivityHandler for AnnounceActivity { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to)?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; self.object.verify(context, request_counter).await?; Ok(()) } @@ -70,11 +70,15 @@ impl ActivityHandler for AnnounceActivity { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - if is_activity_already_known(context.pool(), self.object.id_unchecked()).await? { + // TODO: this is pretty ugly, but i cant think of a much better way + let object = serde_json::to_string(&self.object)?; + let object_data: ActivityCommonFields = serde_json::from_str(&object)?; + + if is_activity_already_known(context.pool(), &object_data.id).await? { return Ok(()); } insert_activity( - self.object.id_unchecked(), + &object_data.id, self.object.clone(), false, true, diff --git a/crates/apub/src/activities/community/block_user.rs b/crates/apub/src/activities/community/block_user.rs index dfe6c4c92..d756ed251 100644 --- a/crates/apub/src/activities/community/block_user.rs +++ b/crates/apub/src/activities/community/block_user.rs @@ -76,7 +76,7 @@ impl ActivityHandler for BlockUserFromCommunity { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to)?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_mod_action(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/community/remove_mod.rs b/crates/apub/src/activities/community/remove_mod.rs index 02ff3c064..1c79e70d2 100644 --- a/crates/apub/src/activities/community/remove_mod.rs +++ b/crates/apub/src/activities/community/remove_mod.rs @@ -64,7 +64,7 @@ impl ActivityHandler for RemoveMod { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to)?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_mod_action(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/community/report.rs b/crates/apub/src/activities/community/report.rs index 1e7cc5fad..5b02490b0 100644 --- a/crates/apub/src/activities/community/report.rs +++ b/crates/apub/src/activities/community/report.rs @@ -1,5 +1,16 @@ +use crate::{ + activities::{ + generate_activity_id, + send_lemmy_activity, + verify_activity, + verify_person_in_community, + }, + fetcher::object_id::ObjectId, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::activities::community::report::Report, + PostOrComment, +}; use activitystreams::activity::kind::FlagType; - use lemmy_api_common::{blocking, comment::CommentReportResponse, post::PostReportResponse}; use lemmy_apub_lib::{ data::Data, @@ -16,19 +27,6 @@ use lemmy_db_views::{comment_report_view::CommentReportView, post_report_view::P use lemmy_utils::LemmyError; use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation}; -use crate::{ - activities::{ - generate_activity_id, - send_lemmy_activity, - verify_activity, - verify_person_in_community, - }, - fetcher::object_id::ObjectId, - objects::{community::ApubCommunity, person::ApubPerson}, - protocol::activities::community::report::Report, - PostOrComment, -}; - impl Report { pub async fn send( object_id: ObjectId, @@ -72,7 +70,7 @@ impl ActivityHandler for Report { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.to[0].dereference(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; Ok(()) diff --git a/crates/apub/src/activities/community/undo_block_user.rs b/crates/apub/src/activities/community/undo_block_user.rs index 2bda94441..467237eb8 100644 --- a/crates/apub/src/activities/community/undo_block_user.rs +++ b/crates/apub/src/activities/community/undo_block_user.rs @@ -66,7 +66,7 @@ impl ActivityHandler for UndoBlockUserFromCommunity { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to)?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_mod_action(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index 28de0db00..9acb89098 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -59,7 +59,7 @@ impl ActivityHandler for UpdateCommunity { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to)?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_mod_action(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/deletion/delete.rs b/crates/apub/src/activities/deletion/delete.rs index a4112a0af..605daf8ff 100644 --- a/crates/apub/src/activities/deletion/delete.rs +++ b/crates/apub/src/activities/deletion/delete.rs @@ -1,7 +1,22 @@ +use crate::{ + activities::{ + community::{announce::GetCommunity, send_to_community}, + deletion::{ + receive_delete_action, + verify_delete_activity, + DeletableObjects, + }, + generate_activity_id, + verify_activity, + verify_is_public, + }, + activity_lists::AnnouncableActivities, + fetcher::object_id::ObjectId, + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::activities::deletion::delete::Delete, +}; use activitystreams::{activity::kind::DeleteType, public}; use anyhow::anyhow; -use url::Url; - use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, @@ -29,20 +44,7 @@ use lemmy_websocket::{ LemmyContext, UserOperationCrud, }; - -use crate::{ - activities::{ - community::{announce::GetCommunity, send_to_community}, - deletion::{receive_delete_action, verify_delete_activity, DeletableObjects}, - generate_activity_id, - verify_activity, - verify_is_public, - }, - activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, - objects::{community::ApubCommunity, person::ApubPerson}, - protocol::activities::deletion::delete::Delete, -}; +use url::Url; #[async_trait::async_trait(?Send)] impl ActivityHandler for Delete { @@ -53,11 +55,11 @@ impl ActivityHandler for Delete { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to)?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_delete_activity( &self.object, - self, + &self.actor, &community, self.summary.is_some(), context, diff --git a/crates/apub/src/activities/deletion/mod.rs b/crates/apub/src/activities/deletion/mod.rs index 3e9a7a3a2..1be3bccf6 100644 --- a/crates/apub/src/activities/deletion/mod.rs +++ b/crates/apub/src/activities/deletion/mod.rs @@ -1,8 +1,12 @@ -use url::Url; - +use crate::{ + activities::{verify_mod_action, verify_person_in_community}, + fetcher::object_id::ObjectId, + objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost}, + protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete}, +}; use lemmy_api_common::blocking; use lemmy_apub_lib::{ - traits::{ActivityFields, ActorType, ApubObject}, + traits::{ActorType, ApubObject}, verify::verify_domains_match, }; use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post}; @@ -12,13 +16,7 @@ use lemmy_websocket::{ LemmyContext, UserOperationCrud, }; - -use crate::{ - activities::{verify_mod_action, verify_person_in_community}, - fetcher::object_id::ObjectId, - objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost}, - protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete}, -}; +use url::Url; pub mod delete; pub mod undo_delete; @@ -80,27 +78,26 @@ impl DeletableObjects { pub(in crate::activities) async fn verify_delete_activity( object: &Url, - activity: &dyn ActivityFields, + actor: &ObjectId, community: &ApubCommunity, is_mod_action: bool, context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { let object = DeletableObjects::read_from_db(object, context).await?; - let actor = ObjectId::new(activity.actor().clone()); match object { DeletableObjects::Community(community) => { if community.local { // can only do this check for local community, in remote case it would try to fetch the // deleted community (which fails) - verify_person_in_community(&actor, &community, context, request_counter).await?; + verify_person_in_community(actor, &community, context, request_counter).await?; } // community deletion is always a mod (or admin) action - verify_mod_action(&actor, &community, context, request_counter).await?; + verify_mod_action(actor, &community, context, request_counter).await?; } DeletableObjects::Post(p) => { verify_delete_activity_post_or_comment( - activity, + actor, &p.ap_id.clone().into(), community, is_mod_action, @@ -111,7 +108,7 @@ pub(in crate::activities) async fn verify_delete_activity( } DeletableObjects::Comment(c) => { verify_delete_activity_post_or_comment( - activity, + actor, &c.ap_id.clone().into(), community, is_mod_action, @@ -125,20 +122,19 @@ pub(in crate::activities) async fn verify_delete_activity( } async fn verify_delete_activity_post_or_comment( - activity: &dyn ActivityFields, + actor: &ObjectId, object_id: &Url, community: &ApubCommunity, is_mod_action: bool, context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let actor = ObjectId::new(activity.actor().clone()); - verify_person_in_community(&actor, community, context, request_counter).await?; + verify_person_in_community(actor, community, context, request_counter).await?; if is_mod_action { - verify_mod_action(&actor, community, context, request_counter).await?; + verify_mod_action(actor, community, context, request_counter).await?; } else { // domain of post ap_id and post.creator ap_id are identical, so we just check the former - verify_domains_match(activity.actor(), object_id)?; + verify_domains_match(actor.inner(), object_id)?; } Ok(()) } diff --git a/crates/apub/src/activities/deletion/undo_delete.rs b/crates/apub/src/activities/deletion/undo_delete.rs index 2de4aefd3..93338a3f3 100644 --- a/crates/apub/src/activities/deletion/undo_delete.rs +++ b/crates/apub/src/activities/deletion/undo_delete.rs @@ -1,20 +1,3 @@ -use activitystreams::{activity::kind::UndoType, public}; -use anyhow::anyhow; -use url::Url; - -use lemmy_api_common::blocking; -use lemmy_apub_lib::{ - data::Data, - traits::{ActivityHandler, ActorType}, -}; -use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post}; -use lemmy_utils::LemmyError; -use lemmy_websocket::{ - send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message}, - LemmyContext, - UserOperationCrud, -}; - use crate::{ activities::{ community::{announce::GetCommunity, send_to_community}, @@ -28,6 +11,21 @@ use crate::{ objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete}, }; +use activitystreams::{activity::kind::UndoType, public}; +use anyhow::anyhow; +use lemmy_api_common::blocking; +use lemmy_apub_lib::{ + data::Data, + traits::{ActivityHandler, ActorType}, +}; +use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post}; +use lemmy_utils::LemmyError; +use lemmy_websocket::{ + send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message}, + LemmyContext, + UserOperationCrud, +}; +use url::Url; #[async_trait::async_trait(?Send)] impl ActivityHandler for UndoDelete { @@ -38,12 +36,12 @@ impl ActivityHandler for UndoDelete { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to)?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; self.object.verify(context, request_counter).await?; let community = self.get_community(context, request_counter).await?; verify_delete_activity( &self.object.object, - self, + &self.actor, &community, self.object.summary.is_some(), context, diff --git a/crates/apub/src/activities/following/accept.rs b/crates/apub/src/activities/following/accept.rs index 984d622a8..68c8ca454 100644 --- a/crates/apub/src/activities/following/accept.rs +++ b/crates/apub/src/activities/following/accept.rs @@ -7,7 +7,7 @@ use activitystreams::activity::kind::AcceptType; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, - traits::{ActivityFields, ActivityHandler, ActorType}, + traits::{ActivityHandler, ActorType}, verify::verify_urls_match, }; use lemmy_db_schema::{source::community::CommunityFollower, traits::Followable}; @@ -51,9 +51,9 @@ impl ActivityHandler for AcceptFollowCommunity { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_activity(self, &context.settings())?; - verify_urls_match(self.to[0].inner(), self.object.actor())?; - verify_urls_match(self.actor(), self.object.to[0].inner())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; + verify_urls_match(self.to[0].inner(), self.object.actor.inner())?; + verify_urls_match(self.actor.inner(), self.object.to[0].inner())?; self.object.verify(context, request_counter).await?; Ok(()) } diff --git a/crates/apub/src/activities/following/follow.rs b/crates/apub/src/activities/following/follow.rs index e048907fe..30c77fe81 100644 --- a/crates/apub/src/activities/following/follow.rs +++ b/crates/apub/src/activities/following/follow.rs @@ -71,7 +71,7 @@ impl ActivityHandler for FollowCommunity { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; verify_urls_match(self.to[0].inner(), self.object.inner())?; verify_person(&self.actor, context, request_counter).await?; let community = self.to[0].dereference(context, request_counter).await?; diff --git a/crates/apub/src/activities/following/undo_follow.rs b/crates/apub/src/activities/following/undo_follow.rs index c3fd78b51..bdc5a4b09 100644 --- a/crates/apub/src/activities/following/undo_follow.rs +++ b/crates/apub/src/activities/following/undo_follow.rs @@ -8,7 +8,7 @@ use activitystreams::activity::kind::UndoType; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, - traits::{ActivityFields, ActivityHandler, ActorType}, + traits::{ActivityHandler, ActorType}, verify::verify_urls_match, }; use lemmy_db_schema::{ @@ -49,9 +49,9 @@ impl ActivityHandler for UndoFollowCommunity { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; verify_urls_match(self.to[0].inner(), self.object.object.inner())?; - verify_urls_match(self.actor(), self.object.actor())?; + verify_urls_match(self.actor.inner(), self.object.actor.inner())?; verify_person(&self.actor, context, request_counter).await?; self.object.verify(context, request_counter).await?; Ok(()) diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index bc6cfb512..e23926f8c 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -11,7 +11,7 @@ use anyhow::anyhow; use lemmy_api_common::blocking; use lemmy_apub_lib::{ activity_queue::send_activity, - traits::{ActivityFields, ActorType}, + traits::ActorType, verify::verify_domains_match, }; use lemmy_db_schema::source::community::Community; @@ -71,9 +71,9 @@ pub(crate) async fn verify_person_in_community( Ok(()) } -fn verify_activity(activity: &dyn ActivityFields, settings: &Settings) -> Result<(), LemmyError> { - check_is_apub_id_valid(activity.actor(), false, settings)?; - verify_domains_match(activity.id_unchecked(), activity.actor())?; +fn verify_activity(id: &Url, actor: &Url, settings: &Settings) -> Result<(), LemmyError> { + check_is_apub_id_valid(actor, false, settings)?; + verify_domains_match(id, actor)?; Ok(()) } diff --git a/crates/apub/src/activities/post/create_or_update.rs b/crates/apub/src/activities/post/create_or_update.rs index 677ce2dc1..e574dda96 100644 --- a/crates/apub/src/activities/post/create_or_update.rs +++ b/crates/apub/src/activities/post/create_or_update.rs @@ -1,16 +1,3 @@ -use activitystreams::public; -use anyhow::anyhow; - -use lemmy_api_common::blocking; -use lemmy_apub_lib::{ - data::Data, - traits::{ActivityFields, ActivityHandler, ActorType, ApubObject}, - verify::{verify_domains_match, verify_urls_match}, -}; -use lemmy_db_schema::{source::community::Community, traits::Crud}; -use lemmy_utils::LemmyError; -use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud}; - use crate::{ activities::{ check_community_deleted_or_removed, @@ -26,6 +13,17 @@ use crate::{ objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost}, protocol::activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType}, }; +use activitystreams::public; +use anyhow::anyhow; +use lemmy_api_common::blocking; +use lemmy_apub_lib::{ + data::Data, + traits::{ActivityHandler, ActorType, ApubObject}, + verify::{verify_domains_match, verify_urls_match}, +}; +use lemmy_db_schema::{source::community::Community, traits::Crud}; +use lemmy_utils::LemmyError; +use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud}; impl CreateOrUpdatePost { pub(crate) async fn new( @@ -77,7 +75,7 @@ impl ActivityHandler for CreateOrUpdatePost { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to)?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; check_community_deleted_or_removed(&community)?; @@ -85,7 +83,7 @@ impl ActivityHandler for CreateOrUpdatePost { match self.kind { CreateOrUpdateType::Create => { verify_domains_match(self.actor.inner(), self.object.id.inner())?; - verify_urls_match(self.actor(), self.object.attributed_to.inner())?; + verify_urls_match(self.actor.inner(), self.object.attributed_to.inner())?; // Check that the post isnt locked or stickied, as that isnt possible for newly created posts. // However, when fetching a remote post we generate a new create activity with the current // locked/stickied value, so this check may fail. So only check if its a local community, @@ -102,7 +100,7 @@ impl ActivityHandler for CreateOrUpdatePost { verify_mod_action(&self.actor, &community, context, request_counter).await?; } else { verify_domains_match(self.actor.inner(), self.object.id.inner())?; - verify_urls_match(self.actor(), self.object.attributed_to.inner())?; + verify_urls_match(self.actor.inner(), self.object.attributed_to.inner())?; } } } diff --git a/crates/apub/src/activities/private_message/create_or_update.rs b/crates/apub/src/activities/private_message/create_or_update.rs index e441718ab..52b6fa74c 100644 --- a/crates/apub/src/activities/private_message/create_or_update.rs +++ b/crates/apub/src/activities/private_message/create_or_update.rs @@ -54,7 +54,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; verify_person(&self.actor, context, request_counter).await?; verify_domains_match(self.actor.inner(), self.object.id.inner())?; self.object.verify(context, request_counter).await?; diff --git a/crates/apub/src/activities/private_message/delete.rs b/crates/apub/src/activities/private_message/delete.rs index da3b6472d..4547b22b8 100644 --- a/crates/apub/src/activities/private_message/delete.rs +++ b/crates/apub/src/activities/private_message/delete.rs @@ -62,7 +62,7 @@ impl ActivityHandler for DeletePrivateMessage { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; verify_person(&self.actor, context, request_counter).await?; verify_domains_match(self.actor.inner(), self.object.inner())?; Ok(()) diff --git a/crates/apub/src/activities/private_message/undo_delete.rs b/crates/apub/src/activities/private_message/undo_delete.rs index bba9e0f22..1272328b1 100644 --- a/crates/apub/src/activities/private_message/undo_delete.rs +++ b/crates/apub/src/activities/private_message/undo_delete.rs @@ -11,7 +11,7 @@ use activitystreams::activity::kind::UndoType; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, - traits::{ActivityFields, ActivityHandler, ActorType}, + traits::{ActivityHandler, ActorType}, verify::{verify_domains_match, verify_urls_match}, }; use lemmy_db_schema::{ @@ -59,10 +59,10 @@ impl ActivityHandler for UndoDeletePrivateMessage { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; verify_person(&self.actor, context, request_counter).await?; - verify_urls_match(self.actor(), self.object.actor())?; - verify_domains_match(self.actor(), self.object.object.inner())?; + verify_urls_match(self.actor.inner(), self.object.actor.inner())?; + verify_domains_match(self.actor.inner(), self.object.object.inner())?; self.object.verify(context, request_counter).await?; Ok(()) } diff --git a/crates/apub/src/activities/voting/undo_vote.rs b/crates/apub/src/activities/voting/undo_vote.rs index e95d25179..786d51192 100644 --- a/crates/apub/src/activities/voting/undo_vote.rs +++ b/crates/apub/src/activities/voting/undo_vote.rs @@ -1,17 +1,3 @@ -use std::ops::Deref; - -use activitystreams::{activity::kind::UndoType, public}; - -use lemmy_api_common::blocking; -use lemmy_apub_lib::{ - data::Data, - traits::{ActivityFields, ActivityHandler, ActorType}, - verify::verify_urls_match, -}; -use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud}; -use lemmy_utils::LemmyError; -use lemmy_websocket::LemmyContext; - use crate::{ activities::{ community::{announce::GetCommunity, send_to_community}, @@ -30,6 +16,17 @@ use crate::{ }, PostOrComment, }; +use activitystreams::{activity::kind::UndoType, public}; +use lemmy_api_common::blocking; +use lemmy_apub_lib::{ + data::Data, + traits::{ActivityHandler, ActorType}, + verify::verify_urls_match, +}; +use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud}; +use lemmy_utils::LemmyError; +use lemmy_websocket::LemmyContext; +use std::ops::Deref; impl UndoVote { pub async fn send( @@ -73,10 +70,10 @@ impl ActivityHandler for UndoVote { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to)?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; - verify_urls_match(self.actor(), self.object.actor())?; + verify_urls_match(self.actor.inner(), self.object.actor.inner())?; self.object.verify(context, request_counter).await?; Ok(()) } diff --git a/crates/apub/src/activities/voting/vote.rs b/crates/apub/src/activities/voting/vote.rs index 01df4b93e..82b9b84e9 100644 --- a/crates/apub/src/activities/voting/vote.rs +++ b/crates/apub/src/activities/voting/vote.rs @@ -1,20 +1,3 @@ -use std::ops::Deref; - -use activitystreams::public; - -use lemmy_api_common::blocking; -use lemmy_apub_lib::{ - data::Data, - traits::{ActivityHandler, ActorType}, -}; -use lemmy_db_schema::{ - newtypes::CommunityId, - source::{community::Community, post::Post}, - traits::Crud, -}; -use lemmy_utils::LemmyError; -use lemmy_websocket::LemmyContext; - use crate::{ activities::{ community::{announce::GetCommunity, send_to_community}, @@ -30,6 +13,20 @@ use crate::{ protocol::activities::voting::vote::{Vote, VoteType}, PostOrComment, }; +use activitystreams::public; +use lemmy_api_common::blocking; +use lemmy_apub_lib::{ + data::Data, + traits::{ActivityHandler, ActorType}, +}; +use lemmy_db_schema::{ + newtypes::CommunityId, + source::{community::Community, post::Post}, + traits::Crud, +}; +use lemmy_utils::LemmyError; +use lemmy_websocket::LemmyContext; +use std::ops::Deref; impl Vote { pub(in crate::activities::voting) fn new( @@ -79,7 +76,7 @@ impl ActivityHandler for Vote { request_counter: &mut i32, ) -> Result<(), LemmyError> { verify_is_public(&self.to)?; - verify_activity(self, &context.settings())?; + verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; Ok(()) diff --git a/crates/apub/src/activity_lists.rs b/crates/apub/src/activity_lists.rs index 1197af85f..6c866b83b 100644 --- a/crates/apub/src/activity_lists.rs +++ b/crates/apub/src/activity_lists.rs @@ -26,12 +26,12 @@ use crate::{ voting::{undo_vote::UndoVote, vote::Vote}, }, }; -use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler}; +use lemmy_apub_lib::traits::ActivityHandler; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] #[serde(untagged)] #[activity_handler(LemmyContext)] pub enum SharedInboxActivities { @@ -41,7 +41,7 @@ pub enum SharedInboxActivities { PersonInboxActivities(PersonInboxActivities), } -#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] #[serde(untagged)] #[activity_handler(LemmyContext)] pub enum GroupInboxActivities { @@ -51,7 +51,7 @@ pub enum GroupInboxActivities { Report(Report), } -#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] #[serde(untagged)] #[activity_handler(LemmyContext)] pub enum PersonInboxActivities { @@ -64,7 +64,7 @@ pub enum PersonInboxActivities { AnnounceActivity(Box), } -#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] #[serde(untagged)] #[activity_handler(LemmyContext)] pub enum AnnouncableActivities { diff --git a/crates/apub/src/fetcher/mod.rs b/crates/apub/src/fetcher/mod.rs index db39d2282..8246f4ce6 100644 --- a/crates/apub/src/fetcher/mod.rs +++ b/crates/apub/src/fetcher/mod.rs @@ -1,44 +1,14 @@ pub mod object_id; pub mod post_or_comment; pub mod search; +pub mod user_or_community; -use crate::{ - fetcher::object_id::ObjectId, - objects::{community::ApubCommunity, person::ApubPerson}, -}; use chrono::NaiveDateTime; -use lemmy_apub_lib::traits::ActorType; use lemmy_db_schema::naive_now; -use lemmy_utils::LemmyError; -use lemmy_websocket::LemmyContext; -use url::Url; static ACTOR_REFETCH_INTERVAL_SECONDS: i64 = 24 * 60 * 60; static ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG: i64 = 10; -/// Get a remote actor from its apub ID (either a person or a community). Thin wrapper around -/// `get_or_fetch_and_upsert_person()` and `get_or_fetch_and_upsert_community()`. -/// -/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database. -/// Otherwise it is fetched from the remote instance, stored and returned. -pub(crate) async fn get_or_fetch_and_upsert_actor( - apub_id: Url, - context: &LemmyContext, - recursion_counter: &mut i32, -) -> Result, LemmyError> { - let community_id = ObjectId::::new(apub_id.clone()); - let community = community_id.dereference(context, recursion_counter).await; - let actor: Box = match community { - Ok(c) => Box::new(c), - Err(_) => { - let person_id = ObjectId::new(apub_id); - let person: ApubPerson = person_id.dereference(context, recursion_counter).await?; - Box::new(person) - } - }; - Ok(actor) -} - /// Determines when a remote actor should be refetched from its instance. In release builds, this is /// `ACTOR_REFETCH_INTERVAL_SECONDS` after the last refetch, in debug builds /// `ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG`. diff --git a/crates/apub/src/fetcher/post_or_comment.rs b/crates/apub/src/fetcher/post_or_comment.rs index c0bc46a81..ef4e59e1d 100644 --- a/crates/apub/src/fetcher/post_or_comment.rs +++ b/crates/apub/src/fetcher/post_or_comment.rs @@ -1,16 +1,13 @@ -use chrono::NaiveDateTime; -use serde::Deserialize; -use url::Url; - -use lemmy_apub_lib::traits::ApubObject; -use lemmy_db_schema::source::{comment::CommentForm, post::PostForm}; -use lemmy_utils::LemmyError; -use lemmy_websocket::LemmyContext; - use crate::{ objects::{comment::ApubComment, post::ApubPost}, protocol::objects::{note::Note, page::Page}, }; +use chrono::NaiveDateTime; +use lemmy_apub_lib::traits::ApubObject; +use lemmy_utils::LemmyError; +use lemmy_websocket::LemmyContext; +use serde::Deserialize; +use url::Url; #[derive(Clone, Debug)] pub enum PostOrComment { @@ -18,11 +15,6 @@ pub enum PostOrComment { Comment(ApubComment), } -pub enum PostOrCommentForm { - PostForm(Box), - CommentForm(CommentForm), -} - #[derive(Deserialize)] #[serde(untagged)] pub enum PageOrNote { @@ -44,10 +36,7 @@ impl ApubObject for PostOrComment { async fn read_from_apub_id( object_id: Url, data: &Self::DataType, - ) -> Result, LemmyError> - where - Self: Sized, - { + ) -> Result, LemmyError> { let post = ApubPost::read_from_apub_id(object_id.clone(), data).await?; Ok(match post { Some(o) => Some(PostOrComment::Post(Box::new(o))), @@ -77,10 +66,7 @@ impl ApubObject for PostOrComment { context: &LemmyContext, expected_domain: &Url, request_counter: &mut i32, - ) -> Result - where - Self: Sized, - { + ) -> Result { Ok(match apub { PageOrNote::Page(p) => PostOrComment::Post(Box::new( ApubPost::from_apub(p, context, expected_domain, request_counter).await?, diff --git a/crates/apub/src/fetcher/user_or_community.rs b/crates/apub/src/fetcher/user_or_community.rs new file mode 100644 index 000000000..16a1d8220 --- /dev/null +++ b/crates/apub/src/fetcher/user_or_community.rs @@ -0,0 +1,113 @@ +use crate::{ + objects::{community::ApubCommunity, person::ApubPerson}, + protocol::objects::{group::Group, person::Person}, +}; +use activitystreams::{chrono::NaiveDateTime, url::Url}; +use lemmy_apub_lib::traits::{ActorType, ApubObject}; +use lemmy_utils::LemmyError; +use lemmy_websocket::LemmyContext; +use serde::Deserialize; + +#[derive(Clone, Debug)] +pub enum UserOrCommunity { + User(ApubPerson), + Community(ApubCommunity), +} + +#[derive(Deserialize)] +#[serde(untagged)] +pub enum PersonOrGroup { + Person(Person), + Group(Group), +} + +#[async_trait::async_trait(?Send)] +impl ApubObject for UserOrCommunity { + type DataType = LemmyContext; + type ApubType = PersonOrGroup; + type TombstoneType = (); + + fn last_refreshed_at(&self) -> Option { + Some(match self { + UserOrCommunity::User(p) => p.last_refreshed_at, + UserOrCommunity::Community(p) => p.last_refreshed_at, + }) + } + + async fn read_from_apub_id( + object_id: Url, + data: &Self::DataType, + ) -> Result, LemmyError> { + let person = ApubPerson::read_from_apub_id(object_id.clone(), data).await?; + Ok(match person { + Some(o) => Some(UserOrCommunity::User(o)), + None => ApubCommunity::read_from_apub_id(object_id, data) + .await? + .map(UserOrCommunity::Community), + }) + } + + async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> { + match self { + UserOrCommunity::User(p) => p.delete(data).await, + UserOrCommunity::Community(p) => p.delete(data).await, + } + } + + async fn to_apub(&self, _data: &Self::DataType) -> Result { + unimplemented!() + } + + fn to_tombstone(&self) -> Result { + unimplemented!() + } + + async fn from_apub( + apub: &Self::ApubType, + data: &Self::DataType, + expected_domain: &Url, + request_counter: &mut i32, + ) -> Result { + Ok(match apub { + PersonOrGroup::Person(p) => UserOrCommunity::User( + ApubPerson::from_apub(p, data, expected_domain, request_counter).await?, + ), + PersonOrGroup::Group(p) => UserOrCommunity::Community( + ApubCommunity::from_apub(p, data, expected_domain, request_counter).await?, + ), + }) + } +} + +impl ActorType for UserOrCommunity { + fn is_local(&self) -> bool { + todo!() + } + + fn actor_id(&self) -> Url { + todo!() + } + + fn name(&self) -> String { + todo!() + } + + fn public_key(&self) -> Option { + match self { + UserOrCommunity::User(p) => p.public_key(), + UserOrCommunity::Community(p) => p.public_key(), + } + } + + fn private_key(&self) -> Option { + todo!() + } + + fn inbox_url(&self) -> Url { + todo!() + } + + fn shared_inbox_url(&self) -> Option { + todo!() + } +} diff --git a/crates/apub/src/http/community.rs b/crates/apub/src/http/community.rs index 4110d2b20..c208f71ed 100644 --- a/crates/apub/src/http/community.rs +++ b/crates/apub/src/http/community.rs @@ -14,6 +14,7 @@ use crate::{ create_apub_tombstone_response, payload_to_string, receive_activity, + ActivityCommonFields, }, objects::community::ApubCommunity, protocol::{ @@ -23,7 +24,7 @@ use crate::{ }; use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse}; use lemmy_api_common::blocking; -use lemmy_apub_lib::traits::{ActivityFields, ApubObject}; +use lemmy_apub_lib::traits::ApubObject; use lemmy_db_schema::source::community::Community; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; @@ -64,23 +65,25 @@ pub async fn community_inbox( ) -> Result { let unparsed = payload_to_string(payload).await?; info!("Received community inbox activity {}", unparsed); + let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?; let activity = serde_json::from_str::>(&unparsed)?; - receive_group_inbox(activity.inner(), request, &context).await?; + receive_group_inbox(activity.inner(), activity_data, request, &context).await?; Ok(HttpResponse::Ok().finish()) } pub(in crate::http) async fn receive_group_inbox( activity: GroupInboxActivities, + activity_data: ActivityCommonFields, request: HttpRequest, context: &LemmyContext, ) -> Result { - let res = receive_activity(request, activity.clone(), context).await; + let actor_id = ObjectId::new(activity_data.actor.clone()); + let res = receive_activity(request, activity.clone(), activity_data, context).await; if let GroupInboxActivities::AnnouncableActivities(announcable) = activity { let community = announcable.get_community(context, &mut 0).await?; - let actor_id = ObjectId::new(announcable.actor().clone()); verify_person_in_community(&actor_id, &community, context, &mut 0).await?; if community.local { AnnounceActivity::send(announcable, &community, vec![], context).await?; diff --git a/crates/apub/src/http/mod.rs b/crates/apub/src/http/mod.rs index 9c61c2747..450b937d5 100644 --- a/crates/apub/src/http/mod.rs +++ b/crates/apub/src/http/mod.rs @@ -2,7 +2,7 @@ use crate::{ activity_lists::SharedInboxActivities, check_is_apub_id_valid, context::WithContext, - fetcher::get_or_fetch_and_upsert_actor, + fetcher::{object_id::ObjectId, user_or_community::UserOrCommunity}, http::{community::receive_group_inbox, person::receive_person_inbox}, insert_activity, }; @@ -20,7 +20,7 @@ use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, signatures::verify_signature, - traits::{ActivityFields, ActivityHandler}, + traits::{ActivityHandler, ActorType}, APUB_JSON_CONTENT_TYPE, }; use lemmy_db_schema::{source::activity::Activity, DbPool}; @@ -44,13 +44,14 @@ pub async fn shared_inbox( ) -> Result { let unparsed = payload_to_string(payload).await?; info!("Received shared inbox activity {}", unparsed); + let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?; let activity = serde_json::from_str::>(&unparsed)?; match activity.inner() { SharedInboxActivities::GroupInboxActivities(g) => { - receive_group_inbox(g, request, &context).await + receive_group_inbox(g, activity_data, request, &context).await } SharedInboxActivities::PersonInboxActivities(p) => { - receive_person_inbox(p, request, &context).await + receive_person_inbox(p, activity_data, request, &context).await } } } @@ -65,15 +66,22 @@ async fn payload_to_string(mut payload: Payload) -> Result { Ok(unparsed) } +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct ActivityCommonFields { + pub(crate) id: Url, + pub(crate) actor: Url, +} + // TODO: move most of this code to library async fn receive_activity<'a, T>( request: HttpRequest, activity: T, + activity_data: ActivityCommonFields, context: &LemmyContext, ) -> Result where T: ActivityHandler - + ActivityFields + Clone + Deserialize<'a> + Serialize @@ -81,26 +89,27 @@ where + Send + 'static, { + check_is_apub_id_valid(&activity_data.actor, false, &context.settings())?; let request_counter = &mut 0; - let actor = - get_or_fetch_and_upsert_actor(activity.actor().clone(), context, request_counter).await?; + let actor = ObjectId::::new(activity_data.actor) + .dereference(context, request_counter) + .await?; verify_signature(&request, &actor.public_key().context(location_info!())?)?; // Do nothing if we received the same activity before - if is_activity_already_known(context.pool(), activity.id_unchecked()).await? { + if is_activity_already_known(context.pool(), &activity_data.id).await? { return Ok(HttpResponse::Ok().finish()); } - check_is_apub_id_valid(activity.actor(), false, &context.settings())?; - info!("Verifying activity {}", activity.id_unchecked().to_string()); + info!("Verifying activity {}", activity_data.id.to_string()); activity .verify(&Data::new(context.clone()), request_counter) .await?; - assert_activity_not_local(&activity, &context.settings().hostname)?; + assert_activity_not_local(&activity_data.id, &context.settings().hostname)?; // Log the activity, so we avoid receiving and parsing it twice. Note that this could still happen // if we receive the same activity twice in very quick succession. insert_activity( - activity.id_unchecked(), + &activity_data.id, activity.clone(), false, true, @@ -108,7 +117,7 @@ where ) .await?; - info!("Receiving activity {}", activity.id_unchecked().to_string()); + info!("Receiving activity {}", activity_data.id.to_string()); activity .receive(&Data::new(context.clone()), request_counter) .await?; @@ -183,17 +192,14 @@ pub(crate) async fn is_activity_already_known( } } -fn assert_activity_not_local( - activity: &T, - hostname: &str, -) -> Result<(), LemmyError> { - let activity_domain = activity.id_unchecked().domain().context(location_info!())?; +fn assert_activity_not_local(id: &Url, hostname: &str) -> Result<(), LemmyError> { + let activity_domain = id.domain().context(location_info!())?; if activity_domain == hostname { return Err( anyhow!( "Error: received activity which was sent by local instance: {:?}", - activity + id ) .into(), ); diff --git a/crates/apub/src/http/person.rs b/crates/apub/src/http/person.rs index a5ea4ad17..193689c5e 100644 --- a/crates/apub/src/http/person.rs +++ b/crates/apub/src/http/person.rs @@ -6,6 +6,7 @@ use crate::{ create_apub_tombstone_response, payload_to_string, receive_activity, + ActivityCommonFields, }, objects::person::ApubPerson, protocol::collections::person_outbox::PersonOutbox, @@ -54,16 +55,18 @@ pub async fn person_inbox( ) -> Result { let unparsed = payload_to_string(payload).await?; info!("Received person inbox activity {}", unparsed); + let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?; let activity = serde_json::from_str::>(&unparsed)?; - receive_person_inbox(activity.inner(), request, &context).await + receive_person_inbox(activity.inner(), activity_data, request, &context).await } pub(in crate::http) async fn receive_person_inbox( activity: PersonInboxActivities, + activity_data: ActivityCommonFields, request: HttpRequest, context: &LemmyContext, ) -> Result { - receive_activity(request, activity, context).await + receive_activity(request, activity, activity_data, context).await } pub(crate) async fn get_apub_person_outbox( diff --git a/crates/apub/src/protocol/activities/community/add_mod.rs b/crates/apub/src/protocol/activities/community/add_mod.rs index 74ec46457..6938f01d4 100644 --- a/crates/apub/src/protocol/activities/community/add_mod.rs +++ b/crates/apub/src/protocol/activities/community/add_mod.rs @@ -1,10 +1,9 @@ use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson}; use activitystreams::{activity::kind::AddType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct AddMod { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/community/announce.rs b/crates/apub/src/protocol/activities/community/announce.rs index 2f4e9bd26..07fbda635 100644 --- a/crates/apub/src/protocol/activities/community/announce.rs +++ b/crates/apub/src/protocol/activities/community/announce.rs @@ -4,11 +4,10 @@ use crate::{ objects::community::ApubCommunity, }; use activitystreams::{activity::kind::AnnounceType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct AnnounceActivity { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/community/block_user.rs b/crates/apub/src/protocol/activities/community/block_user.rs index 4ede06ae1..ec95e6e9b 100644 --- a/crates/apub/src/protocol/activities/community/block_user.rs +++ b/crates/apub/src/protocol/activities/community/block_user.rs @@ -3,11 +3,10 @@ use crate::{ objects::{community::ApubCommunity, person::ApubPerson}, }; use activitystreams::{activity::kind::BlockType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct BlockUserFromCommunity { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/community/remove_mod.rs b/crates/apub/src/protocol/activities/community/remove_mod.rs index db30ddbe4..cca263549 100644 --- a/crates/apub/src/protocol/activities/community/remove_mod.rs +++ b/crates/apub/src/protocol/activities/community/remove_mod.rs @@ -1,10 +1,9 @@ use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson}; use activitystreams::{activity::kind::RemoveType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct RemoveMod { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/community/report.rs b/crates/apub/src/protocol/activities/community/report.rs index 5efdd792e..d10a9d285 100644 --- a/crates/apub/src/protocol/activities/community/report.rs +++ b/crates/apub/src/protocol/activities/community/report.rs @@ -3,11 +3,10 @@ use crate::{ objects::{community::ApubCommunity, person::ApubPerson}, }; use activitystreams::{activity::kind::FlagType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Report { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/community/undo_block_user.rs b/crates/apub/src/protocol/activities/community/undo_block_user.rs index 0e89f87ef..24356fab2 100644 --- a/crates/apub/src/protocol/activities/community/undo_block_user.rs +++ b/crates/apub/src/protocol/activities/community/undo_block_user.rs @@ -4,11 +4,10 @@ use crate::{ protocol::activities::community::block_user::BlockUserFromCommunity, }; use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct UndoBlockUserFromCommunity { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/community/update.rs b/crates/apub/src/protocol/activities/community/update.rs index 4ba1ed843..686938aa4 100644 --- a/crates/apub/src/protocol/activities/community/update.rs +++ b/crates/apub/src/protocol/activities/community/update.rs @@ -4,13 +4,12 @@ use crate::{ protocol::objects::group::Group, }; use activitystreams::{activity::kind::UpdateType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; /// This activity is received from a remote community mod, and updates the description or other /// fields of a local community. -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct UpdateCommunity { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/create_or_update/comment.rs b/crates/apub/src/protocol/activities/create_or_update/comment.rs index ede7417bc..4e5b412d7 100644 --- a/crates/apub/src/protocol/activities/create_or_update/comment.rs +++ b/crates/apub/src/protocol/activities/create_or_update/comment.rs @@ -4,11 +4,10 @@ use crate::{ protocol::{activities::CreateOrUpdateType, objects::note::Note}, }; use activitystreams::{link::Mention, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct CreateOrUpdateComment { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/create_or_update/post.rs b/crates/apub/src/protocol/activities/create_or_update/post.rs index 03b283e3c..b1851c0d9 100644 --- a/crates/apub/src/protocol/activities/create_or_update/post.rs +++ b/crates/apub/src/protocol/activities/create_or_update/post.rs @@ -4,11 +4,10 @@ use crate::{ protocol::{activities::CreateOrUpdateType, objects::page::Page}, }; use activitystreams::unparsed::Unparsed; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct CreateOrUpdatePost { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/deletion/delete.rs b/crates/apub/src/protocol/activities/deletion/delete.rs index f8e81b47a..af5022799 100644 --- a/crates/apub/src/protocol/activities/deletion/delete.rs +++ b/crates/apub/src/protocol/activities/deletion/delete.rs @@ -1,12 +1,11 @@ use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson}; use activitystreams::{activity::kind::DeleteType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; use url::Url; #[skip_serializing_none] -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Delete { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/deletion/undo_delete.rs b/crates/apub/src/protocol/activities/deletion/undo_delete.rs index d962820b3..8a30546e5 100644 --- a/crates/apub/src/protocol/activities/deletion/undo_delete.rs +++ b/crates/apub/src/protocol/activities/deletion/undo_delete.rs @@ -1,16 +1,13 @@ -use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; -use serde::{Deserialize, Serialize}; -use url::Url; - -use lemmy_apub_lib::traits::ActivityFields; - use crate::{ fetcher::object_id::ObjectId, objects::person::ApubPerson, protocol::activities::deletion::delete::Delete, }; +use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; +use serde::{Deserialize, Serialize}; +use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct UndoDelete { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/following/accept.rs b/crates/apub/src/protocol/activities/following/accept.rs index 502a908c2..7eeb3a418 100644 --- a/crates/apub/src/protocol/activities/following/accept.rs +++ b/crates/apub/src/protocol/activities/following/accept.rs @@ -4,11 +4,10 @@ use crate::{ protocol::activities::following::follow::FollowCommunity, }; use activitystreams::{activity::kind::AcceptType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct AcceptFollowCommunity { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/following/follow.rs b/crates/apub/src/protocol/activities/following/follow.rs index 9dfec2163..651ab1d2d 100644 --- a/crates/apub/src/protocol/activities/following/follow.rs +++ b/crates/apub/src/protocol/activities/following/follow.rs @@ -3,11 +3,10 @@ use crate::{ objects::{community::ApubCommunity, person::ApubPerson}, }; use activitystreams::{activity::kind::FollowType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct FollowCommunity { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/following/undo_follow.rs b/crates/apub/src/protocol/activities/following/undo_follow.rs index be6a7ab89..3abeabd29 100644 --- a/crates/apub/src/protocol/activities/following/undo_follow.rs +++ b/crates/apub/src/protocol/activities/following/undo_follow.rs @@ -4,11 +4,10 @@ use crate::{ protocol::activities::following::follow::FollowCommunity, }; use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct UndoFollowCommunity { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/private_message/create_or_update.rs b/crates/apub/src/protocol/activities/private_message/create_or_update.rs index 7632ef9fe..5092a1640 100644 --- a/crates/apub/src/protocol/activities/private_message/create_or_update.rs +++ b/crates/apub/src/protocol/activities/private_message/create_or_update.rs @@ -4,11 +4,10 @@ use crate::{ protocol::{activities::CreateOrUpdateType, objects::chat_message::ChatMessage}, }; use activitystreams::unparsed::Unparsed; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct CreateOrUpdatePrivateMessage { pub(crate) id: Url, diff --git a/crates/apub/src/protocol/activities/private_message/delete.rs b/crates/apub/src/protocol/activities/private_message/delete.rs index 499d7d1d6..87da3c310 100644 --- a/crates/apub/src/protocol/activities/private_message/delete.rs +++ b/crates/apub/src/protocol/activities/private_message/delete.rs @@ -3,11 +3,10 @@ use crate::{ objects::{person::ApubPerson, private_message::ApubPrivateMessage}, }; use activitystreams::{activity::kind::DeleteType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct DeletePrivateMessage { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/private_message/undo_delete.rs b/crates/apub/src/protocol/activities/private_message/undo_delete.rs index 699f6eec9..16d82492c 100644 --- a/crates/apub/src/protocol/activities/private_message/undo_delete.rs +++ b/crates/apub/src/protocol/activities/private_message/undo_delete.rs @@ -4,11 +4,10 @@ use crate::{ protocol::activities::private_message::delete::DeletePrivateMessage, }; use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; -use lemmy_apub_lib::traits::ActivityFields; use serde::{Deserialize, Serialize}; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct UndoDeletePrivateMessage { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/voting/undo_vote.rs b/crates/apub/src/protocol/activities/voting/undo_vote.rs index 0d3e66360..05606dbe9 100644 --- a/crates/apub/src/protocol/activities/voting/undo_vote.rs +++ b/crates/apub/src/protocol/activities/voting/undo_vote.rs @@ -1,16 +1,13 @@ -use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; -use serde::{Deserialize, Serialize}; -use url::Url; - -use lemmy_apub_lib::traits::ActivityFields; - use crate::{ fetcher::object_id::ObjectId, objects::person::ApubPerson, protocol::activities::voting::vote::Vote, }; +use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; +use serde::{Deserialize, Serialize}; +use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct UndoVote { pub(crate) actor: ObjectId, diff --git a/crates/apub/src/protocol/activities/voting/vote.rs b/crates/apub/src/protocol/activities/voting/vote.rs index fdc87a3bd..6d82ccc42 100644 --- a/crates/apub/src/protocol/activities/voting/vote.rs +++ b/crates/apub/src/protocol/activities/voting/vote.rs @@ -4,14 +4,13 @@ use crate::{ }; use activitystreams::unparsed::Unparsed; use anyhow::anyhow; -use lemmy_apub_lib::traits::ActivityFields; use lemmy_utils::LemmyError; use serde::{Deserialize, Serialize}; use std::convert::TryFrom; use strum_macros::ToString; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Vote { pub(crate) actor: ObjectId, diff --git a/crates/apub_lib/src/traits.rs b/crates/apub_lib/src/traits.rs index 8d819a27b..2d5424082 100644 --- a/crates/apub_lib/src/traits.rs +++ b/crates/apub_lib/src/traits.rs @@ -5,11 +5,6 @@ pub use lemmy_apub_lib_derive::*; use lemmy_utils::{location_info, LemmyError}; use url::Url; -pub trait ActivityFields { - fn id_unchecked(&self) -> &Url; - fn actor(&self) -> &Url; -} - #[async_trait::async_trait(?Send)] pub trait ActivityHandler { type DataType; diff --git a/crates/apub_lib_derive/src/lib.rs b/crates/apub_lib_derive/src/lib.rs index 1f8d12a7d..72e00fe2b 100644 --- a/crates/apub_lib_derive/src/lib.rs +++ b/crates/apub_lib_derive/src/lib.rs @@ -127,40 +127,3 @@ fn generate_match_arm(enum_name: &Ident, variant: &Variant, body: &TokenStream) _ => unimplemented!(), } } - -#[proc_macro_derive(ActivityFields)] -pub fn derive_activity_fields(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - - let name = input.ident; - - let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - - let expanded = match input.data { - Data::Enum(e) => { - let variants = e.variants; - let impl_id = variants - .iter() - .map(|v| generate_match_arm(&name, v, "e! {a.id_unchecked()})); - let impl_actor = variants - .iter() - .map(|v| generate_match_arm(&name, v, "e! {a.actor()})); - quote! { - impl #impl_generics lemmy_apub_lib::traits::ActivityFields for #name #ty_generics #where_clause { - fn id_unchecked(&self) -> &url::Url { match self { #(#impl_id)* } } - fn actor(&self) -> &url::Url { match self { #(#impl_actor)* } } - } - } - } - Data::Struct(_) => { - quote! { - impl #impl_generics lemmy_apub_lib::traits::ActivityFields for #name #ty_generics #where_clause { - fn id_unchecked(&self) -> &url::Url { &self.id } - fn actor(&self) -> &url::Url { &self.actor.inner() } - } - } - } - _ => unimplemented!(), - }; - expanded.into() -} From 2edf8ba1576d67234d1129cd97b131c0654a54f7 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Fri, 5 Nov 2021 01:24:10 +0100 Subject: [PATCH 03/10] Move ObjectId to library --- Cargo.lock | 2 + crates/api/src/comment_report.rs | 7 ++- crates/api/src/post_report.rs | 7 ++- crates/api_crud/src/community/create.rs | 2 +- crates/api_crud/src/community/read.rs | 8 +--- crates/api_crud/src/post/create.rs | 15 +++--- crates/api_crud/src/user/read.rs | 8 +--- .../activities/comment/create_or_update.rs | 2 +- crates/apub/src/activities/comment/mod.rs | 7 +-- .../apub/src/activities/community/add_mod.rs | 2 +- .../apub/src/activities/community/announce.rs | 4 +- .../src/activities/community/block_user.rs | 2 +- crates/apub/src/activities/community/mod.rs | 3 +- .../src/activities/community/remove_mod.rs | 2 +- .../apub/src/activities/community/report.rs | 2 +- .../activities/community/undo_block_user.rs | 2 +- .../apub/src/activities/community/update.rs | 2 +- crates/apub/src/activities/deletion/delete.rs | 8 +--- crates/apub/src/activities/deletion/mod.rs | 2 +- .../src/activities/deletion/undo_delete.rs | 2 +- .../apub/src/activities/following/accept.rs | 2 +- .../apub/src/activities/following/follow.rs | 2 +- .../src/activities/following/undo_follow.rs | 2 +- crates/apub/src/activities/mod.rs | 4 +- .../src/activities/post/create_or_update.rs | 2 +- .../private_message/create_or_update.rs | 2 +- .../src/activities/private_message/delete.rs | 2 +- .../activities/private_message/undo_delete.rs | 2 +- .../apub/src/activities/voting/undo_vote.rs | 2 +- crates/apub/src/activities/voting/vote.rs | 2 +- .../src/collections/community_moderators.rs | 7 ++- .../apub/src/collections/community_outbox.rs | 22 ++++----- crates/apub/src/fetcher/mod.rs | 23 ---------- crates/apub/src/fetcher/search.rs | 16 +++---- crates/apub/src/http/community.rs | 7 ++- crates/apub/src/http/mod.rs | 3 +- crates/apub/src/objects/comment.rs | 46 +++++++++---------- crates/apub/src/objects/community.rs | 33 +++++++------ crates/apub/src/objects/person.rs | 8 ++-- crates/apub/src/objects/post.rs | 4 +- crates/apub/src/objects/private_message.rs | 14 +++--- .../protocol/activities/community/add_mod.rs | 3 +- .../protocol/activities/community/announce.rs | 7 +-- .../activities/community/block_user.rs | 6 +-- .../activities/community/remove_mod.rs | 3 +- .../protocol/activities/community/report.rs | 3 +- .../activities/community/undo_block_user.rs | 2 +- .../protocol/activities/community/update.rs | 7 +-- .../activities/create_or_update/comment.rs | 2 +- .../activities/create_or_update/post.rs | 2 +- .../protocol/activities/deletion/delete.rs | 3 +- .../activities/deletion/undo_delete.rs | 7 +-- .../protocol/activities/following/accept.rs | 2 +- .../protocol/activities/following/follow.rs | 6 +-- .../activities/following/undo_follow.rs | 2 +- .../private_message/create_or_update.rs | 2 +- .../activities/private_message/delete.rs | 6 +-- .../activities/private_message/undo_delete.rs | 2 +- .../protocol/activities/voting/undo_vote.rs | 7 +-- .../src/protocol/activities/voting/vote.rs | 6 +-- .../protocol/collections/group_followers.rs | 2 +- .../protocol/collections/group_moderators.rs | 3 +- .../src/protocol/collections/person_outbox.rs | 2 +- .../apub/src/protocol/objects/chat_message.rs | 3 +- crates/apub/src/protocol/objects/group.rs | 4 +- crates/apub/src/protocol/objects/note.rs | 4 +- crates/apub/src/protocol/objects/page.rs | 3 +- crates/apub/src/protocol/objects/person.rs | 3 +- crates/apub_lib/Cargo.toml | 1 + crates/apub_lib/src/lib.rs | 1 + .../src/fetcher => apub_lib/src}/object_id.rs | 46 +++++++++++++++---- crates/db_schema/Cargo.toml | 1 + crates/db_schema/src/newtypes.rs | 32 +++++++------ 73 files changed, 222 insertions(+), 255 deletions(-) rename crates/{apub/src/fetcher => apub_lib/src}/object_id.rs (74%) diff --git a/Cargo.lock b/Cargo.lock index d41277520..8fb762939 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1869,6 +1869,7 @@ dependencies = [ "async-trait", "background-jobs", "base64 0.13.0", + "diesel", "http", "http-signature-normalization-actix", "http-signature-normalization-reqwest", @@ -1904,6 +1905,7 @@ dependencies = [ "diesel-derive-newtype", "diesel_migrations", "lazy_static", + "lemmy_apub_lib", "lemmy_utils", "log", "regex", diff --git a/crates/api/src/comment_report.rs b/crates/api/src/comment_report.rs index 82ecc1f44..f1bf7023c 100644 --- a/crates/api/src/comment_report.rs +++ b/crates/api/src/comment_report.rs @@ -1,5 +1,5 @@ +use crate::Perform; use actix_web::web::Data; - use lemmy_api_common::{ blocking, check_community_ban, @@ -7,7 +7,8 @@ use lemmy_api_common::{ get_local_user_view_from_jwt, is_mod_or_admin, }; -use lemmy_apub::{fetcher::object_id::ObjectId, protocol::activities::community::report::Report}; +use lemmy_apub::protocol::activities::community::report::Report; +use lemmy_apub_lib::object_id::ObjectId; use lemmy_db_schema::{source::comment_report::*, traits::Reportable}; use lemmy_db_views::{ comment_report_view::{CommentReportQueryBuilder, CommentReportView}, @@ -16,8 +17,6 @@ use lemmy_db_views::{ use lemmy_utils::{ApiError, ConnectionId, LemmyError}; use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation}; -use crate::Perform; - /// Creates a comment report and notifies the moderators of the community #[async_trait::async_trait(?Send)] impl Perform for CreateCommentReport { diff --git a/crates/api/src/post_report.rs b/crates/api/src/post_report.rs index 98b2f1c11..0e47f592d 100644 --- a/crates/api/src/post_report.rs +++ b/crates/api/src/post_report.rs @@ -1,5 +1,5 @@ +use crate::Perform; use actix_web::web::Data; - use lemmy_api_common::{ blocking, check_community_ban, @@ -13,7 +13,8 @@ use lemmy_api_common::{ ResolvePostReport, }, }; -use lemmy_apub::{fetcher::object_id::ObjectId, protocol::activities::community::report::Report}; +use lemmy_apub::protocol::activities::community::report::Report; +use lemmy_apub_lib::object_id::ObjectId; use lemmy_db_schema::{ source::post_report::{PostReport, PostReportForm}, traits::Reportable, @@ -25,8 +26,6 @@ use lemmy_db_views::{ use lemmy_utils::{ApiError, ConnectionId, LemmyError}; use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation}; -use crate::Perform; - /// Creates a post report and notifies the moderators of the community #[async_trait::async_trait(?Send)] impl Perform for CreatePostReport { diff --git a/crates/api_crud/src/community/create.rs b/crates/api_crud/src/community/create.rs index 523ccf00d..b91cab433 100644 --- a/crates/api_crud/src/community/create.rs +++ b/crates/api_crud/src/community/create.rs @@ -7,7 +7,6 @@ use lemmy_api_common::{ is_admin, }; use lemmy_apub::{ - fetcher::object_id::ObjectId, generate_followers_url, generate_inbox_url, generate_local_apub_endpoint, @@ -15,6 +14,7 @@ use lemmy_apub::{ objects::community::ApubCommunity, EndpointType, }; +use lemmy_apub_lib::object_id::ObjectId; use lemmy_db_schema::{ diesel_option_overwrite_to_url, source::{ diff --git a/crates/api_crud/src/community/read.rs b/crates/api_crud/src/community/read.rs index feaf110fb..47c0058c9 100644 --- a/crates/api_crud/src/community/read.rs +++ b/crates/api_crud/src/community/read.rs @@ -1,12 +1,8 @@ use crate::PerformCrud; use actix_web::web::Data; use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt_opt}; -use lemmy_apub::{ - fetcher::object_id::ObjectId, - get_actor_id_from_name, - objects::community::ApubCommunity, -}; -use lemmy_apub_lib::webfinger::WebfingerType; +use lemmy_apub::{get_actor_id_from_name, objects::community::ApubCommunity}; +use lemmy_apub_lib::{object_id::ObjectId, webfinger::WebfingerType}; use lemmy_db_schema::{ from_opt_str_to_opt_enum, traits::DeleteableOrRemoveable, diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 99b67d2ea..4b5c9e73d 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -1,7 +1,5 @@ +use crate::PerformCrud; use actix_web::web::Data; -use log::warn; -use webmention::{Webmention, WebmentionError}; - use lemmy_api_common::{ blocking, check_community_ban, @@ -33,8 +31,9 @@ use lemmy_utils::{ LemmyError, }; use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud}; - -use crate::PerformCrud; +use log::warn; +use url::Url; +use webmention::{Webmention, WebmentionError}; #[async_trait::async_trait(?Send)] impl PerformCrud for CreatePost { @@ -136,10 +135,8 @@ impl PerformCrud for CreatePost { mark_post_as_read(person_id, post_id, context.pool()).await?; if let Some(url) = &updated_post.url { - let mut webmention = Webmention::new( - updated_post.ap_id.clone().into_inner(), - url.clone().into_inner(), - )?; + let mut webmention = + Webmention::new::(updated_post.ap_id.clone().into(), url.clone().into())?; webmention.set_checked(true); match webmention.send().await { Ok(_) => {} diff --git a/crates/api_crud/src/user/read.rs b/crates/api_crud/src/user/read.rs index b649c8fbb..41db9f99b 100644 --- a/crates/api_crud/src/user/read.rs +++ b/crates/api_crud/src/user/read.rs @@ -1,12 +1,8 @@ use crate::PerformCrud; use actix_web::web::Data; use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, person::*}; -use lemmy_apub::{ - fetcher::object_id::ObjectId, - get_actor_id_from_name, - objects::person::ApubPerson, -}; -use lemmy_apub_lib::webfinger::WebfingerType; +use lemmy_apub::{get_actor_id_from_name, objects::person::ApubPerson}; +use lemmy_apub_lib::{object_id::ObjectId, webfinger::WebfingerType}; use lemmy_db_schema::{from_opt_str_to_opt_enum, SortType}; use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder}; use lemmy_db_views_actor::{ diff --git a/crates/apub/src/activities/comment/create_or_update.rs b/crates/apub/src/activities/comment/create_or_update.rs index 84f6d3f28..0d12c4b39 100644 --- a/crates/apub/src/activities/comment/create_or_update.rs +++ b/crates/apub/src/activities/comment/create_or_update.rs @@ -9,7 +9,6 @@ use crate::{ verify_person_in_community, }, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson}, protocol::activities::{create_or_update::comment::CreateOrUpdateComment, CreateOrUpdateType}, }; @@ -17,6 +16,7 @@ use activitystreams::public; use lemmy_api_common::{blocking, check_post_deleted_or_removed}; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType, ApubObject}, verify::verify_domains_match, }; diff --git a/crates/apub/src/activities/comment/mod.rs b/crates/apub/src/activities/comment/mod.rs index 9eb2bb447..1a3f7d3a0 100644 --- a/crates/apub/src/activities/comment/mod.rs +++ b/crates/apub/src/activities/comment/mod.rs @@ -1,7 +1,4 @@ -use crate::{ - fetcher::object_id::ObjectId, - objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson}, -}; +use crate::objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson}; use activitystreams::{ base::BaseExt, link::{LinkExt, Mention}, @@ -9,7 +6,7 @@ use activitystreams::{ use anyhow::anyhow; use itertools::Itertools; use lemmy_api_common::blocking; -use lemmy_apub_lib::{traits::ActorType, webfinger::WebfingerResponse}; +use lemmy_apub_lib::{object_id::ObjectId, traits::ActorType, webfinger::WebfingerResponse}; use lemmy_db_schema::{ newtypes::LocalUserId, source::{comment::Comment, person::Person, post::Post}, diff --git a/crates/apub/src/activities/community/add_mod.rs b/crates/apub/src/activities/community/add_mod.rs index 11dc5a0b9..8dad86096 100644 --- a/crates/apub/src/activities/community/add_mod.rs +++ b/crates/apub/src/activities/community/add_mod.rs @@ -9,7 +9,6 @@ use crate::{ verify_person_in_community, }, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, generate_moderators_url, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::community::add_mod::AddMod, @@ -18,6 +17,7 @@ use activitystreams::{activity::kind::AddType, public}; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, }; use lemmy_db_schema::{ diff --git a/crates/apub/src/activities/community/announce.rs b/crates/apub/src/activities/community/announce.rs index b245a1b88..1fcce8377 100644 --- a/crates/apub/src/activities/community/announce.rs +++ b/crates/apub/src/activities/community/announce.rs @@ -1,7 +1,6 @@ use crate::{ activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_is_public}, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, http::{is_activity_already_known, ActivityCommonFields}, insert_activity, objects::community::ApubCommunity, @@ -10,6 +9,7 @@ use crate::{ use activitystreams::{activity::kind::AnnounceType, public}; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, }; use lemmy_utils::LemmyError; @@ -36,7 +36,7 @@ impl AnnounceActivity { actor: ObjectId::new(community.actor_id()), to: vec![public()], object, - cc: vec![community.followers_url.clone().into_inner()], + cc: vec![community.followers_url.clone().into()], kind: AnnounceType::Announce, id: generate_activity_id( &AnnounceType::Announce, diff --git a/crates/apub/src/activities/community/block_user.rs b/crates/apub/src/activities/community/block_user.rs index d756ed251..851c96fd0 100644 --- a/crates/apub/src/activities/community/block_user.rs +++ b/crates/apub/src/activities/community/block_user.rs @@ -8,7 +8,6 @@ use crate::{ verify_person_in_community, }, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::community::block_user::BlockUserFromCommunity, }; @@ -16,6 +15,7 @@ use activitystreams::{activity::kind::BlockType, public}; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, }; use lemmy_db_schema::{ diff --git a/crates/apub/src/activities/community/mod.rs b/crates/apub/src/activities/community/mod.rs index 96e692d58..b63c8b656 100644 --- a/crates/apub/src/activities/community/mod.rs +++ b/crates/apub/src/activities/community/mod.rs @@ -1,12 +1,11 @@ use crate::{ activities::send_lemmy_activity, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, insert_activity, objects::community::ApubCommunity, protocol::activities::community::announce::AnnounceActivity, }; -use lemmy_apub_lib::traits::ActorType; +use lemmy_apub_lib::{object_id::ObjectId, traits::ActorType}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use url::Url; diff --git a/crates/apub/src/activities/community/remove_mod.rs b/crates/apub/src/activities/community/remove_mod.rs index 1c79e70d2..c5edf333b 100644 --- a/crates/apub/src/activities/community/remove_mod.rs +++ b/crates/apub/src/activities/community/remove_mod.rs @@ -9,7 +9,6 @@ use crate::{ verify_person_in_community, }, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, generate_moderators_url, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::community::remove_mod::RemoveMod, @@ -18,6 +17,7 @@ use activitystreams::{activity::kind::RemoveType, public}; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, }; use lemmy_db_schema::{ diff --git a/crates/apub/src/activities/community/report.rs b/crates/apub/src/activities/community/report.rs index 5b02490b0..f0be3e0a0 100644 --- a/crates/apub/src/activities/community/report.rs +++ b/crates/apub/src/activities/community/report.rs @@ -5,7 +5,6 @@ use crate::{ verify_activity, verify_person_in_community, }, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::community::report::Report, PostOrComment, @@ -14,6 +13,7 @@ use activitystreams::activity::kind::FlagType; use lemmy_api_common::{blocking, comment::CommentReportResponse, post::PostReportResponse}; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, }; use lemmy_db_schema::{ diff --git a/crates/apub/src/activities/community/undo_block_user.rs b/crates/apub/src/activities/community/undo_block_user.rs index 467237eb8..bb4c03587 100644 --- a/crates/apub/src/activities/community/undo_block_user.rs +++ b/crates/apub/src/activities/community/undo_block_user.rs @@ -8,7 +8,6 @@ use crate::{ verify_person_in_community, }, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::community::{ block_user::BlockUserFromCommunity, @@ -19,6 +18,7 @@ use activitystreams::{activity::kind::UndoType, public}; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, }; use lemmy_db_schema::{ diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index 9acb89098..45b08e02f 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -8,7 +8,6 @@ use crate::{ verify_person_in_community, }, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::{activities::community::update::UpdateCommunity, objects::group::Group}, }; @@ -16,6 +15,7 @@ use activitystreams::{activity::kind::UpdateType, public}; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType, ApubObject}, }; use lemmy_db_schema::{ diff --git a/crates/apub/src/activities/deletion/delete.rs b/crates/apub/src/activities/deletion/delete.rs index 605daf8ff..6e2174982 100644 --- a/crates/apub/src/activities/deletion/delete.rs +++ b/crates/apub/src/activities/deletion/delete.rs @@ -1,17 +1,12 @@ use crate::{ activities::{ community::{announce::GetCommunity, send_to_community}, - deletion::{ - receive_delete_action, - verify_delete_activity, - DeletableObjects, - }, + deletion::{receive_delete_action, verify_delete_activity, DeletableObjects}, generate_activity_id, verify_activity, verify_is_public, }, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::deletion::delete::Delete, }; @@ -20,6 +15,7 @@ use anyhow::anyhow; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, }; use lemmy_db_schema::{ diff --git a/crates/apub/src/activities/deletion/mod.rs b/crates/apub/src/activities/deletion/mod.rs index 1be3bccf6..ddd607a7c 100644 --- a/crates/apub/src/activities/deletion/mod.rs +++ b/crates/apub/src/activities/deletion/mod.rs @@ -1,11 +1,11 @@ use crate::{ activities::{verify_mod_action, verify_person_in_community}, - fetcher::object_id::ObjectId, objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost}, protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete}, }; use lemmy_api_common::blocking; use lemmy_apub_lib::{ + object_id::ObjectId, traits::{ActorType, ApubObject}, verify::verify_domains_match, }; diff --git a/crates/apub/src/activities/deletion/undo_delete.rs b/crates/apub/src/activities/deletion/undo_delete.rs index 93338a3f3..b3e44af29 100644 --- a/crates/apub/src/activities/deletion/undo_delete.rs +++ b/crates/apub/src/activities/deletion/undo_delete.rs @@ -7,7 +7,6 @@ use crate::{ verify_is_public, }, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete}, }; @@ -16,6 +15,7 @@ use anyhow::anyhow; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, }; use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post}; diff --git a/crates/apub/src/activities/following/accept.rs b/crates/apub/src/activities/following/accept.rs index 68c8ca454..44d6009a2 100644 --- a/crates/apub/src/activities/following/accept.rs +++ b/crates/apub/src/activities/following/accept.rs @@ -1,12 +1,12 @@ use crate::{ activities::{generate_activity_id, send_lemmy_activity, verify_activity}, - fetcher::object_id::ObjectId, protocol::activities::following::{accept::AcceptFollowCommunity, follow::FollowCommunity}, }; use activitystreams::activity::kind::AcceptType; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, verify::verify_urls_match, }; diff --git a/crates/apub/src/activities/following/follow.rs b/crates/apub/src/activities/following/follow.rs index 30c77fe81..22f3db4ba 100644 --- a/crates/apub/src/activities/following/follow.rs +++ b/crates/apub/src/activities/following/follow.rs @@ -6,7 +6,6 @@ use crate::{ verify_person, verify_person_in_community, }, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::following::{accept::AcceptFollowCommunity, follow::FollowCommunity}, }; @@ -14,6 +13,7 @@ use activitystreams::activity::kind::FollowType; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, verify::verify_urls_match, }; diff --git a/crates/apub/src/activities/following/undo_follow.rs b/crates/apub/src/activities/following/undo_follow.rs index bdc5a4b09..ac25fcd5c 100644 --- a/crates/apub/src/activities/following/undo_follow.rs +++ b/crates/apub/src/activities/following/undo_follow.rs @@ -1,6 +1,5 @@ use crate::{ activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_person}, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::following::{follow::FollowCommunity, undo_follow::UndoFollowCommunity}, }; @@ -8,6 +7,7 @@ use activitystreams::activity::kind::UndoType; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, verify::verify_urls_match, }; diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index e23926f8c..920a531e9 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -1,7 +1,6 @@ use crate::{ check_is_apub_id_valid, context::WithContext, - fetcher::object_id::ObjectId, generate_moderators_url, insert_activity, objects::{community::ApubCommunity, person::ApubPerson}, @@ -11,6 +10,7 @@ use anyhow::anyhow; use lemmy_api_common::blocking; use lemmy_apub_lib::{ activity_queue::send_activity, + object_id::ObjectId, traits::ActorType, verify::verify_domains_match, }; @@ -110,7 +110,7 @@ fn verify_add_remove_moderator_target( target: &Url, community: &ApubCommunity, ) -> Result<(), LemmyError> { - if target != &generate_moderators_url(&community.actor_id)?.into_inner() { + if target != &generate_moderators_url(&community.actor_id)?.into() { return Err(anyhow!("Unkown target url").into()); } Ok(()) diff --git a/crates/apub/src/activities/post/create_or_update.rs b/crates/apub/src/activities/post/create_or_update.rs index e574dda96..925a778f2 100644 --- a/crates/apub/src/activities/post/create_or_update.rs +++ b/crates/apub/src/activities/post/create_or_update.rs @@ -9,7 +9,6 @@ use crate::{ verify_person_in_community, }, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost}, protocol::activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType}, }; @@ -18,6 +17,7 @@ use anyhow::anyhow; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType, ApubObject}, verify::{verify_domains_match, verify_urls_match}, }; diff --git a/crates/apub/src/activities/private_message/create_or_update.rs b/crates/apub/src/activities/private_message/create_or_update.rs index 52b6fa74c..30599db88 100644 --- a/crates/apub/src/activities/private_message/create_or_update.rs +++ b/crates/apub/src/activities/private_message/create_or_update.rs @@ -1,6 +1,5 @@ use crate::{ activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_person}, - fetcher::object_id::ObjectId, objects::{person::ApubPerson, private_message::ApubPrivateMessage}, protocol::activities::{ private_message::create_or_update::CreateOrUpdatePrivateMessage, @@ -10,6 +9,7 @@ use crate::{ use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType, ApubObject}, verify::verify_domains_match, }; diff --git a/crates/apub/src/activities/private_message/delete.rs b/crates/apub/src/activities/private_message/delete.rs index 4547b22b8..46675442f 100644 --- a/crates/apub/src/activities/private_message/delete.rs +++ b/crates/apub/src/activities/private_message/delete.rs @@ -1,6 +1,5 @@ use crate::{ activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_person}, - fetcher::object_id::ObjectId, objects::{person::ApubPerson, private_message::ApubPrivateMessage}, protocol::activities::private_message::delete::DeletePrivateMessage, }; @@ -8,6 +7,7 @@ use activitystreams::activity::kind::DeleteType; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, verify::verify_domains_match, }; diff --git a/crates/apub/src/activities/private_message/undo_delete.rs b/crates/apub/src/activities/private_message/undo_delete.rs index 1272328b1..fbb8660c3 100644 --- a/crates/apub/src/activities/private_message/undo_delete.rs +++ b/crates/apub/src/activities/private_message/undo_delete.rs @@ -1,6 +1,5 @@ use crate::{ activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_person}, - fetcher::object_id::ObjectId, objects::{person::ApubPerson, private_message::ApubPrivateMessage}, protocol::activities::private_message::{ delete::DeletePrivateMessage, @@ -11,6 +10,7 @@ use activitystreams::activity::kind::UndoType; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, verify::{verify_domains_match, verify_urls_match}, }; diff --git a/crates/apub/src/activities/voting/undo_vote.rs b/crates/apub/src/activities/voting/undo_vote.rs index 786d51192..0fe40b628 100644 --- a/crates/apub/src/activities/voting/undo_vote.rs +++ b/crates/apub/src/activities/voting/undo_vote.rs @@ -8,7 +8,6 @@ use crate::{ voting::{undo_vote_comment, undo_vote_post}, }, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::voting::{ undo_vote::UndoVote, @@ -20,6 +19,7 @@ use activitystreams::{activity::kind::UndoType, public}; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, verify::verify_urls_match, }; diff --git a/crates/apub/src/activities/voting/vote.rs b/crates/apub/src/activities/voting/vote.rs index 82b9b84e9..6b9bfbd2f 100644 --- a/crates/apub/src/activities/voting/vote.rs +++ b/crates/apub/src/activities/voting/vote.rs @@ -8,7 +8,6 @@ use crate::{ voting::{vote_comment, vote_post}, }, activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::voting::vote::{Vote, VoteType}, PostOrComment, @@ -17,6 +16,7 @@ use activitystreams::public; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, traits::{ActivityHandler, ActorType}, }; use lemmy_db_schema::{ diff --git a/crates/apub/src/collections/community_moderators.rs b/crates/apub/src/collections/community_moderators.rs index d97affe2c..3579ed38f 100644 --- a/crates/apub/src/collections/community_moderators.rs +++ b/crates/apub/src/collections/community_moderators.rs @@ -1,13 +1,12 @@ use crate::{ collections::CommunityContext, - fetcher::object_id::ObjectId, generate_moderators_url, objects::person::ApubPerson, protocol::collections::group_moderators::GroupModerators, }; use activitystreams::{chrono::NaiveDateTime, collection::kind::OrderedCollectionType}; use lemmy_api_common::blocking; -use lemmy_apub_lib::{traits::ApubObject, verify::verify_domains_match}; +use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject, verify::verify_domains_match}; use lemmy_db_schema::{ source::community::{CommunityModerator, CommunityModeratorForm}, traits::Joinable, @@ -54,7 +53,7 @@ impl ApubObject for ApubCommunityModerators { let ordered_items = self .0 .iter() - .map(|m| ObjectId::::new(m.moderator.actor_id.clone().into_inner())) + .map(|m| ObjectId::::new(m.moderator.actor_id.clone())) .collect(); Ok(GroupModerators { r#type: OrderedCollectionType::OrderedCollection, @@ -81,7 +80,7 @@ impl ApubObject for ApubCommunityModerators { .await??; // Remove old mods from database which arent in the moderators collection anymore for mod_user in ¤t_moderators { - let mod_id = ObjectId::new(mod_user.moderator.actor_id.clone().into_inner()); + let mod_id = ObjectId::new(mod_user.moderator.actor_id.clone()); if !apub.ordered_items.contains(&mod_id) { let community_moderator_form = CommunityModeratorForm { community_id: mod_user.community.id, diff --git a/crates/apub/src/collections/community_outbox.rs b/crates/apub/src/collections/community_outbox.rs index 451c3fa94..96d0892cb 100644 --- a/crates/apub/src/collections/community_outbox.rs +++ b/crates/apub/src/collections/community_outbox.rs @@ -1,7 +1,14 @@ +use crate::{ + collections::CommunityContext, + generate_outbox_url, + objects::{person::ApubPerson, post::ApubPost}, + protocol::{ + activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType}, + collections::group_outbox::GroupOutbox, + }, +}; use activitystreams::collection::kind::OrderedCollectionType; use chrono::NaiveDateTime; -use url::Url; - use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, @@ -13,16 +20,7 @@ use lemmy_db_schema::{ traits::Crud, }; use lemmy_utils::LemmyError; - -use crate::{ - collections::CommunityContext, - generate_outbox_url, - objects::{person::ApubPerson, post::ApubPost}, - protocol::{ - activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType}, - collections::group_outbox::GroupOutbox, - }, -}; +use url::Url; #[derive(Clone, Debug)] pub(crate) struct ApubCommunityOutbox(Vec); diff --git a/crates/apub/src/fetcher/mod.rs b/crates/apub/src/fetcher/mod.rs index 8246f4ce6..d41ee4f71 100644 --- a/crates/apub/src/fetcher/mod.rs +++ b/crates/apub/src/fetcher/mod.rs @@ -1,26 +1,3 @@ -pub mod object_id; pub mod post_or_comment; pub mod search; pub mod user_or_community; - -use chrono::NaiveDateTime; -use lemmy_db_schema::naive_now; - -static ACTOR_REFETCH_INTERVAL_SECONDS: i64 = 24 * 60 * 60; -static ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG: i64 = 10; - -/// Determines when a remote actor should be refetched from its instance. In release builds, this is -/// `ACTOR_REFETCH_INTERVAL_SECONDS` after the last refetch, in debug builds -/// `ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG`. -/// -/// TODO it won't pick up new avatars, summaries etc until a day after. -/// Actors need an "update" activity pushed to other servers to fix this. -fn should_refetch_object(last_refreshed: NaiveDateTime) -> bool { - let update_interval = if cfg!(debug_assertions) { - // avoid infinite loop when fetching community outbox - chrono::Duration::seconds(ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG) - } else { - chrono::Duration::seconds(ACTOR_REFETCH_INTERVAL_SECONDS) - }; - last_refreshed.lt(&(naive_now() - update_interval)) -} diff --git a/crates/apub/src/fetcher/search.rs b/crates/apub/src/fetcher/search.rs index 51699eb04..88027c561 100644 --- a/crates/apub/src/fetcher/search.rs +++ b/crates/apub/src/fetcher/search.rs @@ -1,11 +1,13 @@ +use crate::{ + objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost}, + protocol::objects::{group::Group, note::Note, page::Page, person::Person}, +}; use anyhow::anyhow; use chrono::NaiveDateTime; use itertools::Itertools; -use serde::Deserialize; -use url::Url; - use lemmy_api_common::blocking; use lemmy_apub_lib::{ + object_id::ObjectId, traits::ApubObject, webfinger::{webfinger_resolve_actor, WebfingerType}, }; @@ -15,12 +17,8 @@ use lemmy_db_schema::{ }; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; - -use crate::{ - fetcher::object_id::ObjectId, - objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost}, - protocol::objects::{group::Group, note::Note, page::Page, person::Person}, -}; +use serde::Deserialize; +use url::Url; /// Attempt to parse the query as URL, and fetch an ActivityPub object from it. /// diff --git a/crates/apub/src/http/community.rs b/crates/apub/src/http/community.rs index c208f71ed..d9228ca53 100644 --- a/crates/apub/src/http/community.rs +++ b/crates/apub/src/http/community.rs @@ -7,7 +7,6 @@ use crate::{ CommunityContext, }, context::WithContext, - fetcher::object_id::ObjectId, generate_outbox_url, http::{ create_apub_response, @@ -24,7 +23,7 @@ use crate::{ }; use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse}; use lemmy_api_common::blocking; -use lemmy_apub_lib::traits::ApubObject; +use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject}; use lemmy_db_schema::source::community::Community; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; @@ -116,7 +115,7 @@ pub(crate) async fn get_apub_community_outbox( Community::read_from_name(conn, &info.community_name) }) .await??; - let id = ObjectId::new(generate_outbox_url(&community.actor_id)?.into_inner()); + let id = ObjectId::new(generate_outbox_url(&community.actor_id)?); let outbox_data = CommunityContext(community.into(), context.get_ref().clone()); let outbox: ApubCommunityOutbox = id.dereference(&outbox_data, &mut 0).await?; Ok(create_apub_response(&outbox.to_apub(&outbox_data).await?)) @@ -131,7 +130,7 @@ pub(crate) async fn get_apub_community_moderators( }) .await?? .into(); - let id = ObjectId::new(generate_outbox_url(&community.actor_id)?.into_inner()); + let id = ObjectId::new(generate_outbox_url(&community.actor_id)?); let outbox_data = CommunityContext(community, context.get_ref().clone()); let moderators: ApubCommunityModerators = id.dereference(&outbox_data, &mut 0).await?; Ok(create_apub_response( diff --git a/crates/apub/src/http/mod.rs b/crates/apub/src/http/mod.rs index 450b937d5..03b68b94b 100644 --- a/crates/apub/src/http/mod.rs +++ b/crates/apub/src/http/mod.rs @@ -2,7 +2,7 @@ use crate::{ activity_lists::SharedInboxActivities, check_is_apub_id_valid, context::WithContext, - fetcher::{object_id::ObjectId, user_or_community::UserOrCommunity}, + fetcher::user_or_community::UserOrCommunity, http::{community::receive_group_inbox, person::receive_person_inbox}, insert_activity, }; @@ -19,6 +19,7 @@ use http::StatusCode; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, + object_id::ObjectId, signatures::verify_signature, traits::{ActivityHandler, ActorType}, APUB_JSON_CONTENT_TYPE, diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs index 68240728a..09270fec8 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -1,15 +1,25 @@ -use std::ops::Deref; - +use crate::{ + activities::verify_person_in_community, + check_is_apub_id_valid, + protocol::{ + objects::{ + note::{Note, SourceCompat}, + tombstone::Tombstone, + }, + Source, + }, + PostOrComment, +}; use activitystreams::{object::kind::NoteType, public}; use anyhow::anyhow; use chrono::NaiveDateTime; use html2md::parse_html; -use url::Url; - use lemmy_api_common::blocking; use lemmy_apub_lib::{ + object_id::ObjectId, traits::ApubObject, values::{MediaTypeHtml, MediaTypeMarkdown}, + verify::verify_domains_match, }; use lemmy_db_schema::{ source::{ @@ -21,26 +31,12 @@ use lemmy_db_schema::{ traits::Crud, }; use lemmy_utils::{ - utils::{convert_datetime, remove_slurs}, + utils::{convert_datetime, markdown_to_html, remove_slurs}, LemmyError, }; use lemmy_websocket::LemmyContext; - -use crate::{ - activities::verify_person_in_community, - check_is_apub_id_valid, - fetcher::object_id::ObjectId, - protocol::{ - objects::{ - note::{Note, SourceCompat}, - tombstone::Tombstone, - }, - Source, - }, - PostOrComment, -}; -use lemmy_apub_lib::verify::verify_domains_match; -use lemmy_utils::utils::markdown_to_html; +use std::ops::Deref; +use url::Url; #[derive(Clone, Debug)] pub struct ApubComment(Comment); @@ -101,9 +97,9 @@ impl ApubObject for ApubComment { let in_reply_to = if let Some(comment_id) = self.parent_id { let parent_comment = blocking(context.pool(), move |conn| Comment::read(conn, comment_id)).await??; - ObjectId::::new(parent_comment.ap_id.into_inner()) + ObjectId::::new(parent_comment.ap_id) } else { - ObjectId::::new(post.ap_id.into_inner()) + ObjectId::::new(post.ap_id) }; let note = Note { @@ -235,7 +231,7 @@ pub(crate) mod tests { .await .unwrap(); - assert_eq!(comment.ap_id.clone().into_inner(), url); + assert_eq!(comment.ap_id, url.into()); assert_eq!(comment.content.len(), 14); assert!(!comment.local); assert_eq!(request_counter, 0); @@ -267,7 +263,7 @@ pub(crate) mod tests { .await .unwrap(); - assert_eq!(comment.ap_id.clone().into_inner(), pleroma_url); + assert_eq!(comment.ap_id, pleroma_url.into()); assert_eq!(comment.content.len(), 64); assert!(!comment.local); assert_eq!(request_counter, 0); diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index 8fd245dc2..851563ab8 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -1,17 +1,6 @@ -use activitystreams::{ - actor::{kind::GroupType, Endpoints}, - object::kind::ImageType, -}; -use chrono::NaiveDateTime; -use itertools::Itertools; -use log::debug; -use std::ops::Deref; -use url::Url; - use crate::{ check_is_apub_id_valid, collections::{community_moderators::ApubCommunityModerators, CommunityContext}, - fetcher::object_id::ObjectId, generate_moderators_url, generate_outbox_url, protocol::{ @@ -20,8 +9,15 @@ use crate::{ Source, }, }; +use activitystreams::{ + actor::{kind::GroupType, Endpoints}, + object::kind::ImageType, +}; +use chrono::NaiveDateTime; +use itertools::Itertools; use lemmy_api_common::blocking; use lemmy_apub_lib::{ + object_id::ObjectId, traits::{ActorType, ApubObject}, values::MediaTypeMarkdown, }; @@ -32,6 +28,9 @@ use lemmy_utils::{ LemmyError, }; use lemmy_websocket::LemmyContext; +use log::debug; +use std::ops::Deref; +use url::Url; #[derive(Clone, Debug)] pub struct ApubCommunity(Community); @@ -105,7 +104,7 @@ impl ApubObject for ApubCommunity { image, sensitive: Some(self.nsfw), moderators: Some(ObjectId::::new( - generate_moderators_url(&self.actor_id)?.into_inner(), + generate_moderators_url(&self.actor_id)?, )), inbox: self.inbox_url.clone().into(), outbox: ObjectId::new(generate_outbox_url(&self.actor_id)?), @@ -187,7 +186,7 @@ impl ActorType for ApubCommunity { } fn shared_inbox_url(&self) -> Option { - self.shared_inbox_url.clone().map(|s| s.into_inner()) + self.shared_inbox_url.clone().map(|s| s.into()) } } @@ -207,8 +206,12 @@ impl ApubCommunity { let follower_inboxes: Vec = follows .into_iter() .filter(|f| !f.follower.local) - .map(|f| f.follower.shared_inbox_url.unwrap_or(f.follower.inbox_url)) - .map(|i| i.into_inner()) + .map(|f| { + f.follower + .shared_inbox_url + .unwrap_or(f.follower.inbox_url) + .into() + }) .collect(); let inboxes = vec![follower_inboxes, additional_inboxes] .into_iter() diff --git a/crates/apub/src/objects/person.rs b/crates/apub/src/objects/person.rs index 652ef6220..f1da65508 100644 --- a/crates/apub/src/objects/person.rs +++ b/crates/apub/src/objects/person.rs @@ -1,6 +1,5 @@ use crate::{ check_is_apub_id_valid, - fetcher::object_id::ObjectId, generate_outbox_url, objects::get_summary_from_string_or_source, protocol::{ @@ -13,6 +12,7 @@ use activitystreams::{actor::Endpoints, object::kind::ImageType}; use chrono::NaiveDateTime; use lemmy_api_common::blocking; use lemmy_apub_lib::{ + object_id::ObjectId, traits::{ActorType, ApubObject}, values::MediaTypeMarkdown, verify::verify_domains_match, @@ -181,7 +181,7 @@ impl ActorType for ApubPerson { self.local } fn actor_id(&self) -> Url { - self.actor_id.to_owned().into_inner() + self.actor_id.to_owned().into() } fn name(&self) -> String { self.name.clone() @@ -200,7 +200,7 @@ impl ActorType for ApubPerson { } fn shared_inbox_url(&self) -> Option { - self.shared_inbox_url.clone().map(|s| s.into_inner()) + self.shared_inbox_url.clone().map(|s| s.into()) } } @@ -247,7 +247,7 @@ pub(crate) mod tests { .await .unwrap(); - assert_eq!(person.actor_id.clone().into_inner(), url); + assert_eq!(person.actor_id, url.into()); assert_eq!(person.name, "lanodan"); assert!(person.public_key.is_some()); assert!(!person.local); diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index b29bdb801..0ba80724d 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -1,7 +1,6 @@ use crate::{ activities::verify_person_in_community, check_is_apub_id_valid, - fetcher::object_id::ObjectId, protocol::{ objects::{page::Page, tombstone::Tombstone}, ImageObject, @@ -15,6 +14,7 @@ use activitystreams::{ use chrono::NaiveDateTime; use lemmy_api_common::blocking; use lemmy_apub_lib::{ + object_id::ObjectId, traits::ApubObject, values::{MediaTypeHtml, MediaTypeMarkdown}, verify::verify_domains_match, @@ -217,7 +217,7 @@ mod tests { .await .unwrap(); - assert_eq!(post.ap_id.clone().into_inner(), url); + assert_eq!(post.ap_id, url.into()); assert_eq!(post.name, "Post title"); assert!(post.body.is_some()); assert_eq!(post.body.as_ref().unwrap().len(), 45); diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs index 5c4befb05..00b3a26cb 100644 --- a/crates/apub/src/objects/private_message.rs +++ b/crates/apub/src/objects/private_message.rs @@ -1,14 +1,12 @@ -use crate::{ - fetcher::object_id::ObjectId, - protocol::{ - objects::chat_message::{ChatMessage, ChatMessageType}, - Source, - }, +use crate::protocol::{ + objects::chat_message::{ChatMessage, ChatMessageType}, + Source, }; use chrono::NaiveDateTime; use html2md::parse_html; use lemmy_api_common::blocking; use lemmy_apub_lib::{ + object_id::ObjectId, traits::ApubObject, values::{MediaTypeHtml, MediaTypeMarkdown}, verify::verify_domains_match, @@ -180,7 +178,7 @@ mod tests { .await .unwrap(); - assert_eq!(pm.ap_id.clone().into_inner(), url); + assert_eq!(pm.ap_id.clone(), url.into()); assert_eq!(pm.content.len(), 20); assert_eq!(request_counter, 0); @@ -204,7 +202,7 @@ mod tests { .await .unwrap(); - assert_eq!(pm.ap_id.clone().into_inner(), pleroma_url); + assert_eq!(pm.ap_id, pleroma_url.into()); assert_eq!(pm.content.len(), 3); assert_eq!(request_counter, 0); diff --git a/crates/apub/src/protocol/activities/community/add_mod.rs b/crates/apub/src/protocol/activities/community/add_mod.rs index 6938f01d4..75571bea8 100644 --- a/crates/apub/src/protocol/activities/community/add_mod.rs +++ b/crates/apub/src/protocol/activities/community/add_mod.rs @@ -1,5 +1,6 @@ -use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson}; +use crate::objects::person::ApubPerson; use activitystreams::{activity::kind::AddType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/community/announce.rs b/crates/apub/src/protocol/activities/community/announce.rs index 07fbda635..2dd094041 100644 --- a/crates/apub/src/protocol/activities/community/announce.rs +++ b/crates/apub/src/protocol/activities/community/announce.rs @@ -1,9 +1,6 @@ -use crate::{ - activity_lists::AnnouncableActivities, - fetcher::object_id::ObjectId, - objects::community::ApubCommunity, -}; +use crate::{activity_lists::AnnouncableActivities, objects::community::ApubCommunity}; use activitystreams::{activity::kind::AnnounceType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/community/block_user.rs b/crates/apub/src/protocol/activities/community/block_user.rs index ec95e6e9b..0b974f697 100644 --- a/crates/apub/src/protocol/activities/community/block_user.rs +++ b/crates/apub/src/protocol/activities/community/block_user.rs @@ -1,8 +1,6 @@ -use crate::{ - fetcher::object_id::ObjectId, - objects::{community::ApubCommunity, person::ApubPerson}, -}; +use crate::objects::{community::ApubCommunity, person::ApubPerson}; use activitystreams::{activity::kind::BlockType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/community/remove_mod.rs b/crates/apub/src/protocol/activities/community/remove_mod.rs index cca263549..6e3e5458c 100644 --- a/crates/apub/src/protocol/activities/community/remove_mod.rs +++ b/crates/apub/src/protocol/activities/community/remove_mod.rs @@ -1,5 +1,6 @@ -use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson}; +use crate::objects::person::ApubPerson; use activitystreams::{activity::kind::RemoveType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/community/report.rs b/crates/apub/src/protocol/activities/community/report.rs index d10a9d285..fbf21ec8d 100644 --- a/crates/apub/src/protocol/activities/community/report.rs +++ b/crates/apub/src/protocol/activities/community/report.rs @@ -1,8 +1,9 @@ use crate::{ - fetcher::{object_id::ObjectId, post_or_comment::PostOrComment}, + fetcher::post_or_comment::PostOrComment, objects::{community::ApubCommunity, person::ApubPerson}, }; use activitystreams::{activity::kind::FlagType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/community/undo_block_user.rs b/crates/apub/src/protocol/activities/community/undo_block_user.rs index 24356fab2..538a7e25c 100644 --- a/crates/apub/src/protocol/activities/community/undo_block_user.rs +++ b/crates/apub/src/protocol/activities/community/undo_block_user.rs @@ -1,9 +1,9 @@ use crate::{ - fetcher::object_id::ObjectId, objects::person::ApubPerson, protocol::activities::community::block_user::BlockUserFromCommunity, }; use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/community/update.rs b/crates/apub/src/protocol/activities/community/update.rs index 686938aa4..b9877338a 100644 --- a/crates/apub/src/protocol/activities/community/update.rs +++ b/crates/apub/src/protocol/activities/community/update.rs @@ -1,9 +1,6 @@ -use crate::{ - fetcher::object_id::ObjectId, - objects::person::ApubPerson, - protocol::objects::group::Group, -}; +use crate::{objects::person::ApubPerson, protocol::objects::group::Group}; use activitystreams::{activity::kind::UpdateType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/create_or_update/comment.rs b/crates/apub/src/protocol/activities/create_or_update/comment.rs index 4e5b412d7..6e90dedb0 100644 --- a/crates/apub/src/protocol/activities/create_or_update/comment.rs +++ b/crates/apub/src/protocol/activities/create_or_update/comment.rs @@ -1,9 +1,9 @@ use crate::{ - fetcher::object_id::ObjectId, objects::person::ApubPerson, protocol::{activities::CreateOrUpdateType, objects::note::Note}, }; use activitystreams::{link::Mention, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/create_or_update/post.rs b/crates/apub/src/protocol/activities/create_or_update/post.rs index b1851c0d9..e64e48408 100644 --- a/crates/apub/src/protocol/activities/create_or_update/post.rs +++ b/crates/apub/src/protocol/activities/create_or_update/post.rs @@ -1,9 +1,9 @@ use crate::{ - fetcher::object_id::ObjectId, objects::person::ApubPerson, protocol::{activities::CreateOrUpdateType, objects::page::Page}, }; use activitystreams::unparsed::Unparsed; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/deletion/delete.rs b/crates/apub/src/protocol/activities/deletion/delete.rs index af5022799..7e2275153 100644 --- a/crates/apub/src/protocol/activities/deletion/delete.rs +++ b/crates/apub/src/protocol/activities/deletion/delete.rs @@ -1,5 +1,6 @@ -use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson}; +use crate::objects::person::ApubPerson; use activitystreams::{activity::kind::DeleteType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; use url::Url; diff --git a/crates/apub/src/protocol/activities/deletion/undo_delete.rs b/crates/apub/src/protocol/activities/deletion/undo_delete.rs index 8a30546e5..aa851cbc7 100644 --- a/crates/apub/src/protocol/activities/deletion/undo_delete.rs +++ b/crates/apub/src/protocol/activities/deletion/undo_delete.rs @@ -1,9 +1,6 @@ -use crate::{ - fetcher::object_id::ObjectId, - objects::person::ApubPerson, - protocol::activities::deletion::delete::Delete, -}; +use crate::{objects::person::ApubPerson, protocol::activities::deletion::delete::Delete}; use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/following/accept.rs b/crates/apub/src/protocol/activities/following/accept.rs index 7eeb3a418..0c5988bc7 100644 --- a/crates/apub/src/protocol/activities/following/accept.rs +++ b/crates/apub/src/protocol/activities/following/accept.rs @@ -1,9 +1,9 @@ use crate::{ - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::following::follow::FollowCommunity, }; use activitystreams::{activity::kind::AcceptType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/following/follow.rs b/crates/apub/src/protocol/activities/following/follow.rs index 651ab1d2d..9d3f6a823 100644 --- a/crates/apub/src/protocol/activities/following/follow.rs +++ b/crates/apub/src/protocol/activities/following/follow.rs @@ -1,8 +1,6 @@ -use crate::{ - fetcher::object_id::ObjectId, - objects::{community::ApubCommunity, person::ApubPerson}, -}; +use crate::objects::{community::ApubCommunity, person::ApubPerson}; use activitystreams::{activity::kind::FollowType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/following/undo_follow.rs b/crates/apub/src/protocol/activities/following/undo_follow.rs index 3abeabd29..5e9c58946 100644 --- a/crates/apub/src/protocol/activities/following/undo_follow.rs +++ b/crates/apub/src/protocol/activities/following/undo_follow.rs @@ -1,9 +1,9 @@ use crate::{ - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson}, protocol::activities::following::follow::FollowCommunity, }; use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/private_message/create_or_update.rs b/crates/apub/src/protocol/activities/private_message/create_or_update.rs index 5092a1640..756bfd5e9 100644 --- a/crates/apub/src/protocol/activities/private_message/create_or_update.rs +++ b/crates/apub/src/protocol/activities/private_message/create_or_update.rs @@ -1,9 +1,9 @@ use crate::{ - fetcher::object_id::ObjectId, objects::person::ApubPerson, protocol::{activities::CreateOrUpdateType, objects::chat_message::ChatMessage}, }; use activitystreams::unparsed::Unparsed; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/private_message/delete.rs b/crates/apub/src/protocol/activities/private_message/delete.rs index 87da3c310..f9ad29fde 100644 --- a/crates/apub/src/protocol/activities/private_message/delete.rs +++ b/crates/apub/src/protocol/activities/private_message/delete.rs @@ -1,8 +1,6 @@ -use crate::{ - fetcher::object_id::ObjectId, - objects::{person::ApubPerson, private_message::ApubPrivateMessage}, -}; +use crate::objects::{person::ApubPerson, private_message::ApubPrivateMessage}; use activitystreams::{activity::kind::DeleteType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/private_message/undo_delete.rs b/crates/apub/src/protocol/activities/private_message/undo_delete.rs index 16d82492c..951f14d4a 100644 --- a/crates/apub/src/protocol/activities/private_message/undo_delete.rs +++ b/crates/apub/src/protocol/activities/private_message/undo_delete.rs @@ -1,9 +1,9 @@ use crate::{ - fetcher::object_id::ObjectId, objects::person::ApubPerson, protocol::activities::private_message::delete::DeletePrivateMessage, }; use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/voting/undo_vote.rs b/crates/apub/src/protocol/activities/voting/undo_vote.rs index 05606dbe9..c6c8f0b03 100644 --- a/crates/apub/src/protocol/activities/voting/undo_vote.rs +++ b/crates/apub/src/protocol/activities/voting/undo_vote.rs @@ -1,9 +1,6 @@ -use crate::{ - fetcher::object_id::ObjectId, - objects::person::ApubPerson, - protocol::activities::voting::vote::Vote, -}; +use crate::{objects::person::ApubPerson, protocol::activities::voting::vote::Vote}; use activitystreams::{activity::kind::UndoType, unparsed::Unparsed}; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/activities/voting/vote.rs b/crates/apub/src/protocol/activities/voting/vote.rs index 6d82ccc42..977a549db 100644 --- a/crates/apub/src/protocol/activities/voting/vote.rs +++ b/crates/apub/src/protocol/activities/voting/vote.rs @@ -1,9 +1,7 @@ -use crate::{ - fetcher::{object_id::ObjectId, post_or_comment::PostOrComment}, - objects::person::ApubPerson, -}; +use crate::{fetcher::post_or_comment::PostOrComment, objects::person::ApubPerson}; use activitystreams::unparsed::Unparsed; use anyhow::anyhow; +use lemmy_apub_lib::object_id::ObjectId; use lemmy_utils::LemmyError; use serde::{Deserialize, Serialize}; use std::convert::TryFrom; diff --git a/crates/apub/src/protocol/collections/group_followers.rs b/crates/apub/src/protocol/collections/group_followers.rs index d3df5e22b..55b92a76c 100644 --- a/crates/apub/src/protocol/collections/group_followers.rs +++ b/crates/apub/src/protocol/collections/group_followers.rs @@ -29,7 +29,7 @@ impl GroupFollowers { .await??; Ok(GroupFollowers { - id: generate_followers_url(&community.actor_id)?.into_inner(), + id: generate_followers_url(&community.actor_id)?.into(), r#type: CollectionType::Collection, total_items: community_followers.len() as i32, items: vec![], diff --git a/crates/apub/src/protocol/collections/group_moderators.rs b/crates/apub/src/protocol/collections/group_moderators.rs index d37751a16..9b8494849 100644 --- a/crates/apub/src/protocol/collections/group_moderators.rs +++ b/crates/apub/src/protocol/collections/group_moderators.rs @@ -1,5 +1,6 @@ -use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson}; +use crate::objects::person::ApubPerson; use activitystreams::collection::kind::OrderedCollectionType; +use lemmy_apub_lib::object_id::ObjectId; use serde::{Deserialize, Serialize}; use url::Url; diff --git a/crates/apub/src/protocol/collections/person_outbox.rs b/crates/apub/src/protocol/collections/person_outbox.rs index 6ec758403..c8af0173b 100644 --- a/crates/apub/src/protocol/collections/person_outbox.rs +++ b/crates/apub/src/protocol/collections/person_outbox.rs @@ -18,7 +18,7 @@ impl PersonOutbox { pub(crate) async fn new(user: Person) -> Result { Ok(PersonOutbox { r#type: OrderedCollectionType::OrderedCollection, - id: generate_outbox_url(&user.actor_id)?.into_inner(), + id: generate_outbox_url(&user.actor_id)?.into(), ordered_items: vec![], total_items: 0, }) diff --git a/crates/apub/src/protocol/objects/chat_message.rs b/crates/apub/src/protocol/objects/chat_message.rs index e9677758c..3a019967e 100644 --- a/crates/apub/src/protocol/objects/chat_message.rs +++ b/crates/apub/src/protocol/objects/chat_message.rs @@ -1,5 +1,4 @@ use crate::{ - fetcher::object_id::ObjectId, objects::{person::ApubPerson, private_message::ApubPrivateMessage}, protocol::Source, }; @@ -8,7 +7,7 @@ use activitystreams::{ unparsed::Unparsed, }; use anyhow::anyhow; -use lemmy_apub_lib::{values::MediaTypeHtml, verify::verify_domains_match}; +use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml, verify::verify_domains_match}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; diff --git a/crates/apub/src/protocol/objects/group.rs b/crates/apub/src/protocol/objects/group.rs index 921a5dc8d..dbc823748 100644 --- a/crates/apub/src/protocol/objects/group.rs +++ b/crates/apub/src/protocol/objects/group.rs @@ -4,7 +4,6 @@ use crate::{ community_moderators::ApubCommunityModerators, community_outbox::ApubCommunityOutbox, }, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, get_summary_from_string_or_source}, protocol::{ImageObject, Source}, }; @@ -13,7 +12,7 @@ use activitystreams::{ unparsed::Unparsed, }; use chrono::{DateTime, FixedOffset}; -use lemmy_apub_lib::{signatures::PublicKey, verify::verify_domains_match}; +use lemmy_apub_lib::{object_id::ObjectId, signatures::PublicKey, verify::verify_domains_match}; use lemmy_db_schema::{naive_now, source::community::CommunityForm}; use lemmy_utils::{ settings::structs::Settings, @@ -73,6 +72,7 @@ impl Group { check_slurs(&title, slur_regex)?; check_slurs_opt(&description, slur_regex)?; + // TODO: test_parse_lemmy_community_moderators() keeps failing here with stack overflow Ok(CommunityForm { name, title, diff --git a/crates/apub/src/protocol/objects/note.rs b/crates/apub/src/protocol/objects/note.rs index 58b164a7d..34cb6bed0 100644 --- a/crates/apub/src/protocol/objects/note.rs +++ b/crates/apub/src/protocol/objects/note.rs @@ -1,6 +1,6 @@ use crate::{ activities::{verify_is_public, verify_person_in_community}, - fetcher::{object_id::ObjectId, post_or_comment::PostOrComment}, + fetcher::post_or_comment::PostOrComment, objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost}, protocol::Source, }; @@ -8,7 +8,7 @@ use activitystreams::{object::kind::NoteType, unparsed::Unparsed}; use anyhow::anyhow; use chrono::{DateTime, FixedOffset}; use lemmy_api_common::blocking; -use lemmy_apub_lib::{values::MediaTypeHtml, verify::verify_domains_match}; +use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml, verify::verify_domains_match}; use lemmy_db_schema::{ newtypes::CommentId, source::{community::Community, post::Post}, diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs index 0cd004799..285a0e04e 100644 --- a/crates/apub/src/protocol/objects/page.rs +++ b/crates/apub/src/protocol/objects/page.rs @@ -1,13 +1,12 @@ use crate::{ activities::{verify_is_public, verify_person_in_community}, - fetcher::object_id::ObjectId, objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost}, protocol::{ImageObject, Source}, }; use activitystreams::{object::kind::PageType, unparsed::Unparsed}; use anyhow::anyhow; use chrono::{DateTime, FixedOffset}; -use lemmy_apub_lib::{values::MediaTypeHtml, verify::verify_domains_match}; +use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml, verify::verify_domains_match}; use lemmy_utils::{utils::check_slurs, LemmyError}; use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; diff --git a/crates/apub/src/protocol/objects/person.rs b/crates/apub/src/protocol/objects/person.rs index 720e7de00..cf9c10b1f 100644 --- a/crates/apub/src/protocol/objects/person.rs +++ b/crates/apub/src/protocol/objects/person.rs @@ -1,11 +1,10 @@ use crate::{ - fetcher::object_id::ObjectId, objects::person::ApubPerson, protocol::{ImageObject, Source}, }; use activitystreams::{actor::Endpoints, unparsed::Unparsed, url::Url}; use chrono::{DateTime, FixedOffset}; -use lemmy_apub_lib::signatures::PublicKey; +use lemmy_apub_lib::{object_id::ObjectId, signatures::PublicKey}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; diff --git a/crates/apub_lib/Cargo.toml b/crates/apub_lib/Cargo.toml index c3835a12e..f3ef989cf 100644 --- a/crates/apub_lib/Cargo.toml +++ b/crates/apub_lib/Cargo.toml @@ -27,3 +27,4 @@ actix-web = { version = "4.0.0-beta.9", default-features = false } http-signature-normalization-actix = { version = "0.5.0-beta.10", default-features = false, features = ["server", "sha-2"] } http-signature-normalization-reqwest = { version = "0.2.0", default-features = false, features = ["sha-2"] } background-jobs = "0.9.1" +diesel = "1.4.8" diff --git a/crates/apub_lib/src/lib.rs b/crates/apub_lib/src/lib.rs index a35f54415..c65baee53 100644 --- a/crates/apub_lib/src/lib.rs +++ b/crates/apub_lib/src/lib.rs @@ -3,6 +3,7 @@ extern crate lazy_static; pub mod activity_queue; pub mod data; +pub mod object_id; pub mod signatures; pub mod traits; pub mod values; diff --git a/crates/apub/src/fetcher/object_id.rs b/crates/apub_lib/src/object_id.rs similarity index 74% rename from crates/apub/src/fetcher/object_id.rs rename to crates/apub_lib/src/object_id.rs index 5c5c518f4..fe55a44aa 100644 --- a/crates/apub/src/fetcher/object_id.rs +++ b/crates/apub_lib/src/object_id.rs @@ -1,8 +1,7 @@ -use crate::fetcher::should_refetch_object; +use crate::{traits::ApubObject, APUB_JSON_CONTENT_TYPE}; +use activitystreams::chrono::{Duration as ChronoDuration, NaiveDateTime, Utc}; use anyhow::anyhow; use diesel::NotFound; -use lemmy_apub_lib::{traits::ApubObject, APUB_JSON_CONTENT_TYPE}; -use lemmy_db_schema::newtypes::DbUrl; use lemmy_utils::{ request::{build_user_agent, retry}, settings::structs::Settings, @@ -144,12 +143,34 @@ where } } +static ACTOR_REFETCH_INTERVAL_SECONDS: i64 = 24 * 60 * 60; +static ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG: i64 = 10; + +/// Determines when a remote actor should be refetched from its instance. In release builds, this is +/// `ACTOR_REFETCH_INTERVAL_SECONDS` after the last refetch, in debug builds +/// `ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG`. +/// +/// TODO it won't pick up new avatars, summaries etc until a day after. +/// Actors need an "update" activity pushed to other servers to fix this. +fn should_refetch_object(last_refreshed: NaiveDateTime) -> bool { + let update_interval = if cfg!(debug_assertions) { + // avoid infinite loop when fetching community outbox + ChronoDuration::seconds(ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG) + } else { + ChronoDuration::seconds(ACTOR_REFETCH_INTERVAL_SECONDS) + }; + let refresh_limit = Utc::now().naive_utc() - update_interval; + last_refreshed.lt(&refresh_limit) +} + impl Display for ObjectId where Kind: ApubObject + Send + 'static, for<'de2> ::ApubType: serde::Deserialize<'de2>, { + #[allow(clippy::to_string_in_display)] fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + // Use to_string here because Url.display is not useful for us write!(f, "{}", self.0.to_string()) } } @@ -164,12 +185,17 @@ where } } -impl From> for DbUrl -where - Kind: ApubObject + Send + 'static, - for<'de2> ::ApubType: serde::Deserialize<'de2>, -{ - fn from(id: ObjectId) -> Self { - id.0.into() +#[cfg(test)] +mod tests { + use super::*; + use crate::object_id::should_refetch_object; + + #[test] + fn test_should_refetch_object() { + let one_second_ago = Utc::now().naive_utc() - ChronoDuration::seconds(1); + assert!(!should_refetch_object(one_second_ago)); + + let two_days_ago = Utc::now().naive_utc() - ChronoDuration::days(2); + assert!(should_refetch_object(two_days_ago)); } } diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index 21212835f..025f590d4 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -12,6 +12,7 @@ doctest = false [dependencies] lemmy_utils = { version = "=0.13.5-rc.7", path = "../utils" } +lemmy_apub_lib = { version = "=0.13.5-rc.7", path = "../apub_lib" } diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"] } diesel_migrations = "1.4.0" chrono = { version = "0.4.19", features = ["serde"] } diff --git a/crates/db_schema/src/newtypes.rs b/crates/db_schema/src/newtypes.rs index 3042d35e7..9219d77f9 100644 --- a/crates/db_schema/src/newtypes.rs +++ b/crates/db_schema/src/newtypes.rs @@ -4,6 +4,7 @@ use diesel::{ serialize::{Output, ToSql}, sql_types::Text, }; +use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject}; use serde::{Deserialize, Serialize}; use std::{ fmt, @@ -93,27 +94,32 @@ where } } -impl DbUrl { - // TODO: remove this method and just use into() - pub fn into_inner(self) -> Url { - self.0 - } -} - impl Display for DbUrl { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.to_owned().0.fmt(f) } } -impl From for Url { - fn from(url: DbUrl) -> Self { - url.0 +// the project doesnt compile with From +#[allow(clippy::from_over_into)] +impl Into for Url { + fn into(self) -> DbUrl { + DbUrl(self) + } +} +#[allow(clippy::from_over_into)] +impl Into for DbUrl { + fn into(self) -> Url { + self.0 } } -impl From for DbUrl { - fn from(url: Url) -> Self { - DbUrl(url) +impl From> for DbUrl +where + Kind: ApubObject + Send + 'static, + for<'de2> ::ApubType: serde::Deserialize<'de2>, +{ + fn from(id: ObjectId) -> Self { + DbUrl(id.into()) } } From c725514841cda13d8743c7e30e7527b848e04d67 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Sat, 6 Nov 2021 13:37:55 +0100 Subject: [PATCH 04/10] Change to_apub and from_apub to take by value and avoid cloning --- crates/api/src/post.rs | 4 +-- crates/api_crud/src/comment/create.rs | 23 ++++++------- crates/api_crud/src/comment/update.rs | 18 +++++----- crates/api_crud/src/community/update.rs | 2 +- crates/api_crud/src/post/create.rs | 19 ++++++----- crates/api_crud/src/post/update.rs | 2 +- crates/api_crud/src/private_message/create.rs | 2 +- crates/api_crud/src/private_message/update.rs | 2 +- .../activities/comment/create_or_update.rs | 8 ++--- .../apub/src/activities/community/update.rs | 10 +++--- .../src/activities/post/create_or_update.rs | 8 ++--- .../private_message/create_or_update.rs | 6 ++-- .../src/collections/community_moderators.rs | 15 ++++---- .../apub/src/collections/community_outbox.rs | 8 ++--- crates/apub/src/fetcher/post_or_comment.rs | 8 ++--- crates/apub/src/fetcher/search.rs | 4 +-- crates/apub/src/fetcher/user_or_community.rs | 4 +-- crates/apub/src/http/comment.rs | 2 +- crates/apub/src/http/community.rs | 6 ++-- crates/apub/src/http/person.rs | 2 +- crates/apub/src/http/post.rs | 2 +- crates/apub/src/objects/comment.rs | 28 +++++++-------- crates/apub/src/objects/community.rs | 8 ++--- crates/apub/src/objects/person.rs | 31 ++++++++--------- crates/apub/src/objects/post.rs | 15 ++++---- crates/apub/src/objects/private_message.rs | 25 +++++++------- crates/apub/src/protocol/objects/group.rs | 34 +++++++++---------- crates/apub_lib/src/object_id.rs | 2 +- crates/apub_lib/src/traits.rs | 4 +-- 29 files changed, 150 insertions(+), 152 deletions(-) diff --git a/crates/api/src/post.rs b/crates/api/src/post.rs index 3564f1352..c7acb08fb 100644 --- a/crates/api/src/post.rs +++ b/crates/api/src/post.rs @@ -169,7 +169,7 @@ impl Perform for LockPost { // apub updates CreateOrUpdatePost::send( - &updated_post, + updated_post, &local_user_view.person.clone().into(), CreateOrUpdateType::Update, context, @@ -242,7 +242,7 @@ impl Perform for StickyPost { // Apub updates // TODO stickied should pry work like locked for ease of use CreateOrUpdatePost::send( - &updated_post, + updated_post, &local_user_view.person.clone().into(), CreateOrUpdateType::Update, context, diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index ab093ea19..4c7bb34f0 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -1,5 +1,5 @@ +use crate::PerformCrud; use actix_web::web::Data; - use lemmy_api_common::{ blocking, check_community_ban, @@ -13,6 +13,7 @@ use lemmy_api_common::{ use lemmy_apub::{ fetcher::post_or_comment::PostOrComment, generate_local_apub_endpoint, + objects::comment::ApubComment, protocol::activities::{ create_or_update::comment::CreateOrUpdateComment, voting::vote::{Vote, VoteType}, @@ -40,8 +41,6 @@ use lemmy_websocket::{ UserOperationCrud, }; -use crate::PerformCrud; - #[async_trait::async_trait(?Send)] impl PerformCrud for CreateComment { type Response = CommentResponse; @@ -121,14 +120,6 @@ impl PerformCrud for CreateComment { .await? .map_err(|e| ApiError::err("couldnt_create_comment", e))?; - CreateOrUpdateComment::send( - &updated_comment.clone().into(), - &local_user_view.person.clone().into(), - CreateOrUpdateType::Create, - context, - ) - .await?; - // Scan the comment for user mentions, add those rows let post_id = post.id; let mentions = scrape_text_for_mentions(&comment_form.content); @@ -155,7 +146,15 @@ impl PerformCrud for CreateComment { .await? .map_err(|e| ApiError::err("couldnt_like_comment", e))?; - let object = PostOrComment::Comment(updated_comment.into()); + let apub_comment: ApubComment = updated_comment.into(); + CreateOrUpdateComment::send( + apub_comment.clone(), + &local_user_view.person.clone().into(), + CreateOrUpdateType::Create, + context, + ) + .await?; + let object = PostOrComment::Comment(apub_comment); Vote::send( &object, &local_user_view.person.clone().into(), diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index 70f15dfb2..4802b1d50 100644 --- a/crates/api_crud/src/comment/update.rs +++ b/crates/api_crud/src/comment/update.rs @@ -72,15 +72,6 @@ impl PerformCrud for EditComment { .await? .map_err(|e| ApiError::err("couldnt_update_comment", e))?; - // Send the apub update - CreateOrUpdateComment::send( - &updated_comment.clone().into(), - &local_user_view.person.clone().into(), - CreateOrUpdateType::Update, - context, - ) - .await?; - // Do the mentions / recipients let updated_comment_content = updated_comment.content.to_owned(); let mentions = scrape_text_for_mentions(&updated_comment_content); @@ -94,6 +85,15 @@ impl PerformCrud for EditComment { ) .await?; + // Send the apub update + CreateOrUpdateComment::send( + updated_comment.into(), + &local_user_view.person.into(), + CreateOrUpdateType::Update, + context, + ) + .await?; + send_comment_ws_message( data.comment_id, UserOperationCrud::EditComment, diff --git a/crates/api_crud/src/community/update.rs b/crates/api_crud/src/community/update.rs index 4764b0254..d1fd89818 100644 --- a/crates/api_crud/src/community/update.rs +++ b/crates/api_crud/src/community/update.rs @@ -72,7 +72,7 @@ impl PerformCrud for EditCommunity { .map_err(|e| ApiError::err("couldnt_update_community", e))?; UpdateCommunity::send( - &updated_community.into(), + updated_community.into(), &local_user_view.person.into(), context, ) diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 4b5c9e73d..248adee6c 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -12,6 +12,7 @@ use lemmy_api_common::{ use lemmy_apub::{ fetcher::post_or_comment::PostOrComment, generate_local_apub_endpoint, + objects::post::ApubPost, protocol::activities::{ create_or_update::post::CreateOrUpdatePost, voting::vote::{Vote, VoteType}, @@ -109,14 +110,6 @@ impl PerformCrud for CreatePost { .await? .map_err(|e| ApiError::err("couldnt_create_post", e))?; - CreateOrUpdatePost::send( - &updated_post.clone().into(), - &local_user_view.person.clone().into(), - CreateOrUpdateType::Create, - context, - ) - .await?; - // They like their own post by default let person_id = local_user_view.person.id; let post_id = inserted_post.id; @@ -145,7 +138,15 @@ impl PerformCrud for CreatePost { } } - let object = PostOrComment::Post(Box::new(updated_post.into())); + let apub_post: ApubPost = updated_post.into(); + CreateOrUpdatePost::send( + apub_post.clone(), + &local_user_view.person.clone().into(), + CreateOrUpdateType::Create, + context, + ) + .await?; + let object = PostOrComment::Post(Box::new(apub_post)); Vote::send( &object, &local_user_view.person.clone().into(), diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index 0a982d688..2cfc67d41 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -109,7 +109,7 @@ impl PerformCrud for EditPost { // Send apub update CreateOrUpdatePost::send( - &updated_post.into(), + updated_post.into(), &local_user_view.person.clone().into(), CreateOrUpdateType::Update, context, diff --git a/crates/api_crud/src/private_message/create.rs b/crates/api_crud/src/private_message/create.rs index 705d781e2..0c6378269 100644 --- a/crates/api_crud/src/private_message/create.rs +++ b/crates/api_crud/src/private_message/create.rs @@ -83,7 +83,7 @@ impl PerformCrud for CreatePrivateMessage { .map_err(|e| ApiError::err("couldnt_create_private_message", e))?; CreateOrUpdatePrivateMessage::send( - &updated_private_message.into(), + updated_private_message.into(), &local_user_view.person.into(), CreateOrUpdateType::Create, context, diff --git a/crates/api_crud/src/private_message/update.rs b/crates/api_crud/src/private_message/update.rs index 8114556c1..95cc5cb34 100644 --- a/crates/api_crud/src/private_message/update.rs +++ b/crates/api_crud/src/private_message/update.rs @@ -47,7 +47,7 @@ impl PerformCrud for EditPrivateMessage { // Send the apub update CreateOrUpdatePrivateMessage::send( - &updated_private_message.into(), + updated_private_message.into(), &local_user_view.person.into(), CreateOrUpdateType::Update, context, diff --git a/crates/apub/src/activities/comment/create_or_update.rs b/crates/apub/src/activities/comment/create_or_update.rs index 0d12c4b39..0095a511d 100644 --- a/crates/apub/src/activities/comment/create_or_update.rs +++ b/crates/apub/src/activities/comment/create_or_update.rs @@ -29,7 +29,7 @@ use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperation impl CreateOrUpdateComment { pub async fn send( - comment: &ApubComment, + comment: ApubComment, actor: &ApubPerson, kind: CreateOrUpdateType, context: &LemmyContext, @@ -48,12 +48,12 @@ impl CreateOrUpdateComment { kind.clone(), &context.settings().get_protocol_and_hostname(), )?; - let maa = collect_non_local_mentions(comment, &community, context).await?; + let maa = collect_non_local_mentions(&comment, &community, context).await?; let create_or_update = CreateOrUpdateComment { actor: ObjectId::new(actor.actor_id()), to: vec![public()], - object: comment.to_apub(context).await?, + object: comment.into_apub(context).await?, cc: maa.ccs, tag: maa.tags, kind, @@ -97,7 +97,7 @@ impl ActivityHandler for CreateOrUpdateComment { request_counter: &mut i32, ) -> Result<(), LemmyError> { let comment = - ApubComment::from_apub(&self.object, context, self.actor.inner(), request_counter).await?; + ApubComment::from_apub(self.object, context, self.actor.inner(), request_counter).await?; let recipients = get_notif_recipients(&self.actor, &comment, context, request_counter).await?; let notif_type = match self.kind { CreateOrUpdateType::Create => UserOperationCrud::CreateComment, diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index 45b08e02f..688722479 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -27,7 +27,7 @@ use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperati impl UpdateCommunity { pub async fn send( - community: &ApubCommunity, + community: ApubCommunity, actor: &ApubPerson, context: &LemmyContext, ) -> Result<(), LemmyError> { @@ -38,7 +38,7 @@ impl UpdateCommunity { let update = UpdateCommunity { actor: ObjectId::new(actor.actor_id()), to: vec![public()], - object: community.to_apub(context).await?, + object: community.clone().into_apub(context).await?, cc: vec![community.actor_id()], kind: UpdateType::Update, id: id.clone(), @@ -46,7 +46,7 @@ impl UpdateCommunity { }; let activity = AnnouncableActivities::UpdateCommunity(Box::new(update)); - send_to_community(activity, &id, actor, community, vec![], context).await + send_to_community(activity, &id, actor, &community, vec![], context).await } } @@ -73,8 +73,8 @@ impl ActivityHandler for UpdateCommunity { ) -> Result<(), LemmyError> { let community = self.get_community(context, request_counter).await?; - let updated_community = Group::from_apub_to_form( - &self.object, + let updated_community = Group::into_form( + self.object, &community.actor_id.clone().into(), &context.settings(), ) diff --git a/crates/apub/src/activities/post/create_or_update.rs b/crates/apub/src/activities/post/create_or_update.rs index 925a778f2..982f90ccc 100644 --- a/crates/apub/src/activities/post/create_or_update.rs +++ b/crates/apub/src/activities/post/create_or_update.rs @@ -27,7 +27,7 @@ use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCru impl CreateOrUpdatePost { pub(crate) async fn new( - post: &ApubPost, + post: ApubPost, actor: &ApubPerson, community: &ApubCommunity, kind: CreateOrUpdateType, @@ -40,7 +40,7 @@ impl CreateOrUpdatePost { Ok(CreateOrUpdatePost { actor: ObjectId::new(actor.actor_id()), to: vec![public()], - object: post.to_apub(context).await?, + object: post.into_apub(context).await?, cc: vec![community.actor_id()], kind, id: id.clone(), @@ -48,7 +48,7 @@ impl CreateOrUpdatePost { }) } pub async fn send( - post: &ApubPost, + post: ApubPost, actor: &ApubPerson, kind: CreateOrUpdateType, context: &LemmyContext, @@ -115,7 +115,7 @@ impl ActivityHandler for CreateOrUpdatePost { ) -> Result<(), LemmyError> { let actor = self.actor.dereference(context, request_counter).await?; let post = - ApubPost::from_apub(&self.object, context, &actor.actor_id(), request_counter).await?; + ApubPost::from_apub(self.object, context, &actor.actor_id(), request_counter).await?; let notif_type = match self.kind { CreateOrUpdateType::Create => UserOperationCrud::CreatePost, diff --git a/crates/apub/src/activities/private_message/create_or_update.rs b/crates/apub/src/activities/private_message/create_or_update.rs index 30599db88..7f40b5fbc 100644 --- a/crates/apub/src/activities/private_message/create_or_update.rs +++ b/crates/apub/src/activities/private_message/create_or_update.rs @@ -19,7 +19,7 @@ use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud} impl CreateOrUpdatePrivateMessage { pub async fn send( - private_message: &ApubPrivateMessage, + private_message: ApubPrivateMessage, actor: &ApubPerson, kind: CreateOrUpdateType, context: &LemmyContext, @@ -38,7 +38,7 @@ impl CreateOrUpdatePrivateMessage { id: id.clone(), actor: ObjectId::new(actor.actor_id()), to: [ObjectId::new(recipient.actor_id())], - object: private_message.to_apub(context).await?, + object: private_message.into_apub(context).await?, kind, unparsed: Default::default(), }; @@ -67,7 +67,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage { request_counter: &mut i32, ) -> Result<(), LemmyError> { let private_message = - ApubPrivateMessage::from_apub(&self.object, context, self.actor.inner(), request_counter) + ApubPrivateMessage::from_apub(self.object, context, self.actor.inner(), request_counter) .await?; let notif_type = match self.kind { diff --git a/crates/apub/src/collections/community_moderators.rs b/crates/apub/src/collections/community_moderators.rs index 3579ed38f..cbbe66708 100644 --- a/crates/apub/src/collections/community_moderators.rs +++ b/crates/apub/src/collections/community_moderators.rs @@ -49,11 +49,11 @@ impl ApubObject for ApubCommunityModerators { unimplemented!() } - async fn to_apub(&self, data: &Self::DataType) -> Result { + async fn into_apub(self, data: &Self::DataType) -> Result { let ordered_items = self .0 - .iter() - .map(|m| ObjectId::::new(m.moderator.actor_id.clone())) + .into_iter() + .map(|m| ObjectId::::new(m.moderator.actor_id)) .collect(); Ok(GroupModerators { r#type: OrderedCollectionType::OrderedCollection, @@ -67,7 +67,7 @@ impl ApubObject for ApubCommunityModerators { } async fn from_apub( - apub: &Self::ApubType, + apub: Self::ApubType, data: &Self::DataType, expected_domain: &Url, request_counter: &mut i32, @@ -94,12 +94,11 @@ impl ApubObject for ApubCommunityModerators { } // Add new mods to database which have been added to moderators collection - for mod_id in &apub.ordered_items { - let mod_id = ObjectId::new(mod_id.clone()); + for mod_id in apub.ordered_items { + let mod_id = ObjectId::new(mod_id); let mod_user: ApubPerson = mod_id.dereference(&data.1, request_counter).await?; if !current_moderators - .clone() .iter() .map(|c| c.moderator.actor_id.clone()) .any(|x| x == mod_user.actor_id) @@ -166,7 +165,7 @@ mod tests { 0: community, 1: context, }; - ApubCommunityModerators::from_apub(&json, &community_context, &url, &mut request_counter) + ApubCommunityModerators::from_apub(json, &community_context, &url, &mut request_counter) .await .unwrap(); assert_eq!(request_counter, 0); diff --git a/crates/apub/src/collections/community_outbox.rs b/crates/apub/src/collections/community_outbox.rs index 96d0892cb..cbad5c484 100644 --- a/crates/apub/src/collections/community_outbox.rs +++ b/crates/apub/src/collections/community_outbox.rs @@ -60,9 +60,9 @@ impl ApubObject for ApubCommunityOutbox { Ok(()) } - async fn to_apub(&self, data: &Self::DataType) -> Result { + async fn into_apub(self, data: &Self::DataType) -> Result { let mut ordered_items = vec![]; - for post in &self.0 { + for post in self.0 { let actor = post.creator_id; let actor: ApubPerson = blocking(data.1.pool(), move |conn| Person::read(conn, actor)) .await?? @@ -86,13 +86,13 @@ impl ApubObject for ApubCommunityOutbox { } async fn from_apub( - apub: &Self::ApubType, + apub: Self::ApubType, data: &Self::DataType, expected_domain: &Url, request_counter: &mut i32, ) -> Result { verify_domains_match(expected_domain, &apub.id)?; - let mut outbox_activities = apub.ordered_items.clone(); + let mut outbox_activities = apub.ordered_items; if outbox_activities.len() > 20 { outbox_activities = outbox_activities[0..20].to_vec(); } diff --git a/crates/apub/src/fetcher/post_or_comment.rs b/crates/apub/src/fetcher/post_or_comment.rs index ef4e59e1d..075b018e3 100644 --- a/crates/apub/src/fetcher/post_or_comment.rs +++ b/crates/apub/src/fetcher/post_or_comment.rs @@ -53,7 +53,7 @@ impl ApubObject for PostOrComment { } } - async fn to_apub(&self, _data: &Self::DataType) -> Result { + async fn into_apub(self, _data: &Self::DataType) -> Result { unimplemented!() } @@ -62,17 +62,17 @@ impl ApubObject for PostOrComment { } async fn from_apub( - apub: &PageOrNote, + apub: PageOrNote, context: &LemmyContext, expected_domain: &Url, request_counter: &mut i32, ) -> Result { Ok(match apub { PageOrNote::Page(p) => PostOrComment::Post(Box::new( - ApubPost::from_apub(p, context, expected_domain, request_counter).await?, + ApubPost::from_apub(*p, context, expected_domain, request_counter).await?, )), PageOrNote::Note(n) => PostOrComment::Comment( - ApubComment::from_apub(n, context, expected_domain, request_counter).await?, + ApubComment::from_apub(*n, context, expected_domain, request_counter).await?, ), }) } diff --git a/crates/apub/src/fetcher/search.rs b/crates/apub/src/fetcher/search.rs index 88027c561..557fc1b54 100644 --- a/crates/apub/src/fetcher/search.rs +++ b/crates/apub/src/fetcher/search.rs @@ -155,7 +155,7 @@ impl ApubObject for SearchableObjects { } } - async fn to_apub(&self, _data: &Self::DataType) -> Result { + async fn into_apub(self, _data: &Self::DataType) -> Result { unimplemented!() } @@ -164,7 +164,7 @@ impl ApubObject for SearchableObjects { } async fn from_apub( - apub: &Self::ApubType, + apub: Self::ApubType, context: &LemmyContext, ed: &Url, rc: &mut i32, diff --git a/crates/apub/src/fetcher/user_or_community.rs b/crates/apub/src/fetcher/user_or_community.rs index 16a1d8220..eccda7c65 100644 --- a/crates/apub/src/fetcher/user_or_community.rs +++ b/crates/apub/src/fetcher/user_or_community.rs @@ -54,7 +54,7 @@ impl ApubObject for UserOrCommunity { } } - async fn to_apub(&self, _data: &Self::DataType) -> Result { + async fn into_apub(self, _data: &Self::DataType) -> Result { unimplemented!() } @@ -63,7 +63,7 @@ impl ApubObject for UserOrCommunity { } async fn from_apub( - apub: &Self::ApubType, + apub: Self::ApubType, data: &Self::DataType, expected_domain: &Url, request_counter: &mut i32, diff --git a/crates/apub/src/http/comment.rs b/crates/apub/src/http/comment.rs index 3086f2fd9..f62ff36e2 100644 --- a/crates/apub/src/http/comment.rs +++ b/crates/apub/src/http/comment.rs @@ -30,7 +30,7 @@ pub(crate) async fn get_apub_comment( } if !comment.deleted { - Ok(create_apub_response(&comment.to_apub(&**context).await?)) + Ok(create_apub_response(&comment.into_apub(&**context).await?)) } else { Ok(create_apub_tombstone_response(&comment.to_tombstone()?)) } diff --git a/crates/apub/src/http/community.rs b/crates/apub/src/http/community.rs index d9228ca53..10794d993 100644 --- a/crates/apub/src/http/community.rs +++ b/crates/apub/src/http/community.rs @@ -47,7 +47,7 @@ pub(crate) async fn get_apub_community_http( .into(); if !community.deleted { - let apub = community.to_apub(&**context).await?; + let apub = community.into_apub(&**context).await?; Ok(create_apub_response(&apub)) } else { @@ -118,7 +118,7 @@ pub(crate) async fn get_apub_community_outbox( let id = ObjectId::new(generate_outbox_url(&community.actor_id)?); let outbox_data = CommunityContext(community.into(), context.get_ref().clone()); let outbox: ApubCommunityOutbox = id.dereference(&outbox_data, &mut 0).await?; - Ok(create_apub_response(&outbox.to_apub(&outbox_data).await?)) + Ok(create_apub_response(&outbox.into_apub(&outbox_data).await?)) } pub(crate) async fn get_apub_community_moderators( @@ -134,6 +134,6 @@ pub(crate) async fn get_apub_community_moderators( let outbox_data = CommunityContext(community, context.get_ref().clone()); let moderators: ApubCommunityModerators = id.dereference(&outbox_data, &mut 0).await?; Ok(create_apub_response( - &moderators.to_apub(&outbox_data).await?, + &moderators.into_apub(&outbox_data).await?, )) } diff --git a/crates/apub/src/http/person.rs b/crates/apub/src/http/person.rs index 193689c5e..3a3a34038 100644 --- a/crates/apub/src/http/person.rs +++ b/crates/apub/src/http/person.rs @@ -39,7 +39,7 @@ pub(crate) async fn get_apub_person_http( .into(); if !person.deleted { - let apub = person.to_apub(&context).await?; + let apub = person.into_apub(&context).await?; Ok(create_apub_response(&apub)) } else { diff --git a/crates/apub/src/http/post.rs b/crates/apub/src/http/post.rs index 0459942a9..52fe002a9 100644 --- a/crates/apub/src/http/post.rs +++ b/crates/apub/src/http/post.rs @@ -30,7 +30,7 @@ pub(crate) async fn get_apub_post( } if !post.deleted { - Ok(create_apub_response(&post.to_apub(&context).await?)) + Ok(create_apub_response(&post.into_apub(&context).await?)) } else { Ok(create_apub_tombstone_response(&post.to_tombstone()?)) } diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs index 09270fec8..da96f8fab 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -87,7 +87,7 @@ impl ApubObject for ApubComment { Ok(()) } - async fn to_apub(&self, context: &LemmyContext) -> Result { + async fn into_apub(self, context: &LemmyContext) -> Result { let creator_id = self.creator_id; let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??; @@ -104,7 +104,7 @@ impl ApubObject for ApubComment { let note = Note { r#type: NoteType::Note, - id: ObjectId::new(self.ap_id.to_owned()), + id: ObjectId::new(self.ap_id.clone()), attributed_to: ObjectId::new(creator.actor_id), to: vec![public()], content: markdown_to_html(&self.content), @@ -133,13 +133,12 @@ impl ApubObject for ApubComment { /// /// If the parent community, post and comment(s) are not known locally, these are also fetched. async fn from_apub( - note: &Note, + note: Note, context: &LemmyContext, expected_domain: &Url, request_counter: &mut i32, ) -> Result { verify_domains_match(note.id.inner(), expected_domain)?; - let ap_id = Some(note.id.clone().into()); let creator = note .attributed_to .dereference(context, request_counter) @@ -176,10 +175,10 @@ impl ApubObject for ApubComment { content: content_slurs_removed, removed: None, read: None, - published: note.published.map(|u| u.to_owned().naive_local()), - updated: note.updated.map(|u| u.to_owned().naive_local()), + published: note.published.map(|u| u.naive_local()), + updated: note.updated.map(|u| u.naive_local()), deleted: None, - ap_id, + ap_id: Some(note.id.into()), local: Some(false), }; let comment = blocking(context.pool(), move |conn| Comment::upsert(conn, &form)).await??; @@ -206,7 +205,7 @@ pub(crate) mod tests { let person = parse_lemmy_person(context).await; let community = parse_lemmy_community(context).await; let post_json = file_to_json_object("assets/lemmy/objects/page.json"); - let post = ApubPost::from_apub(&post_json, context, url, &mut 0) + let post = ApubPost::from_apub(post_json, context, url, &mut 0) .await .unwrap(); (person, community, post) @@ -225,9 +224,9 @@ pub(crate) mod tests { let url = Url::parse("https://enterprise.lemmy.ml/comment/38741").unwrap(); let data = prepare_comment_test(&url, &context).await; - let json = file_to_json_object("assets/lemmy/objects/note.json"); + let json: Note = file_to_json_object("assets/lemmy/objects/note.json"); let mut request_counter = 0; - let comment = ApubComment::from_apub(&json, &context, &url, &mut request_counter) + let comment = ApubComment::from_apub(json.clone(), &context, &url, &mut request_counter) .await .unwrap(); @@ -236,10 +235,11 @@ pub(crate) mod tests { assert!(!comment.local); assert_eq!(request_counter, 0); - let to_apub = comment.to_apub(&context).await.unwrap(); + let comment_id = comment.id; + let to_apub = comment.into_apub(&context).await.unwrap(); assert_json_include!(actual: json, expected: to_apub); - Comment::delete(&*context.pool().get().unwrap(), comment.id).unwrap(); + Comment::delete(&*context.pool().get().unwrap(), comment_id).unwrap(); cleanup(data, &context); } @@ -254,12 +254,12 @@ pub(crate) mod tests { Url::parse("https://queer.hacktivis.me/objects/8d4973f4-53de-49cd-8c27-df160e16a9c2") .unwrap(); let person_json = file_to_json_object("assets/pleroma/objects/person.json"); - ApubPerson::from_apub(&person_json, &context, &pleroma_url, &mut 0) + ApubPerson::from_apub(person_json, &context, &pleroma_url, &mut 0) .await .unwrap(); let json = file_to_json_object("assets/pleroma/objects/note.json"); let mut request_counter = 0; - let comment = ApubComment::from_apub(&json, &context, &pleroma_url, &mut request_counter) + let comment = ApubComment::from_apub(json, &context, &pleroma_url, &mut request_counter) .await .unwrap(); diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index 851563ab8..1eb58995c 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -79,7 +79,7 @@ impl ApubObject for ApubCommunity { Ok(()) } - async fn to_apub(&self, _context: &LemmyContext) -> Result { + async fn into_apub(self, _context: &LemmyContext) -> Result { let source = self.description.clone().map(|bio| Source { content: bio, media_type: MediaTypeMarkdown::Markdown, @@ -130,12 +130,12 @@ impl ApubObject for ApubCommunity { /// Converts a `Group` to `Community`, inserts it into the database and updates moderators. async fn from_apub( - group: &Group, + group: Group, context: &LemmyContext, expected_domain: &Url, request_counter: &mut i32, ) -> Result { - let form = Group::from_apub_to_form(group, expected_domain, &context.settings()).await?; + let form = Group::into_form(group.clone(), expected_domain, &context.settings()).await?; // Fetching mods and outbox is not necessary for Lemmy to work, so ignore errors. Besides, // we need to ignore these errors so that tests can work entirely offline. @@ -242,7 +242,7 @@ pub(crate) mod tests { let url = Url::parse("https://enterprise.lemmy.ml/c/tenforward").unwrap(); let mut request_counter = 0; - let community = ApubCommunity::from_apub(&json, context, &url, &mut request_counter) + let community = ApubCommunity::from_apub(json, context, &url, &mut request_counter) .await .unwrap(); // this makes two requests to the (intentionally) broken outbox/moderators collections diff --git a/crates/apub/src/objects/person.rs b/crates/apub/src/objects/person.rs index f1da65508..dcaa9cd6d 100644 --- a/crates/apub/src/objects/person.rs +++ b/crates/apub/src/objects/person.rs @@ -76,7 +76,7 @@ impl ApubObject for ApubPerson { Ok(()) } - async fn to_apub(&self, _pool: &LemmyContext) -> Result { + async fn into_apub(self, _pool: &LemmyContext) -> Result { let kind = if self.bot_account { UserTypes::Service } else { @@ -124,17 +124,16 @@ impl ApubObject for ApubPerson { } async fn from_apub( - person: &Person, + person: Person, context: &LemmyContext, expected_domain: &Url, _request_counter: &mut i32, ) -> Result { verify_domains_match(person.id.inner(), expected_domain)?; - let actor_id = Some(person.id.clone().into()); - let name = person.preferred_username.clone(); - let display_name: Option = person.name.clone(); + let name = person.preferred_username; + let display_name: Option = person.name; let bio = get_summary_from_string_or_source(&person.summary, &person.source); - let shared_inbox = person.endpoints.shared_inbox.clone().map(|s| s.into()); + let shared_inbox = person.endpoints.shared_inbox.map(|s| s.into()); let bot_account = match person.kind { UserTypes::Person => false, UserTypes::Service => true, @@ -152,21 +151,21 @@ impl ApubObject for ApubPerson { display_name: Some(display_name), banned: None, deleted: None, - avatar: Some(person.icon.clone().map(|i| i.url.into())), - banner: Some(person.image.clone().map(|i| i.url.into())), - published: person.published.map(|u| u.clone().naive_local()), - updated: person.updated.map(|u| u.clone().naive_local()), - actor_id, + avatar: Some(person.icon.map(|i| i.url.into())), + banner: Some(person.image.map(|i| i.url.into())), + published: person.published.map(|u| u.naive_local()), + updated: person.updated.map(|u| u.naive_local()), + actor_id: Some(person.id.into()), bio: Some(bio), local: Some(false), admin: Some(false), bot_account: Some(bot_account), private_key: None, - public_key: Some(Some(person.public_key.public_key_pem.clone())), + public_key: Some(Some(person.public_key.public_key_pem)), last_refreshed_at: Some(naive_now()), - inbox_url: Some(person.inbox.to_owned().into()), + inbox_url: Some(person.inbox.into()), shared_inbox_url: Some(shared_inbox), - matrix_user_id: Some(person.matrix_user_id.clone()), + matrix_user_id: Some(person.matrix_user_id), }; let person = blocking(context.pool(), move |conn| { DbPerson::upsert(conn, &person_form) @@ -215,7 +214,7 @@ pub(crate) mod tests { let json = file_to_json_object("assets/lemmy/objects/person.json"); let url = Url::parse("https://enterprise.lemmy.ml/u/picard").unwrap(); let mut request_counter = 0; - let person = ApubPerson::from_apub(&json, context, &url, &mut request_counter) + let person = ApubPerson::from_apub(json, context, &url, &mut request_counter) .await .unwrap(); assert_eq!(request_counter, 0); @@ -243,7 +242,7 @@ pub(crate) mod tests { let json = file_to_json_object("assets/pleroma/objects/person.json"); let url = Url::parse("https://queer.hacktivis.me/users/lanodan").unwrap(); let mut request_counter = 0; - let person = ApubPerson::from_apub(&json, &context, &url, &mut request_counter) + let person = ApubPerson::from_apub(json, &context, &url, &mut request_counter) .await .unwrap(); diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index 0ba80724d..bbb5537e2 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -87,7 +87,7 @@ impl ApubObject for ApubPost { } // Turn a Lemmy post into an ActivityPub page that can be sent out over the network. - async fn to_apub(&self, context: &LemmyContext) -> Result { + async fn into_apub(self, context: &LemmyContext) -> Result { let creator_id = self.creator_id; let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??; let community_id = self.community_id; @@ -134,7 +134,7 @@ impl ApubObject for ApubPost { } async fn from_apub( - page: &Page, + page: Page, context: &LemmyContext, expected_domain: &Url, request_counter: &mut i32, @@ -144,7 +144,6 @@ impl ApubObject for ApubPost { if !page.is_mod_action(context).await? { verify_domains_match(page.id.inner(), expected_domain)?; }; - let ap_id = Some(page.id.clone().into()); let creator = page .attributed_to .dereference(context, request_counter) @@ -153,7 +152,7 @@ impl ApubObject for ApubPost { check_is_apub_id_valid(page.id.inner(), community.local, &context.settings())?; verify_person_in_community(&page.attributed_to, &community, context, request_counter).await?; - let thumbnail_url: Option = page.image.clone().map(|i| i.url); + let thumbnail_url: Option = page.image.map(|i| i.url); let (metadata_res, pictrs_thumbnail) = if let Some(url) = &page.url { fetch_site_data(context.client(), &context.settings(), Some(url)).await } else { @@ -168,8 +167,8 @@ impl ApubObject for ApubPost { .as_ref() .map(|s| remove_slurs(&s.content, &context.settings().slur_regex())); let form = PostForm { - name: page.name.clone(), - url: page.url.clone().map(|u| u.into()), + name: page.name, + url: page.url.map(|u| u.into()), body: body_slurs_removed, creator_id: creator.id, community_id: community.id, @@ -184,7 +183,7 @@ impl ApubObject for ApubPost { embed_description, embed_html, thumbnail_url: pictrs_thumbnail.map(|u| u.into()), - ap_id, + ap_id: Some(page.id.into()), local: Some(false), }; let post = blocking(context.pool(), move |conn| Post::upsert(conn, &form)).await??; @@ -213,7 +212,7 @@ mod tests { let json = file_to_json_object("assets/lemmy/objects/page.json"); let url = Url::parse("https://enterprise.lemmy.ml/post/55143").unwrap(); let mut request_counter = 0; - let post = ApubPost::from_apub(&json, &context, &url, &mut request_counter) + let post = ApubPost::from_apub(json, &context, &url, &mut request_counter) .await .unwrap(); diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs index 00b3a26cb..334f37c5f 100644 --- a/crates/apub/src/objects/private_message.rs +++ b/crates/apub/src/objects/private_message.rs @@ -70,7 +70,7 @@ impl ApubObject for ApubPrivateMessage { unimplemented!() } - async fn to_apub(&self, context: &LemmyContext) -> Result { + async fn into_apub(self, context: &LemmyContext) -> Result { let creator_id = self.creator_id; let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??; @@ -101,13 +101,13 @@ impl ApubObject for ApubPrivateMessage { } async fn from_apub( - note: &ChatMessage, + note: ChatMessage, context: &LemmyContext, expected_domain: &Url, request_counter: &mut i32, ) -> Result { verify_domains_match(note.id.inner(), expected_domain)?; - let ap_id = Some(note.id.clone().into()); + let ap_id = Some(note.id.into()); let creator = note .attributed_to .dereference(context, request_counter) @@ -123,8 +123,8 @@ impl ApubObject for ApubPrivateMessage { creator_id: creator.id, recipient_id: recipient.id, content, - published: note.published.map(|u| u.to_owned().naive_local()), - updated: note.updated.map(|u| u.to_owned().naive_local()), + published: note.published.map(|u| u.naive_local()), + updated: note.updated.map(|u| u.naive_local()), deleted: None, read: None, ap_id, @@ -150,12 +150,12 @@ mod tests { async fn prepare_comment_test(url: &Url, context: &LemmyContext) -> (ApubPerson, ApubPerson) { let lemmy_person = file_to_json_object("assets/lemmy/objects/person.json"); - let person1 = ApubPerson::from_apub(&lemmy_person, context, url, &mut 0) + let person1 = ApubPerson::from_apub(lemmy_person, context, url, &mut 0) .await .unwrap(); let pleroma_person = file_to_json_object("assets/pleroma/objects/person.json"); let pleroma_url = Url::parse("https://queer.hacktivis.me/users/lanodan").unwrap(); - let person2 = ApubPerson::from_apub(&pleroma_person, context, &pleroma_url, &mut 0) + let person2 = ApubPerson::from_apub(pleroma_person, context, &pleroma_url, &mut 0) .await .unwrap(); (person1, person2) @@ -172,9 +172,9 @@ mod tests { let context = init_context(); let url = Url::parse("https://enterprise.lemmy.ml/private_message/1621").unwrap(); let data = prepare_comment_test(&url, &context).await; - let json = file_to_json_object("assets/lemmy/objects/chat_message.json"); + let json: ChatMessage = file_to_json_object("assets/lemmy/objects/chat_message.json"); let mut request_counter = 0; - let pm = ApubPrivateMessage::from_apub(&json, &context, &url, &mut request_counter) + let pm = ApubPrivateMessage::from_apub(json.clone(), &context, &url, &mut request_counter) .await .unwrap(); @@ -182,10 +182,11 @@ mod tests { assert_eq!(pm.content.len(), 20); assert_eq!(request_counter, 0); - let to_apub = pm.to_apub(&context).await.unwrap(); + let pm_id = pm.id; + let to_apub = pm.into_apub(&context).await.unwrap(); assert_json_include!(actual: json, expected: to_apub); - PrivateMessage::delete(&*context.pool().get().unwrap(), pm.id).unwrap(); + PrivateMessage::delete(&*context.pool().get().unwrap(), pm_id).unwrap(); cleanup(data, &context); } @@ -198,7 +199,7 @@ mod tests { let pleroma_url = Url::parse("https://queer.hacktivis.me/objects/2").unwrap(); let json = file_to_json_object("assets/pleroma/objects/chat_message.json"); let mut request_counter = 0; - let pm = ApubPrivateMessage::from_apub(&json, &context, &pleroma_url, &mut request_counter) + let pm = ApubPrivateMessage::from_apub(json, &context, &pleroma_url, &mut request_counter) .await .unwrap(); diff --git a/crates/apub/src/protocol/objects/group.rs b/crates/apub/src/protocol/objects/group.rs index dbc823748..acaf59092 100644 --- a/crates/apub/src/protocol/objects/group.rs +++ b/crates/apub/src/protocol/objects/group.rs @@ -55,17 +55,17 @@ pub struct Group { } impl Group { - pub(crate) async fn from_apub_to_form( - group: &Group, + pub(crate) async fn into_form( + self, expected_domain: &Url, settings: &Settings, ) -> Result { - check_is_apub_id_valid(group.id.inner(), true, settings)?; - verify_domains_match(expected_domain, group.id.inner())?; - let name = group.preferred_username.clone(); - let title = group.name.clone(); - let description = get_summary_from_string_or_source(&group.summary, &group.source); - let shared_inbox = group.endpoints.shared_inbox.clone().map(|s| s.into()); + check_is_apub_id_valid(self.id.inner(), true, settings)?; + verify_domains_match(expected_domain, self.id.inner())?; + let name = self.preferred_username; + let title = self.name; + let description = get_summary_from_string_or_source(&self.summary, &self.source); + let shared_inbox = self.endpoints.shared_inbox.map(|s| s.into()); let slur_regex = &settings.slur_regex(); check_slurs(&name, slur_regex)?; @@ -78,19 +78,19 @@ impl Group { title, description, removed: None, - published: group.published.map(|u| u.naive_local()), - updated: group.updated.map(|u| u.naive_local()), + published: self.published.map(|u| u.naive_local()), + updated: self.updated.map(|u| u.naive_local()), deleted: None, - nsfw: Some(group.sensitive.unwrap_or(false)), - actor_id: Some(group.id.clone().into()), + nsfw: Some(self.sensitive.unwrap_or(false)), + actor_id: Some(self.id.into()), local: Some(false), private_key: None, - public_key: Some(group.public_key.public_key_pem.clone()), + public_key: Some(self.public_key.public_key_pem), last_refreshed_at: Some(naive_now()), - icon: Some(group.icon.clone().map(|i| i.url.into())), - banner: Some(group.image.clone().map(|i| i.url.into())), - followers_url: Some(group.followers.clone().into()), - inbox_url: Some(group.inbox.clone().into()), + icon: Some(self.icon.map(|i| i.url.into())), + banner: Some(self.image.map(|i| i.url.into())), + followers_url: Some(self.followers.into()), + inbox_url: Some(self.inbox.into()), shared_inbox_url: Some(shared_inbox), }) } diff --git a/crates/apub_lib/src/object_id.rs b/crates/apub_lib/src/object_id.rs index fe55a44aa..52fe5b470 100644 --- a/crates/apub_lib/src/object_id.rs +++ b/crates/apub_lib/src/object_id.rs @@ -139,7 +139,7 @@ where let res2: Kind::ApubType = res.json().await?; - Ok(Kind::from_apub(&res2, data, self.inner(), request_counter).await?) + Ok(Kind::from_apub(res2, data, self.inner(), request_counter).await?) } } diff --git a/crates/apub_lib/src/traits.rs b/crates/apub_lib/src/traits.rs index 2d5424082..38b2d685d 100644 --- a/crates/apub_lib/src/traits.rs +++ b/crates/apub_lib/src/traits.rs @@ -41,7 +41,7 @@ pub trait ApubObject { async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError>; /// Trait for converting an object or actor into the respective ActivityPub type. - async fn to_apub(&self, data: &Self::DataType) -> Result; + async fn into_apub(self, data: &Self::DataType) -> Result; fn to_tombstone(&self) -> Result; /// Converts an object from ActivityPub type to Lemmy internal type. @@ -51,7 +51,7 @@ pub trait ApubObject { /// * `expected_domain` Domain where the object was received from. None in case of mod action. /// * `mod_action_allowed` True if the object can be a mod activity, ignore `expected_domain` in this case async fn from_apub( - apub: &Self::ApubType, + apub: Self::ApubType, data: &Self::DataType, expected_domain: &Url, request_counter: &mut i32, From 8ea21c39b7d25bf39e9d333040674b55cf640b50 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Sat, 6 Nov 2021 14:25:34 +0100 Subject: [PATCH 05/10] Reduce stack memory usage in apub code - use our own, smaller Endpoints struct - wrap ObjectId.url in Box - adjust usage of Box in different places --- crates/api/src/post.rs | 2 +- crates/api_crud/src/post/create.rs | 2 +- crates/apub/src/activities/community/update.rs | 16 +++++++--------- crates/apub/src/activities/deletion/mod.rs | 12 ++++++------ .../apub/src/activities/post/create_or_update.rs | 2 +- crates/apub/src/activities/voting/undo_vote.rs | 3 +-- crates/apub/src/activities/voting/vote.rs | 3 +-- crates/apub/src/activity_lists.rs | 10 +++++----- crates/apub/src/fetcher/post_or_comment.rs | 16 ++++++++-------- crates/apub/src/http/community.rs | 2 +- crates/apub/src/http/mod.rs | 2 +- crates/apub/src/objects/community.rs | 8 ++------ crates/apub/src/objects/person.rs | 8 +++++--- .../src/protocol/activities/community/update.rs | 2 +- crates/apub/src/protocol/objects/group.rs | 10 +++------- crates/apub/src/protocol/objects/mod.rs | 10 ++++++++++ crates/apub/src/protocol/objects/person.rs | 6 +++--- crates/apub_lib/src/object_id.rs | 9 +++++---- crates/apub_lib/src/signatures.rs | 4 ++-- crates/apub_lib/src/traits.rs | 2 +- 20 files changed, 65 insertions(+), 64 deletions(-) diff --git a/crates/api/src/post.rs b/crates/api/src/post.rs index c7acb08fb..f22104eb7 100644 --- a/crates/api/src/post.rs +++ b/crates/api/src/post.rs @@ -73,7 +73,7 @@ impl Perform for CreatePostLike { .await??; let community_id = post.community_id; - let object = PostOrComment::Post(Box::new(post)); + let object = PostOrComment::Post(post); // Only add the like if the score isnt 0 let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1); diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 248adee6c..1147c1a32 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -146,7 +146,7 @@ impl PerformCrud for CreatePost { context, ) .await?; - let object = PostOrComment::Post(Box::new(apub_post)); + let object = PostOrComment::Post(apub_post); Vote::send( &object, &local_user_view.person.clone().into(), diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index 688722479..f5d7e5651 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -9,7 +9,7 @@ use crate::{ }, activity_lists::AnnouncableActivities, objects::{community::ApubCommunity, person::ApubPerson}, - protocol::{activities::community::update::UpdateCommunity, objects::group::Group}, + protocol::activities::community::update::UpdateCommunity, }; use activitystreams::{activity::kind::UpdateType, public}; use lemmy_api_common::blocking; @@ -38,14 +38,14 @@ impl UpdateCommunity { let update = UpdateCommunity { actor: ObjectId::new(actor.actor_id()), to: vec![public()], - object: community.clone().into_apub(context).await?, + object: Box::new(community.clone().into_apub(context).await?), cc: vec![community.actor_id()], kind: UpdateType::Update, id: id.clone(), unparsed: Default::default(), }; - let activity = AnnouncableActivities::UpdateCommunity(Box::new(update)); + let activity = AnnouncableActivities::UpdateCommunity(update); send_to_community(activity, &id, actor, &community, vec![], context).await } } @@ -73,12 +73,10 @@ impl ActivityHandler for UpdateCommunity { ) -> Result<(), LemmyError> { let community = self.get_community(context, request_counter).await?; - let updated_community = Group::into_form( - self.object, - &community.actor_id.clone().into(), - &context.settings(), - ) - .await?; + let updated_community = self + .object + .into_form(&community.actor_id.clone().into(), &context.settings()) + .await?; let cf = CommunityForm { name: updated_community.name, title: updated_community.title, diff --git a/crates/apub/src/activities/deletion/mod.rs b/crates/apub/src/activities/deletion/mod.rs index ddd607a7c..1d5a3836f 100644 --- a/crates/apub/src/activities/deletion/mod.rs +++ b/crates/apub/src/activities/deletion/mod.rs @@ -53,9 +53,9 @@ pub async fn send_apub_remove( } pub enum DeletableObjects { - Community(Box), - Comment(Box), - Post(Box), + Community(ApubCommunity), + Comment(ApubComment), + Post(ApubPost), } impl DeletableObjects { @@ -64,13 +64,13 @@ impl DeletableObjects { context: &LemmyContext, ) -> Result { if let Some(c) = ApubCommunity::read_from_apub_id(ap_id.clone(), context).await? { - return Ok(DeletableObjects::Community(Box::new(c))); + return Ok(DeletableObjects::Community(c)); } if let Some(p) = ApubPost::read_from_apub_id(ap_id.clone(), context).await? { - return Ok(DeletableObjects::Post(Box::new(p))); + return Ok(DeletableObjects::Post(p)); } if let Some(c) = ApubComment::read_from_apub_id(ap_id.clone(), context).await? { - return Ok(DeletableObjects::Comment(Box::new(c))); + return Ok(DeletableObjects::Comment(c)); } Err(diesel::NotFound.into()) } diff --git a/crates/apub/src/activities/post/create_or_update.rs b/crates/apub/src/activities/post/create_or_update.rs index 982f90ccc..1c71c8ec1 100644 --- a/crates/apub/src/activities/post/create_or_update.rs +++ b/crates/apub/src/activities/post/create_or_update.rs @@ -61,7 +61,7 @@ impl CreateOrUpdatePost { .into(); let create_or_update = CreateOrUpdatePost::new(post, actor, &community, kind, context).await?; let id = create_or_update.id.clone(); - let activity = AnnouncableActivities::CreateOrUpdatePost(Box::new(create_or_update)); + let activity = AnnouncableActivities::CreateOrUpdatePost(create_or_update); send_to_community(activity, &id, actor, &community, vec![], context).await } } diff --git a/crates/apub/src/activities/voting/undo_vote.rs b/crates/apub/src/activities/voting/undo_vote.rs index 0fe40b628..6d6f3eaff 100644 --- a/crates/apub/src/activities/voting/undo_vote.rs +++ b/crates/apub/src/activities/voting/undo_vote.rs @@ -26,7 +26,6 @@ use lemmy_apub_lib::{ use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; -use std::ops::Deref; impl UndoVote { pub async fn send( @@ -90,7 +89,7 @@ impl ActivityHandler for UndoVote { .dereference(context, request_counter) .await?; match object { - PostOrComment::Post(p) => undo_vote_post(actor, p.deref(), context).await, + PostOrComment::Post(p) => undo_vote_post(actor, &p, context).await, PostOrComment::Comment(c) => undo_vote_comment(actor, &c, context).await, } } diff --git a/crates/apub/src/activities/voting/vote.rs b/crates/apub/src/activities/voting/vote.rs index 6b9bfbd2f..89e88fe64 100644 --- a/crates/apub/src/activities/voting/vote.rs +++ b/crates/apub/src/activities/voting/vote.rs @@ -26,7 +26,6 @@ use lemmy_db_schema::{ }; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; -use std::ops::Deref; impl Vote { pub(in crate::activities::voting) fn new( @@ -90,7 +89,7 @@ impl ActivityHandler for Vote { let actor = self.actor.dereference(context, request_counter).await?; let object = self.object.dereference(context, request_counter).await?; match object { - PostOrComment::Post(p) => vote_post(&self.kind, actor, p.deref(), context).await, + PostOrComment::Post(p) => vote_post(&self.kind, actor, &p, context).await, PostOrComment::Comment(c) => vote_comment(&self.kind, actor, &c, context).await, } } diff --git a/crates/apub/src/activity_lists.rs b/crates/apub/src/activity_lists.rs index 6c866b83b..2b695111f 100644 --- a/crates/apub/src/activity_lists.rs +++ b/crates/apub/src/activity_lists.rs @@ -38,7 +38,7 @@ pub enum SharedInboxActivities { GroupInboxActivities(GroupInboxActivities), // Note, pm activities need to be at the end, otherwise comments will end up here. We can probably // avoid this problem by replacing createpm.object with our own struct, instead of NoteExt. - PersonInboxActivities(PersonInboxActivities), + PersonInboxActivities(Box), } #[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] @@ -47,7 +47,7 @@ pub enum SharedInboxActivities { pub enum GroupInboxActivities { FollowCommunity(FollowCommunity), UndoFollowCommunity(UndoFollowCommunity), - AnnouncableActivities(AnnouncableActivities), + AnnouncableActivities(Box), Report(Report), } @@ -61,7 +61,7 @@ pub enum PersonInboxActivities { CreateOrUpdatePrivateMessage(CreateOrUpdatePrivateMessage), DeletePrivateMessage(DeletePrivateMessage), UndoDeletePrivateMessage(UndoDeletePrivateMessage), - AnnounceActivity(Box), + AnnounceActivity(AnnounceActivity), } #[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] @@ -69,12 +69,12 @@ pub enum PersonInboxActivities { #[activity_handler(LemmyContext)] pub enum AnnouncableActivities { CreateOrUpdateComment(CreateOrUpdateComment), - CreateOrUpdatePost(Box), + CreateOrUpdatePost(CreateOrUpdatePost), Vote(Vote), UndoVote(UndoVote), Delete(Delete), UndoDelete(UndoDelete), - UpdateCommunity(Box), + UpdateCommunity(UpdateCommunity), BlockUserFromCommunity(BlockUserFromCommunity), UndoBlockUserFromCommunity(UndoBlockUserFromCommunity), AddMod(AddMod), diff --git a/crates/apub/src/fetcher/post_or_comment.rs b/crates/apub/src/fetcher/post_or_comment.rs index 075b018e3..dc1546f9c 100644 --- a/crates/apub/src/fetcher/post_or_comment.rs +++ b/crates/apub/src/fetcher/post_or_comment.rs @@ -11,15 +11,15 @@ use url::Url; #[derive(Clone, Debug)] pub enum PostOrComment { - Post(Box), + Post(ApubPost), Comment(ApubComment), } #[derive(Deserialize)] #[serde(untagged)] pub enum PageOrNote { - Page(Box), - Note(Box), + Page(Page), + Note(Note), } #[async_trait::async_trait(?Send)] @@ -39,7 +39,7 @@ impl ApubObject for PostOrComment { ) -> Result, LemmyError> { let post = ApubPost::read_from_apub_id(object_id.clone(), data).await?; Ok(match post { - Some(o) => Some(PostOrComment::Post(Box::new(o))), + Some(o) => Some(PostOrComment::Post(o)), None => ApubComment::read_from_apub_id(object_id, data) .await? .map(PostOrComment::Comment), @@ -68,11 +68,11 @@ impl ApubObject for PostOrComment { request_counter: &mut i32, ) -> Result { Ok(match apub { - PageOrNote::Page(p) => PostOrComment::Post(Box::new( - ApubPost::from_apub(*p, context, expected_domain, request_counter).await?, - )), + PageOrNote::Page(p) => PostOrComment::Post( + ApubPost::from_apub(p, context, expected_domain, request_counter).await?, + ), PageOrNote::Note(n) => PostOrComment::Comment( - ApubComment::from_apub(*n, context, expected_domain, request_counter).await?, + ApubComment::from_apub(n, context, expected_domain, request_counter).await?, ), }) } diff --git a/crates/apub/src/http/community.rs b/crates/apub/src/http/community.rs index 10794d993..1854da98b 100644 --- a/crates/apub/src/http/community.rs +++ b/crates/apub/src/http/community.rs @@ -85,7 +85,7 @@ pub(in crate::http) async fn receive_group_inbox( let community = announcable.get_community(context, &mut 0).await?; verify_person_in_community(&actor_id, &community, context, &mut 0).await?; if community.local { - AnnounceActivity::send(announcable, &community, vec![], context).await?; + AnnounceActivity::send(*announcable, &community, vec![], context).await?; } } diff --git a/crates/apub/src/http/mod.rs b/crates/apub/src/http/mod.rs index 03b68b94b..b3288b0d9 100644 --- a/crates/apub/src/http/mod.rs +++ b/crates/apub/src/http/mod.rs @@ -52,7 +52,7 @@ pub async fn shared_inbox( receive_group_inbox(g, activity_data, request, &context).await } SharedInboxActivities::PersonInboxActivities(p) => { - receive_person_inbox(p, activity_data, request, &context).await + receive_person_inbox(*p, activity_data, request, &context).await } } } diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index 1eb58995c..35a19353f 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -4,15 +4,12 @@ use crate::{ generate_moderators_url, generate_outbox_url, protocol::{ - objects::{group::Group, tombstone::Tombstone}, + objects::{group::Group, tombstone::Tombstone, Endpoints}, ImageObject, Source, }, }; -use activitystreams::{ - actor::{kind::GroupType, Endpoints}, - object::kind::ImageType, -}; +use activitystreams::{actor::kind::GroupType, object::kind::ImageType}; use chrono::NaiveDateTime; use itertools::Itertools; use lemmy_api_common::blocking; @@ -111,7 +108,6 @@ impl ApubObject for ApubCommunity { followers: self.followers_url.clone().into(), endpoints: Endpoints { shared_inbox: self.shared_inbox_url.clone().map(|s| s.into()), - ..Default::default() }, public_key: self.get_public_key()?, published: Some(convert_datetime(self.published)), diff --git a/crates/apub/src/objects/person.rs b/crates/apub/src/objects/person.rs index dcaa9cd6d..5f494b70f 100644 --- a/crates/apub/src/objects/person.rs +++ b/crates/apub/src/objects/person.rs @@ -3,12 +3,15 @@ use crate::{ generate_outbox_url, objects::get_summary_from_string_or_source, protocol::{ - objects::person::{Person, UserTypes}, + objects::{ + person::{Person, UserTypes}, + Endpoints, + }, ImageObject, Source, }, }; -use activitystreams::{actor::Endpoints, object::kind::ImageType}; +use activitystreams::object::kind::ImageType; use chrono::NaiveDateTime; use lemmy_api_common::blocking; use lemmy_apub_lib::{ @@ -109,7 +112,6 @@ impl ApubObject for ApubPerson { outbox: generate_outbox_url(&self.actor_id)?.into(), endpoints: Endpoints { shared_inbox: self.shared_inbox_url.clone().map(|s| s.into()), - ..Default::default() }, public_key: self.get_public_key()?, updated: self.updated.map(convert_datetime), diff --git a/crates/apub/src/protocol/activities/community/update.rs b/crates/apub/src/protocol/activities/community/update.rs index b9877338a..9a831a1f8 100644 --- a/crates/apub/src/protocol/activities/community/update.rs +++ b/crates/apub/src/protocol/activities/community/update.rs @@ -12,7 +12,7 @@ pub struct UpdateCommunity { pub(crate) actor: ObjectId, pub(crate) to: Vec, // TODO: would be nice to use a separate struct here, which only contains the fields updated here - pub(crate) object: Group, + pub(crate) object: Box, pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: UpdateType, diff --git a/crates/apub/src/protocol/objects/group.rs b/crates/apub/src/protocol/objects/group.rs index acaf59092..a761a4425 100644 --- a/crates/apub/src/protocol/objects/group.rs +++ b/crates/apub/src/protocol/objects/group.rs @@ -5,12 +5,9 @@ use crate::{ community_outbox::ApubCommunityOutbox, }, objects::{community::ApubCommunity, get_summary_from_string_or_source}, - protocol::{ImageObject, Source}, -}; -use activitystreams::{ - actor::{kind::GroupType, Endpoints}, - unparsed::Unparsed, + protocol::{objects::Endpoints, ImageObject, Source}, }; +use activitystreams::{actor::kind::GroupType, unparsed::Unparsed}; use chrono::{DateTime, FixedOffset}; use lemmy_apub_lib::{object_id::ObjectId, signatures::PublicKey, verify::verify_domains_match}; use lemmy_db_schema::{naive_now, source::community::CommunityForm}; @@ -46,7 +43,7 @@ pub struct Group { pub(crate) inbox: Url, pub(crate) outbox: ObjectId, pub(crate) followers: Url, - pub(crate) endpoints: Endpoints, + pub(crate) endpoints: Endpoints, pub(crate) public_key: PublicKey, pub(crate) published: Option>, pub(crate) updated: Option>, @@ -72,7 +69,6 @@ impl Group { check_slurs(&title, slur_regex)?; check_slurs_opt(&description, slur_regex)?; - // TODO: test_parse_lemmy_community_moderators() keeps failing here with stack overflow Ok(CommunityForm { name, title, diff --git a/crates/apub/src/protocol/objects/mod.rs b/crates/apub/src/protocol/objects/mod.rs index 529ee6370..bf53d5c99 100644 --- a/crates/apub/src/protocol/objects/mod.rs +++ b/crates/apub/src/protocol/objects/mod.rs @@ -1,3 +1,6 @@ +use serde::{Deserialize, Serialize}; +use url::Url; + pub(crate) mod chat_message; pub(crate) mod group; pub(crate) mod note; @@ -5,6 +8,13 @@ pub(crate) mod page; pub(crate) mod person; pub(crate) mod tombstone; +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Endpoints { + #[serde(skip_serializing_if = "Option::is_none")] + pub shared_inbox: Option, +} + #[cfg(test)] mod tests { use crate::protocol::{ diff --git a/crates/apub/src/protocol/objects/person.rs b/crates/apub/src/protocol/objects/person.rs index cf9c10b1f..e45ea78c7 100644 --- a/crates/apub/src/protocol/objects/person.rs +++ b/crates/apub/src/protocol/objects/person.rs @@ -1,8 +1,8 @@ use crate::{ objects::person::ApubPerson, - protocol::{ImageObject, Source}, + protocol::{objects::Endpoints, ImageObject, Source}, }; -use activitystreams::{actor::Endpoints, unparsed::Unparsed, url::Url}; +use activitystreams::{unparsed::Unparsed, url::Url}; use chrono::{DateTime, FixedOffset}; use lemmy_apub_lib::{object_id::ObjectId, signatures::PublicKey}; use serde::{Deserialize, Serialize}; @@ -35,7 +35,7 @@ pub struct Person { pub(crate) inbox: Url, /// mandatory field in activitypub, currently empty in lemmy pub(crate) outbox: Url, - pub(crate) endpoints: Endpoints, + pub(crate) endpoints: Endpoints, pub(crate) public_key: PublicKey, pub(crate) published: Option>, pub(crate) updated: Option>, diff --git a/crates/apub_lib/src/object_id.rs b/crates/apub_lib/src/object_id.rs index 52fe5b470..8e4b70a23 100644 --- a/crates/apub_lib/src/object_id.rs +++ b/crates/apub_lib/src/object_id.rs @@ -28,9 +28,10 @@ lazy_static! { .unwrap(); } +/// We store Url on the heap because it is quite large (88 bytes). #[derive(Clone, PartialEq, Serialize, Deserialize, Debug)] #[serde(transparent)] -pub struct ObjectId(Url, #[serde(skip)] PhantomData) +pub struct ObjectId(Box, #[serde(skip)] PhantomData) where Kind: ApubObject + Send + 'static, for<'de2> ::ApubType: serde::Deserialize<'de2>; @@ -44,7 +45,7 @@ where where T: Into, { - ObjectId(url.into(), PhantomData::) + ObjectId(Box::new(url.into()), PhantomData::) } pub fn inner(&self) -> &Url { @@ -103,7 +104,7 @@ where data: &::DataType, ) -> Result, LemmyError> { let id = self.0.clone(); - ApubObject::read_from_apub_id(id, data).await + ApubObject::read_from_apub_id(*id, data).await } async fn dereference_from_http( @@ -181,7 +182,7 @@ where for<'de2> ::ApubType: serde::Deserialize<'de2>, { fn from(id: ObjectId) -> Self { - id.0 + *id.0 } } diff --git a/crates/apub_lib/src/signatures.rs b/crates/apub_lib/src/signatures.rs index df9590685..ccc720815 100644 --- a/crates/apub_lib/src/signatures.rs +++ b/crates/apub_lib/src/signatures.rs @@ -91,7 +91,7 @@ pub fn verify_signature(request: &HttpRequest, public_key: &str) -> Result<(), L #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct PublicKey { - pub id: String, - pub owner: Url, + pub(crate) id: String, + pub(crate) owner: Box, pub public_key_pem: String, } diff --git a/crates/apub_lib/src/traits.rs b/crates/apub_lib/src/traits.rs index 38b2d685d..18b33ba65 100644 --- a/crates/apub_lib/src/traits.rs +++ b/crates/apub_lib/src/traits.rs @@ -82,7 +82,7 @@ pub trait ActorType { fn get_public_key(&self) -> Result { Ok(PublicKey { id: format!("{}#main-key", self.actor_id()), - owner: self.actor_id(), + owner: Box::new(self.actor_id()), public_key_pem: self.public_key().context(location_info!())?, }) } From 02ce7bdc7d2df4fc2e5a0405496362faf31058ca Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Sat, 6 Nov 2021 15:01:00 +0100 Subject: [PATCH 06/10] Remove unused ActorType methods --- crates/apub/src/fetcher/user_or_community.rs | 8 -------- crates/apub/src/objects/community.rs | 6 ------ crates/apub/src/objects/person.rs | 6 ------ crates/apub_lib/src/traits.rs | 2 -- 4 files changed, 22 deletions(-) diff --git a/crates/apub/src/fetcher/user_or_community.rs b/crates/apub/src/fetcher/user_or_community.rs index eccda7c65..5f7c388ed 100644 --- a/crates/apub/src/fetcher/user_or_community.rs +++ b/crates/apub/src/fetcher/user_or_community.rs @@ -80,18 +80,10 @@ impl ApubObject for UserOrCommunity { } impl ActorType for UserOrCommunity { - fn is_local(&self) -> bool { - todo!() - } - fn actor_id(&self) -> Url { todo!() } - fn name(&self) -> String { - todo!() - } - fn public_key(&self) -> Option { match self { UserOrCommunity::User(p) => p.public_key(), diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index 35a19353f..f6737a3a8 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -161,15 +161,9 @@ impl ApubObject for ApubCommunity { } impl ActorType for ApubCommunity { - fn is_local(&self) -> bool { - self.local - } fn actor_id(&self) -> Url { self.actor_id.to_owned().into() } - fn name(&self) -> String { - self.name.clone() - } fn public_key(&self) -> Option { self.public_key.to_owned() } diff --git a/crates/apub/src/objects/person.rs b/crates/apub/src/objects/person.rs index 5f494b70f..ea0883214 100644 --- a/crates/apub/src/objects/person.rs +++ b/crates/apub/src/objects/person.rs @@ -178,15 +178,9 @@ impl ApubObject for ApubPerson { } impl ActorType for ApubPerson { - fn is_local(&self) -> bool { - self.local - } fn actor_id(&self) -> Url { self.actor_id.to_owned().into() } - fn name(&self) -> String { - self.name.clone() - } fn public_key(&self) -> Option { self.public_key.to_owned() diff --git a/crates/apub_lib/src/traits.rs b/crates/apub_lib/src/traits.rs index 18b33ba65..e5dcbc1ed 100644 --- a/crates/apub_lib/src/traits.rs +++ b/crates/apub_lib/src/traits.rs @@ -63,9 +63,7 @@ pub trait ApubObject { /// Common methods provided by ActivityPub actors (community and person). Not all methods are /// implemented by all actors. pub trait ActorType { - fn is_local(&self) -> bool; fn actor_id(&self) -> Url; - fn name(&self) -> String; // TODO: this should not be an option (needs db migration in lemmy) fn public_key(&self) -> Option; From a5a674a270f0b9daf8519b5dd30c83fc2c8c3488 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Sat, 6 Nov 2021 18:35:14 +0100 Subject: [PATCH 07/10] Add method ApubObject.verify() --- .../activities/comment/create_or_update.rs | 7 +-- .../apub/src/activities/community/update.rs | 12 ++-- .../src/activities/post/create_or_update.rs | 6 +- .../private_message/create_or_update.rs | 5 +- .../src/collections/community_moderators.rs | 17 +++++- .../apub/src/collections/community_outbox.rs | 12 +++- crates/apub/src/fetcher/post_or_comment.rs | 25 +++++--- crates/apub/src/fetcher/search.rs | 31 ++++++++-- crates/apub/src/fetcher/user_or_community.rs | 29 +++++++--- crates/apub/src/objects/comment.rs | 57 ++++++++++++------ crates/apub/src/objects/community.rs | 17 +++++- crates/apub/src/objects/person.rs | 58 +++++++++++-------- crates/apub/src/objects/post.rs | 34 ++++++++--- crates/apub/src/objects/private_message.rs | 44 +++++++++++--- .../apub/src/protocol/objects/chat_message.rs | 23 +------- crates/apub/src/protocol/objects/group.rs | 34 +++++------ crates/apub/src/protocol/objects/note.rs | 34 +---------- crates/apub/src/protocol/objects/page.rs | 19 +----- crates/apub_lib/src/object_id.rs | 3 +- crates/apub_lib/src/traits.rs | 8 ++- 20 files changed, 284 insertions(+), 191 deletions(-) diff --git a/crates/apub/src/activities/comment/create_or_update.rs b/crates/apub/src/activities/comment/create_or_update.rs index 0095a511d..1ba2c8bb5 100644 --- a/crates/apub/src/activities/comment/create_or_update.rs +++ b/crates/apub/src/activities/comment/create_or_update.rs @@ -85,9 +85,7 @@ impl ActivityHandler for CreateOrUpdateComment { check_community_deleted_or_removed(&community)?; check_post_deleted_or_removed(&post)?; - // TODO: should add a check that the correct community is in cc (probably needs changes to - // comment deserialization) - self.object.verify(context, request_counter).await?; + ApubComment::verify(&self.object, self.actor.inner(), context, request_counter).await?; Ok(()) } @@ -96,8 +94,7 @@ impl ActivityHandler for CreateOrUpdateComment { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let comment = - ApubComment::from_apub(self.object, context, self.actor.inner(), request_counter).await?; + let comment = ApubComment::from_apub(self.object, context, request_counter).await?; let recipients = get_notif_recipients(&self.actor, &comment, context, request_counter).await?; let notif_type = match self.kind { CreateOrUpdateType::Create => UserOperationCrud::CreateComment, diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index f5d7e5651..eebfe336c 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -63,6 +63,13 @@ impl ActivityHandler for UpdateCommunity { let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; verify_mod_action(&self.actor, &community, context, request_counter).await?; + ApubCommunity::verify( + &self.object, + &community.actor_id.clone().into(), + context, + request_counter, + ) + .await?; Ok(()) } @@ -73,10 +80,7 @@ impl ActivityHandler for UpdateCommunity { ) -> Result<(), LemmyError> { let community = self.get_community(context, request_counter).await?; - let updated_community = self - .object - .into_form(&community.actor_id.clone().into(), &context.settings()) - .await?; + let updated_community = self.object.into_form()?; let cf = CommunityForm { name: updated_community.name, title: updated_community.title, diff --git a/crates/apub/src/activities/post/create_or_update.rs b/crates/apub/src/activities/post/create_or_update.rs index 1c71c8ec1..db5d725fc 100644 --- a/crates/apub/src/activities/post/create_or_update.rs +++ b/crates/apub/src/activities/post/create_or_update.rs @@ -104,7 +104,7 @@ impl ActivityHandler for CreateOrUpdatePost { } } } - self.object.verify(context, request_counter).await?; + ApubPost::verify(&self.object, self.actor.inner(), context, request_counter).await?; Ok(()) } @@ -113,9 +113,7 @@ impl ActivityHandler for CreateOrUpdatePost { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - let actor = self.actor.dereference(context, request_counter).await?; - let post = - ApubPost::from_apub(self.object, context, &actor.actor_id(), request_counter).await?; + let post = ApubPost::from_apub(self.object, context, request_counter).await?; let notif_type = match self.kind { CreateOrUpdateType::Create => UserOperationCrud::CreatePost, diff --git a/crates/apub/src/activities/private_message/create_or_update.rs b/crates/apub/src/activities/private_message/create_or_update.rs index 7f40b5fbc..e3d72f54a 100644 --- a/crates/apub/src/activities/private_message/create_or_update.rs +++ b/crates/apub/src/activities/private_message/create_or_update.rs @@ -57,7 +57,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage { verify_activity(&self.id, self.actor.inner(), &context.settings())?; verify_person(&self.actor, context, request_counter).await?; verify_domains_match(self.actor.inner(), self.object.id.inner())?; - self.object.verify(context, request_counter).await?; + ApubPrivateMessage::verify(&self.object, self.actor.inner(), context, request_counter).await?; Ok(()) } @@ -67,8 +67,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage { request_counter: &mut i32, ) -> Result<(), LemmyError> { let private_message = - ApubPrivateMessage::from_apub(self.object, context, self.actor.inner(), request_counter) - .await?; + ApubPrivateMessage::from_apub(self.object, context, request_counter).await?; let notif_type = match self.kind { CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage, diff --git a/crates/apub/src/collections/community_moderators.rs b/crates/apub/src/collections/community_moderators.rs index cbbe66708..695f7aca1 100644 --- a/crates/apub/src/collections/community_moderators.rs +++ b/crates/apub/src/collections/community_moderators.rs @@ -66,13 +66,21 @@ impl ApubObject for ApubCommunityModerators { unimplemented!() } + async fn verify( + group_moderators: &GroupModerators, + expected_domain: &Url, + _context: &CommunityContext, + _request_counter: &mut i32, + ) -> Result<(), LemmyError> { + verify_domains_match(&group_moderators.id, expected_domain)?; + Ok(()) + } + async fn from_apub( apub: Self::ApubType, data: &Self::DataType, - expected_domain: &Url, request_counter: &mut i32, ) -> Result { - verify_domains_match(expected_domain, &apub.id)?; let community_id = data.0.id; let current_moderators = blocking(data.1.pool(), move |conn| { CommunityModeratorView::for_community(conn, community_id) @@ -165,7 +173,10 @@ mod tests { 0: community, 1: context, }; - ApubCommunityModerators::from_apub(json, &community_context, &url, &mut request_counter) + ApubCommunityModerators::verify(&json, &url, &community_context, &mut request_counter) + .await + .unwrap(); + ApubCommunityModerators::from_apub(json, &community_context, &mut request_counter) .await .unwrap(); assert_eq!(request_counter, 0); diff --git a/crates/apub/src/collections/community_outbox.rs b/crates/apub/src/collections/community_outbox.rs index cbad5c484..3632f61a7 100644 --- a/crates/apub/src/collections/community_outbox.rs +++ b/crates/apub/src/collections/community_outbox.rs @@ -85,13 +85,21 @@ impl ApubObject for ApubCommunityOutbox { unimplemented!() } + async fn verify( + group_outbox: &GroupOutbox, + expected_domain: &Url, + _context: &CommunityContext, + _request_counter: &mut i32, + ) -> Result<(), LemmyError> { + verify_domains_match(expected_domain, &group_outbox.id)?; + Ok(()) + } + async fn from_apub( apub: Self::ApubType, data: &Self::DataType, - expected_domain: &Url, request_counter: &mut i32, ) -> Result { - verify_domains_match(expected_domain, &apub.id)?; let mut outbox_activities = apub.ordered_items; if outbox_activities.len() > 20 { outbox_activities = outbox_activities[0..20].to_vec(); diff --git a/crates/apub/src/fetcher/post_or_comment.rs b/crates/apub/src/fetcher/post_or_comment.rs index dc1546f9c..2ca84bee1 100644 --- a/crates/apub/src/fetcher/post_or_comment.rs +++ b/crates/apub/src/fetcher/post_or_comment.rs @@ -61,19 +61,30 @@ impl ApubObject for PostOrComment { unimplemented!() } + async fn verify( + apub: &Self::ApubType, + expected_domain: &Url, + data: &Self::DataType, + request_counter: &mut i32, + ) -> Result<(), LemmyError> { + match apub { + PageOrNote::Page(a) => ApubPost::verify(a, expected_domain, data, request_counter).await, + PageOrNote::Note(a) => ApubComment::verify(a, expected_domain, data, request_counter).await, + } + } + async fn from_apub( apub: PageOrNote, context: &LemmyContext, - expected_domain: &Url, request_counter: &mut i32, ) -> Result { Ok(match apub { - PageOrNote::Page(p) => PostOrComment::Post( - ApubPost::from_apub(p, context, expected_domain, request_counter).await?, - ), - PageOrNote::Note(n) => PostOrComment::Comment( - ApubComment::from_apub(n, context, expected_domain, request_counter).await?, - ), + PageOrNote::Page(p) => { + PostOrComment::Post(ApubPost::from_apub(p, context, request_counter).await?) + } + PageOrNote::Note(n) => { + PostOrComment::Comment(ApubComment::from_apub(n, context, request_counter).await?) + } }) } } diff --git a/crates/apub/src/fetcher/search.rs b/crates/apub/src/fetcher/search.rs index 557fc1b54..1c03a10bd 100644 --- a/crates/apub/src/fetcher/search.rs +++ b/crates/apub/src/fetcher/search.rs @@ -163,19 +163,40 @@ impl ApubObject for SearchableObjects { unimplemented!() } + async fn verify( + apub: &Self::ApubType, + expected_domain: &Url, + data: &Self::DataType, + request_counter: &mut i32, + ) -> Result<(), LemmyError> { + match apub { + SearchableApubTypes::Group(a) => { + ApubCommunity::verify(a, expected_domain, data, request_counter).await + } + SearchableApubTypes::Person(a) => { + ApubPerson::verify(a, expected_domain, data, request_counter).await + } + SearchableApubTypes::Page(a) => { + ApubPost::verify(a, expected_domain, data, request_counter).await + } + SearchableApubTypes::Note(a) => { + ApubComment::verify(a, expected_domain, data, request_counter).await + } + } + } + async fn from_apub( apub: Self::ApubType, context: &LemmyContext, - ed: &Url, rc: &mut i32, ) -> Result { use SearchableApubTypes as SAT; use SearchableObjects as SO; Ok(match apub { - SAT::Group(g) => SO::Community(ApubCommunity::from_apub(g, context, ed, rc).await?), - SAT::Person(p) => SO::Person(ApubPerson::from_apub(p, context, ed, rc).await?), - SAT::Page(p) => SO::Post(ApubPost::from_apub(p, context, ed, rc).await?), - SAT::Note(n) => SO::Comment(ApubComment::from_apub(n, context, ed, rc).await?), + SAT::Group(g) => SO::Community(ApubCommunity::from_apub(g, context, rc).await?), + SAT::Person(p) => SO::Person(ApubPerson::from_apub(p, context, rc).await?), + SAT::Page(p) => SO::Post(ApubPost::from_apub(p, context, rc).await?), + SAT::Note(n) => SO::Comment(ApubComment::from_apub(n, context, rc).await?), }) } } diff --git a/crates/apub/src/fetcher/user_or_community.rs b/crates/apub/src/fetcher/user_or_community.rs index 5f7c388ed..e5bc49ba8 100644 --- a/crates/apub/src/fetcher/user_or_community.rs +++ b/crates/apub/src/fetcher/user_or_community.rs @@ -62,19 +62,34 @@ impl ApubObject for UserOrCommunity { unimplemented!() } + async fn verify( + apub: &Self::ApubType, + expected_domain: &Url, + data: &Self::DataType, + request_counter: &mut i32, + ) -> Result<(), LemmyError> { + match apub { + PersonOrGroup::Person(a) => { + ApubPerson::verify(a, expected_domain, data, request_counter).await + } + PersonOrGroup::Group(a) => { + ApubCommunity::verify(a, expected_domain, data, request_counter).await + } + } + } + async fn from_apub( apub: Self::ApubType, data: &Self::DataType, - expected_domain: &Url, request_counter: &mut i32, ) -> Result { Ok(match apub { - PersonOrGroup::Person(p) => UserOrCommunity::User( - ApubPerson::from_apub(p, data, expected_domain, request_counter).await?, - ), - PersonOrGroup::Group(p) => UserOrCommunity::Community( - ApubCommunity::from_apub(p, data, expected_domain, request_counter).await?, - ), + PersonOrGroup::Person(p) => { + UserOrCommunity::User(ApubPerson::from_apub(p, data, request_counter).await?) + } + PersonOrGroup::Group(p) => { + UserOrCommunity::Community(ApubCommunity::from_apub(p, data, request_counter).await?) + } }) } } diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs index da96f8fab..d0f74acfa 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -1,5 +1,5 @@ use crate::{ - activities::verify_person_in_community, + activities::{verify_is_public, verify_person_in_community}, check_is_apub_id_valid, protocol::{ objects::{ @@ -129,21 +129,16 @@ impl ApubObject for ApubComment { )) } - /// Converts a `Note` to `Comment`. - /// - /// If the parent community, post and comment(s) are not known locally, these are also fetched. - async fn from_apub( - note: Note, - context: &LemmyContext, + async fn verify( + note: &Note, expected_domain: &Url, + context: &LemmyContext, request_counter: &mut i32, - ) -> Result { + ) -> Result<(), LemmyError> { verify_domains_match(note.id.inner(), expected_domain)?; - let creator = note - .attributed_to - .dereference(context, request_counter) - .await?; - let (post, parent_comment_id) = note.get_parents(context, request_counter).await?; + verify_domains_match(note.attributed_to.inner(), note.id.inner())?; + verify_is_public(¬e.to)?; + let (post, _) = note.get_parents(context, request_counter).await?; let community_id = post.community_id; let community = blocking(context.pool(), move |conn| { Community::read(conn, community_id) @@ -160,6 +155,22 @@ impl ApubObject for ApubComment { if post.locked { return Err(anyhow!("Post is locked").into()); } + Ok(()) + } + + /// Converts a `Note` to `Comment`. + /// + /// If the parent community, post and comment(s) are not known locally, these are also fetched. + async fn from_apub( + note: Note, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { + let creator = note + .attributed_to + .dereference(context, request_counter) + .await?; + let (post, parent_comment_id) = note.get_parents(context, request_counter).await?; let content = if let SourceCompat::Lemmy(source) = ¬e.source { source.content.clone() @@ -205,7 +216,10 @@ pub(crate) mod tests { let person = parse_lemmy_person(context).await; let community = parse_lemmy_community(context).await; let post_json = file_to_json_object("assets/lemmy/objects/page.json"); - let post = ApubPost::from_apub(post_json, context, url, &mut 0) + ApubPost::verify(&post_json, url, context, &mut 0) + .await + .unwrap(); + let post = ApubPost::from_apub(post_json, context, &mut 0) .await .unwrap(); (person, community, post) @@ -226,7 +240,10 @@ pub(crate) mod tests { let json: Note = file_to_json_object("assets/lemmy/objects/note.json"); let mut request_counter = 0; - let comment = ApubComment::from_apub(json.clone(), &context, &url, &mut request_counter) + ApubComment::verify(&json, &url, &context, &mut request_counter) + .await + .unwrap(); + let comment = ApubComment::from_apub(json.clone(), &context, &mut request_counter) .await .unwrap(); @@ -254,12 +271,18 @@ pub(crate) mod tests { Url::parse("https://queer.hacktivis.me/objects/8d4973f4-53de-49cd-8c27-df160e16a9c2") .unwrap(); let person_json = file_to_json_object("assets/pleroma/objects/person.json"); - ApubPerson::from_apub(person_json, &context, &pleroma_url, &mut 0) + ApubPerson::verify(&person_json, &pleroma_url, &context, &mut 0) + .await + .unwrap(); + ApubPerson::from_apub(person_json, &context, &mut 0) .await .unwrap(); let json = file_to_json_object("assets/pleroma/objects/note.json"); let mut request_counter = 0; - let comment = ApubComment::from_apub(json, &context, &pleroma_url, &mut request_counter) + ApubComment::verify(&json, &pleroma_url, &context, &mut request_counter) + .await + .unwrap(); + let comment = ApubComment::from_apub(json, &context, &mut request_counter) .await .unwrap(); diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index f6737a3a8..21ca9d4f5 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -124,14 +124,22 @@ impl ApubObject for ApubCommunity { )) } + async fn verify( + group: &Group, + expected_domain: &Url, + context: &LemmyContext, + _request_counter: &mut i32, + ) -> Result<(), LemmyError> { + group.verify(expected_domain, context).await + } + /// Converts a `Group` to `Community`, inserts it into the database and updates moderators. async fn from_apub( group: Group, context: &LemmyContext, - expected_domain: &Url, request_counter: &mut i32, ) -> Result { - let form = Group::into_form(group.clone(), expected_domain, &context.settings()).await?; + let form = Group::into_form(group.clone())?; // Fetching mods and outbox is not necessary for Lemmy to work, so ignore errors. Besides, // we need to ignore these errors so that tests can work entirely offline. @@ -232,7 +240,10 @@ pub(crate) mod tests { let url = Url::parse("https://enterprise.lemmy.ml/c/tenforward").unwrap(); let mut request_counter = 0; - let community = ApubCommunity::from_apub(json, context, &url, &mut request_counter) + ApubCommunity::verify(&json, &url, context, &mut request_counter) + .await + .unwrap(); + let community = ApubCommunity::from_apub(json, context, &mut request_counter) .await .unwrap(); // this makes two requests to the (intentionally) broken outbox/moderators collections diff --git a/crates/apub/src/objects/person.rs b/crates/apub/src/objects/person.rs index ea0883214..e3fcdd2ee 100644 --- a/crates/apub/src/objects/person.rs +++ b/crates/apub/src/objects/person.rs @@ -125,32 +125,31 @@ impl ApubObject for ApubPerson { unimplemented!() } + async fn verify( + person: &Person, + expected_domain: &Url, + context: &LemmyContext, + _request_counter: &mut i32, + ) -> Result<(), LemmyError> { + verify_domains_match(person.id.inner(), expected_domain)?; + check_is_apub_id_valid(person.id.inner(), false, &context.settings())?; + + let slur_regex = &context.settings().slur_regex(); + check_slurs(&person.preferred_username, slur_regex)?; + check_slurs_opt(&person.name, slur_regex)?; + let bio = get_summary_from_string_or_source(&person.summary, &person.source); + check_slurs_opt(&bio, slur_regex)?; + Ok(()) + } + async fn from_apub( person: Person, context: &LemmyContext, - expected_domain: &Url, _request_counter: &mut i32, ) -> Result { - verify_domains_match(person.id.inner(), expected_domain)?; - let name = person.preferred_username; - let display_name: Option = person.name; - let bio = get_summary_from_string_or_source(&person.summary, &person.source); - let shared_inbox = person.endpoints.shared_inbox.map(|s| s.into()); - let bot_account = match person.kind { - UserTypes::Person => false, - UserTypes::Service => true, - }; - - let slur_regex = &context.settings().slur_regex(); - check_slurs(&name, slur_regex)?; - check_slurs_opt(&display_name, slur_regex)?; - check_slurs_opt(&bio, slur_regex)?; - - check_is_apub_id_valid(person.id.inner(), false, &context.settings())?; - let person_form = PersonForm { - name, - display_name: Some(display_name), + name: person.preferred_username, + display_name: Some(person.name), banned: None, deleted: None, avatar: Some(person.icon.map(|i| i.url.into())), @@ -158,15 +157,18 @@ impl ApubObject for ApubPerson { published: person.published.map(|u| u.naive_local()), updated: person.updated.map(|u| u.naive_local()), actor_id: Some(person.id.into()), - bio: Some(bio), + bio: Some(get_summary_from_string_or_source( + &person.summary, + &person.source, + )), local: Some(false), admin: Some(false), - bot_account: Some(bot_account), + bot_account: Some(person.kind == UserTypes::Service), private_key: None, public_key: Some(Some(person.public_key.public_key_pem)), last_refreshed_at: Some(naive_now()), inbox_url: Some(person.inbox.into()), - shared_inbox_url: Some(shared_inbox), + shared_inbox_url: Some(person.endpoints.shared_inbox.map(|s| s.into())), matrix_user_id: Some(person.matrix_user_id), }; let person = blocking(context.pool(), move |conn| { @@ -210,7 +212,10 @@ pub(crate) mod tests { let json = file_to_json_object("assets/lemmy/objects/person.json"); let url = Url::parse("https://enterprise.lemmy.ml/u/picard").unwrap(); let mut request_counter = 0; - let person = ApubPerson::from_apub(json, context, &url, &mut request_counter) + ApubPerson::verify(&json, &url, context, &mut request_counter) + .await + .unwrap(); + let person = ApubPerson::from_apub(json, context, &mut request_counter) .await .unwrap(); assert_eq!(request_counter, 0); @@ -238,7 +243,10 @@ pub(crate) mod tests { let json = file_to_json_object("assets/pleroma/objects/person.json"); let url = Url::parse("https://queer.hacktivis.me/users/lanodan").unwrap(); let mut request_counter = 0; - let person = ApubPerson::from_apub(json, &context, &url, &mut request_counter) + ApubPerson::verify(&json, &url, &context, &mut request_counter) + .await + .unwrap(); + let person = ApubPerson::from_apub(json, &context, &mut request_counter) .await .unwrap(); diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index bbb5537e2..9e68cbb1d 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -1,5 +1,5 @@ use crate::{ - activities::verify_person_in_community, + activities::{verify_is_public, verify_person_in_community}, check_is_apub_id_valid, protocol::{ objects::{page::Page, tombstone::Tombstone}, @@ -30,7 +30,7 @@ use lemmy_db_schema::{ }; use lemmy_utils::{ request::fetch_site_data, - utils::{convert_datetime, markdown_to_html, remove_slurs}, + utils::{check_slurs, convert_datetime, markdown_to_html, remove_slurs}, LemmyError, }; use lemmy_websocket::LemmyContext; @@ -133,24 +133,37 @@ impl ApubObject for ApubPost { )) } - async fn from_apub( - page: Page, - context: &LemmyContext, + async fn verify( + page: &Page, expected_domain: &Url, + context: &LemmyContext, request_counter: &mut i32, - ) -> Result { + ) -> Result<(), LemmyError> { // We can't verify the domain in case of mod action, because the mod may be on a different // instance from the post author. if !page.is_mod_action(context).await? { verify_domains_match(page.id.inner(), expected_domain)?; }; + + let community = page.extract_community(context, request_counter).await?; + check_is_apub_id_valid(page.id.inner(), community.local, &context.settings())?; + verify_person_in_community(&page.attributed_to, &community, context, request_counter).await?; + check_slurs(&page.name, &context.settings().slur_regex())?; + verify_domains_match(page.attributed_to.inner(), page.id.inner())?; + verify_is_public(&page.to.clone())?; + Ok(()) + } + + async fn from_apub( + page: Page, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result { let creator = page .attributed_to .dereference(context, request_counter) .await?; let community = page.extract_community(context, request_counter).await?; - check_is_apub_id_valid(page.id.inner(), community.local, &context.settings())?; - verify_person_in_community(&page.attributed_to, &community, context, request_counter).await?; let thumbnail_url: Option = page.image.map(|i| i.url); let (metadata_res, pictrs_thumbnail) = if let Some(url) = &page.url { @@ -212,7 +225,10 @@ mod tests { let json = file_to_json_object("assets/lemmy/objects/page.json"); let url = Url::parse("https://enterprise.lemmy.ml/post/55143").unwrap(); let mut request_counter = 0; - let post = ApubPost::from_apub(json, &context, &url, &mut request_counter) + ApubPost::verify(&json, &url, &context, &mut request_counter) + .await + .unwrap(); + let post = ApubPost::from_apub(json, &context, &mut request_counter) .await .unwrap(); diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs index 334f37c5f..30c8e4dc5 100644 --- a/crates/apub/src/objects/private_message.rs +++ b/crates/apub/src/objects/private_message.rs @@ -2,6 +2,7 @@ use crate::protocol::{ objects::chat_message::{ChatMessage, ChatMessageType}, Source, }; +use anyhow::anyhow; use chrono::NaiveDateTime; use html2md::parse_html; use lemmy_api_common::blocking; @@ -100,14 +101,29 @@ impl ApubObject for ApubPrivateMessage { unimplemented!() } + async fn verify( + note: &ChatMessage, + expected_domain: &Url, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result<(), LemmyError> { + verify_domains_match(note.id.inner(), expected_domain)?; + verify_domains_match(note.attributed_to.inner(), note.id.inner())?; + let person = note + .attributed_to + .dereference(context, request_counter) + .await?; + if person.banned { + return Err(anyhow!("Person is banned from site").into()); + } + Ok(()) + } + async fn from_apub( note: ChatMessage, context: &LemmyContext, - expected_domain: &Url, request_counter: &mut i32, ) -> Result { - verify_domains_match(note.id.inner(), expected_domain)?; - let ap_id = Some(note.id.into()); let creator = note .attributed_to .dereference(context, request_counter) @@ -127,7 +143,7 @@ impl ApubObject for ApubPrivateMessage { updated: note.updated.map(|u| u.naive_local()), deleted: None, read: None, - ap_id, + ap_id: Some(note.id.into()), local: Some(false), }; let pm = blocking(context.pool(), move |conn| { @@ -150,12 +166,18 @@ mod tests { async fn prepare_comment_test(url: &Url, context: &LemmyContext) -> (ApubPerson, ApubPerson) { let lemmy_person = file_to_json_object("assets/lemmy/objects/person.json"); - let person1 = ApubPerson::from_apub(lemmy_person, context, url, &mut 0) + ApubPerson::verify(&lemmy_person, url, context, &mut 0) + .await + .unwrap(); + let person1 = ApubPerson::from_apub(lemmy_person, context, &mut 0) .await .unwrap(); let pleroma_person = file_to_json_object("assets/pleroma/objects/person.json"); let pleroma_url = Url::parse("https://queer.hacktivis.me/users/lanodan").unwrap(); - let person2 = ApubPerson::from_apub(pleroma_person, context, &pleroma_url, &mut 0) + ApubPerson::verify(&pleroma_person, &pleroma_url, context, &mut 0) + .await + .unwrap(); + let person2 = ApubPerson::from_apub(pleroma_person, context, &mut 0) .await .unwrap(); (person1, person2) @@ -174,7 +196,10 @@ mod tests { let data = prepare_comment_test(&url, &context).await; let json: ChatMessage = file_to_json_object("assets/lemmy/objects/chat_message.json"); let mut request_counter = 0; - let pm = ApubPrivateMessage::from_apub(json.clone(), &context, &url, &mut request_counter) + ApubPrivateMessage::verify(&json, &url, &context, &mut request_counter) + .await + .unwrap(); + let pm = ApubPrivateMessage::from_apub(json.clone(), &context, &mut request_counter) .await .unwrap(); @@ -199,7 +224,10 @@ mod tests { let pleroma_url = Url::parse("https://queer.hacktivis.me/objects/2").unwrap(); let json = file_to_json_object("assets/pleroma/objects/chat_message.json"); let mut request_counter = 0; - let pm = ApubPrivateMessage::from_apub(json, &context, &pleroma_url, &mut request_counter) + ApubPrivateMessage::verify(&json, &pleroma_url, &context, &mut request_counter) + .await + .unwrap(); + let pm = ApubPrivateMessage::from_apub(json, &context, &mut request_counter) .await .unwrap(); diff --git a/crates/apub/src/protocol/objects/chat_message.rs b/crates/apub/src/protocol/objects/chat_message.rs index 3a019967e..b86929139 100644 --- a/crates/apub/src/protocol/objects/chat_message.rs +++ b/crates/apub/src/protocol/objects/chat_message.rs @@ -6,10 +6,7 @@ use activitystreams::{ chrono::{DateTime, FixedOffset}, unparsed::Unparsed, }; -use anyhow::anyhow; -use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml, verify::verify_domains_match}; -use lemmy_utils::LemmyError; -use lemmy_websocket::LemmyContext; +use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; @@ -35,21 +32,3 @@ pub struct ChatMessage { pub enum ChatMessageType { ChatMessage, } - -impl ChatMessage { - pub(crate) async fn verify( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result<(), LemmyError> { - verify_domains_match(self.attributed_to.inner(), self.id.inner())?; - let person = self - .attributed_to - .dereference(context, request_counter) - .await?; - if person.banned { - return Err(anyhow!("Person is banned from site").into()); - } - Ok(()) - } -} diff --git a/crates/apub/src/protocol/objects/group.rs b/crates/apub/src/protocol/objects/group.rs index a761a4425..8a6e67203 100644 --- a/crates/apub/src/protocol/objects/group.rs +++ b/crates/apub/src/protocol/objects/group.rs @@ -12,10 +12,10 @@ use chrono::{DateTime, FixedOffset}; use lemmy_apub_lib::{object_id::ObjectId, signatures::PublicKey, verify::verify_domains_match}; use lemmy_db_schema::{naive_now, source::community::CommunityForm}; use lemmy_utils::{ - settings::structs::Settings, utils::{check_slurs, check_slurs_opt}, LemmyError, }; +use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; use url::Url; @@ -52,27 +52,27 @@ pub struct Group { } impl Group { - pub(crate) async fn into_form( - self, + pub(crate) async fn verify( + &self, expected_domain: &Url, - settings: &Settings, - ) -> Result { - check_is_apub_id_valid(self.id.inner(), true, settings)?; + context: &LemmyContext, + ) -> Result<(), LemmyError> { + check_is_apub_id_valid(self.id.inner(), true, &context.settings())?; verify_domains_match(expected_domain, self.id.inner())?; - let name = self.preferred_username; - let title = self.name; + + let slur_regex = &context.settings().slur_regex(); + check_slurs(&self.preferred_username, slur_regex)?; + check_slurs(&self.name, slur_regex)?; let description = get_summary_from_string_or_source(&self.summary, &self.source); - let shared_inbox = self.endpoints.shared_inbox.map(|s| s.into()); - - let slur_regex = &settings.slur_regex(); - check_slurs(&name, slur_regex)?; - check_slurs(&title, slur_regex)?; check_slurs_opt(&description, slur_regex)?; + Ok(()) + } + pub(crate) fn into_form(self) -> Result { Ok(CommunityForm { - name, - title, - description, + name: self.preferred_username, + title: self.name, + description: get_summary_from_string_or_source(&self.summary, &self.source), removed: None, published: self.published.map(|u| u.naive_local()), updated: self.updated.map(|u| u.naive_local()), @@ -87,7 +87,7 @@ impl Group { banner: Some(self.image.map(|i| i.url.into())), followers_url: Some(self.followers.into()), inbox_url: Some(self.inbox.into()), - shared_inbox_url: Some(shared_inbox), + shared_inbox_url: Some(self.endpoints.shared_inbox.map(|s| s.into())), }) } } diff --git a/crates/apub/src/protocol/objects/note.rs b/crates/apub/src/protocol/objects/note.rs index 34cb6bed0..acb4b6fb1 100644 --- a/crates/apub/src/protocol/objects/note.rs +++ b/crates/apub/src/protocol/objects/note.rs @@ -1,19 +1,13 @@ use crate::{ - activities::{verify_is_public, verify_person_in_community}, fetcher::post_or_comment::PostOrComment, - objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost}, + objects::{comment::ApubComment, person::ApubPerson, post::ApubPost}, protocol::Source, }; use activitystreams::{object::kind::NoteType, unparsed::Unparsed}; -use anyhow::anyhow; use chrono::{DateTime, FixedOffset}; use lemmy_api_common::blocking; -use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml, verify::verify_domains_match}; -use lemmy_db_schema::{ - newtypes::CommentId, - source::{community::Community, post::Post}, - traits::Crud, -}; +use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml}; +use lemmy_db_schema::{newtypes::CommentId, source::post::Post, traits::Crud}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; @@ -76,26 +70,4 @@ impl Note { } } } - - pub(crate) async fn verify( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result<(), LemmyError> { - let (post, _parent_comment_id) = self.get_parents(context, request_counter).await?; - let community_id = post.community_id; - let community: ApubCommunity = blocking(context.pool(), move |conn| { - Community::read(conn, community_id) - }) - .await?? - .into(); - - if post.locked { - return Err(anyhow!("Post is locked").into()); - } - verify_domains_match(self.attributed_to.inner(), self.id.inner())?; - verify_person_in_community(&self.attributed_to, &community, context, request_counter).await?; - verify_is_public(&self.to)?; - Ok(()) - } } diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs index 285a0e04e..ef7ab6e69 100644 --- a/crates/apub/src/protocol/objects/page.rs +++ b/crates/apub/src/protocol/objects/page.rs @@ -1,13 +1,12 @@ use crate::{ - activities::{verify_is_public, verify_person_in_community}, objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost}, protocol::{ImageObject, Source}, }; use activitystreams::{object::kind::PageType, unparsed::Unparsed}; use anyhow::anyhow; use chrono::{DateTime, FixedOffset}; -use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml, verify::verify_domains_match}; -use lemmy_utils::{utils::check_slurs, LemmyError}; +use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml}; +use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; @@ -54,20 +53,6 @@ impl Page { Ok(is_mod_action) } - pub(crate) async fn verify( - &self, - context: &LemmyContext, - request_counter: &mut i32, - ) -> Result<(), LemmyError> { - let community = self.extract_community(context, request_counter).await?; - - check_slurs(&self.name, &context.settings().slur_regex())?; - verify_domains_match(self.attributed_to.inner(), self.id.inner())?; - verify_person_in_community(&self.attributed_to, &community, context, request_counter).await?; - verify_is_public(&self.to.clone())?; - Ok(()) - } - pub(crate) async fn extract_community( &self, context: &LemmyContext, diff --git a/crates/apub_lib/src/object_id.rs b/crates/apub_lib/src/object_id.rs index 8e4b70a23..546430685 100644 --- a/crates/apub_lib/src/object_id.rs +++ b/crates/apub_lib/src/object_id.rs @@ -140,7 +140,8 @@ where let res2: Kind::ApubType = res.json().await?; - Ok(Kind::from_apub(res2, data, self.inner(), request_counter).await?) + Kind::verify(&res2, self.inner(), data, request_counter).await?; + Ok(Kind::from_apub(res2, data, request_counter).await?) } } diff --git a/crates/apub_lib/src/traits.rs b/crates/apub_lib/src/traits.rs index e5dcbc1ed..c0cdb1afb 100644 --- a/crates/apub_lib/src/traits.rs +++ b/crates/apub_lib/src/traits.rs @@ -44,6 +44,13 @@ pub trait ApubObject { async fn into_apub(self, data: &Self::DataType) -> Result; fn to_tombstone(&self) -> Result; + async fn verify( + apub: &Self::ApubType, + expected_domain: &Url, + data: &Self::DataType, + request_counter: &mut i32, + ) -> Result<(), LemmyError>; + /// Converts an object from ActivityPub type to Lemmy internal type. /// /// * `apub` The object to read from @@ -53,7 +60,6 @@ pub trait ApubObject { async fn from_apub( apub: Self::ApubType, data: &Self::DataType, - expected_domain: &Url, request_counter: &mut i32, ) -> Result where From 888e6838563504ac48fb87f49539963934e88558 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Sat, 6 Nov 2021 18:44:34 +0100 Subject: [PATCH 08/10] For verify_is_public() we also need to check cc field --- crates/apub/src/activities/comment/create_or_update.rs | 2 +- crates/apub/src/activities/community/add_mod.rs | 2 +- crates/apub/src/activities/community/announce.rs | 2 +- crates/apub/src/activities/community/block_user.rs | 2 +- crates/apub/src/activities/community/remove_mod.rs | 2 +- crates/apub/src/activities/community/undo_block_user.rs | 2 +- crates/apub/src/activities/community/update.rs | 2 +- crates/apub/src/activities/deletion/delete.rs | 2 +- crates/apub/src/activities/deletion/undo_delete.rs | 2 +- crates/apub/src/activities/mod.rs | 4 ++-- crates/apub/src/activities/post/create_or_update.rs | 2 +- crates/apub/src/activities/voting/undo_vote.rs | 2 +- crates/apub/src/activities/voting/vote.rs | 2 +- crates/apub/src/objects/comment.rs | 3 ++- crates/apub/src/objects/post.rs | 3 ++- crates/apub/src/protocol/objects/note.rs | 2 ++ crates/apub/src/protocol/objects/page.rs | 2 ++ 17 files changed, 22 insertions(+), 16 deletions(-) diff --git a/crates/apub/src/activities/comment/create_or_update.rs b/crates/apub/src/activities/comment/create_or_update.rs index 1ba2c8bb5..7ac1e4e59 100644 --- a/crates/apub/src/activities/comment/create_or_update.rs +++ b/crates/apub/src/activities/comment/create_or_update.rs @@ -75,7 +75,7 @@ impl ActivityHandler for CreateOrUpdateComment { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + 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?; diff --git a/crates/apub/src/activities/community/add_mod.rs b/crates/apub/src/activities/community/add_mod.rs index 8dad86096..f8026cce6 100644 --- a/crates/apub/src/activities/community/add_mod.rs +++ b/crates/apub/src/activities/community/add_mod.rs @@ -64,7 +64,7 @@ impl ActivityHandler for AddMod { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + verify_is_public(&self.to, &self.cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/community/announce.rs b/crates/apub/src/activities/community/announce.rs index 1fcce8377..6830bd139 100644 --- a/crates/apub/src/activities/community/announce.rs +++ b/crates/apub/src/activities/community/announce.rs @@ -59,7 +59,7 @@ impl ActivityHandler for AnnounceActivity { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + verify_is_public(&self.to, &self.cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; self.object.verify(context, request_counter).await?; Ok(()) diff --git a/crates/apub/src/activities/community/block_user.rs b/crates/apub/src/activities/community/block_user.rs index 851c96fd0..4be0660f8 100644 --- a/crates/apub/src/activities/community/block_user.rs +++ b/crates/apub/src/activities/community/block_user.rs @@ -75,7 +75,7 @@ impl ActivityHandler for BlockUserFromCommunity { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + verify_is_public(&self.to, &self.cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/community/remove_mod.rs b/crates/apub/src/activities/community/remove_mod.rs index c5edf333b..a644c19d7 100644 --- a/crates/apub/src/activities/community/remove_mod.rs +++ b/crates/apub/src/activities/community/remove_mod.rs @@ -63,7 +63,7 @@ impl ActivityHandler for RemoveMod { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + verify_is_public(&self.to, &self.cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/community/undo_block_user.rs b/crates/apub/src/activities/community/undo_block_user.rs index bb4c03587..f309fe2b8 100644 --- a/crates/apub/src/activities/community/undo_block_user.rs +++ b/crates/apub/src/activities/community/undo_block_user.rs @@ -65,7 +65,7 @@ impl ActivityHandler for UndoBlockUserFromCommunity { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + verify_is_public(&self.to, &self.cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index eebfe336c..b4ffb7fc6 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -58,7 +58,7 @@ impl ActivityHandler for UpdateCommunity { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + verify_is_public(&self.to, &self.cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/deletion/delete.rs b/crates/apub/src/activities/deletion/delete.rs index 6e2174982..54e9c3941 100644 --- a/crates/apub/src/activities/deletion/delete.rs +++ b/crates/apub/src/activities/deletion/delete.rs @@ -50,7 +50,7 @@ impl ActivityHandler for Delete { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + verify_is_public(&self.to, &self.cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_delete_activity( diff --git a/crates/apub/src/activities/deletion/undo_delete.rs b/crates/apub/src/activities/deletion/undo_delete.rs index b3e44af29..edd893bc3 100644 --- a/crates/apub/src/activities/deletion/undo_delete.rs +++ b/crates/apub/src/activities/deletion/undo_delete.rs @@ -35,7 +35,7 @@ impl ActivityHandler for UndoDelete { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + verify_is_public(&self.to, &self.cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; self.object.verify(context, request_counter).await?; let community = self.get_community(context, request_counter).await?; diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 920a531e9..a6c753764 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -116,8 +116,8 @@ fn verify_add_remove_moderator_target( Ok(()) } -pub(crate) fn verify_is_public(to: &[Url]) -> Result<(), LemmyError> { - if !to.contains(&public()) { +pub(crate) fn verify_is_public(to: &[Url], cc: &[Url]) -> Result<(), LemmyError> { + if !to.contains(&public()) && !cc.contains(&public()) { return Err(anyhow!("Object is not public").into()); } Ok(()) diff --git a/crates/apub/src/activities/post/create_or_update.rs b/crates/apub/src/activities/post/create_or_update.rs index db5d725fc..05a7f38d0 100644 --- a/crates/apub/src/activities/post/create_or_update.rs +++ b/crates/apub/src/activities/post/create_or_update.rs @@ -74,7 +74,7 @@ impl ActivityHandler for CreateOrUpdatePost { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + verify_is_public(&self.to, &self.cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/voting/undo_vote.rs b/crates/apub/src/activities/voting/undo_vote.rs index 6d6f3eaff..c066d731c 100644 --- a/crates/apub/src/activities/voting/undo_vote.rs +++ b/crates/apub/src/activities/voting/undo_vote.rs @@ -68,7 +68,7 @@ impl ActivityHandler for UndoVote { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + verify_is_public(&self.to, &self.cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/activities/voting/vote.rs b/crates/apub/src/activities/voting/vote.rs index 89e88fe64..304c512a7 100644 --- a/crates/apub/src/activities/voting/vote.rs +++ b/crates/apub/src/activities/voting/vote.rs @@ -74,7 +74,7 @@ impl ActivityHandler for Vote { context: &Data, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_is_public(&self.to)?; + verify_is_public(&self.to, &self.cc)?; verify_activity(&self.id, self.actor.inner(), &context.settings())?; let community = self.get_community(context, request_counter).await?; verify_person_in_community(&self.actor, &community, context, request_counter).await?; diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs index d0f74acfa..83895e8d3 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -107,6 +107,7 @@ impl ApubObject for ApubComment { id: ObjectId::new(self.ap_id.clone()), attributed_to: ObjectId::new(creator.actor_id), to: vec![public()], + cc: vec![], content: markdown_to_html(&self.content), media_type: Some(MediaTypeHtml::Html), source: SourceCompat::Lemmy(Source { @@ -137,7 +138,7 @@ impl ApubObject for ApubComment { ) -> Result<(), LemmyError> { verify_domains_match(note.id.inner(), expected_domain)?; verify_domains_match(note.attributed_to.inner(), note.id.inner())?; - verify_is_public(¬e.to)?; + verify_is_public(¬e.to, ¬e.cc)?; let (post, _) = note.get_parents(context, request_counter).await?; let community_id = post.community_id; let community = blocking(context.pool(), move |conn| { diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index 9e68cbb1d..4e34fc88e 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -110,6 +110,7 @@ impl ApubObject for ApubPost { id: ObjectId::new(self.ap_id.clone()), attributed_to: ObjectId::new(creator.actor_id), to: vec![community.actor_id.into(), public()], + cc: vec![], name: self.name.clone(), content: self.body.as_ref().map(|b| markdown_to_html(b)), media_type: Some(MediaTypeHtml::Html), @@ -150,7 +151,7 @@ impl ApubObject for ApubPost { verify_person_in_community(&page.attributed_to, &community, context, request_counter).await?; check_slurs(&page.name, &context.settings().slur_regex())?; verify_domains_match(page.attributed_to.inner(), page.id.inner())?; - verify_is_public(&page.to.clone())?; + verify_is_public(&page.to, &page.cc)?; Ok(()) } diff --git a/crates/apub/src/protocol/objects/note.rs b/crates/apub/src/protocol/objects/note.rs index acb4b6fb1..3ffc1123d 100644 --- a/crates/apub/src/protocol/objects/note.rs +++ b/crates/apub/src/protocol/objects/note.rs @@ -23,6 +23,8 @@ pub struct Note { pub(crate) id: ObjectId, pub(crate) attributed_to: ObjectId, pub(crate) to: Vec, + #[serde(default)] + pub(crate) cc: Vec, pub(crate) content: String, pub(crate) media_type: Option, pub(crate) source: SourceCompat, diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs index ef7ab6e69..89fb11415 100644 --- a/crates/apub/src/protocol/objects/page.rs +++ b/crates/apub/src/protocol/objects/page.rs @@ -20,6 +20,8 @@ pub struct Page { pub(crate) id: ObjectId, pub(crate) attributed_to: ObjectId, pub(crate) to: Vec, + #[serde(default)] + pub(crate) cc: Vec, pub(crate) name: String, pub(crate) content: Option, pub(crate) media_type: Option, From 252d87d33201818079d7ea5c59f207dbb085235d Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Mon, 8 Nov 2021 13:11:24 +0100 Subject: [PATCH 09/10] Fix clippy error --- crates/apub/src/activities/community/update.rs | 2 +- crates/apub/src/objects/community.rs | 2 +- crates/apub/src/protocol/objects/group.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index b4ffb7fc6..cc82c9e31 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -80,7 +80,7 @@ impl ActivityHandler for UpdateCommunity { ) -> Result<(), LemmyError> { let community = self.get_community(context, request_counter).await?; - let updated_community = self.object.into_form()?; + let updated_community = self.object.into_form(); let cf = CommunityForm { name: updated_community.name, title: updated_community.title, diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index 21ca9d4f5..f2fb45e4f 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -139,7 +139,7 @@ impl ApubObject for ApubCommunity { context: &LemmyContext, request_counter: &mut i32, ) -> Result { - let form = Group::into_form(group.clone())?; + let form = Group::into_form(group.clone()); // Fetching mods and outbox is not necessary for Lemmy to work, so ignore errors. Besides, // we need to ignore these errors so that tests can work entirely offline. diff --git a/crates/apub/src/protocol/objects/group.rs b/crates/apub/src/protocol/objects/group.rs index 8a6e67203..4dc1c5bd1 100644 --- a/crates/apub/src/protocol/objects/group.rs +++ b/crates/apub/src/protocol/objects/group.rs @@ -68,8 +68,8 @@ impl Group { Ok(()) } - pub(crate) fn into_form(self) -> Result { - Ok(CommunityForm { + pub(crate) fn into_form(self) -> CommunityForm { + CommunityForm { name: self.preferred_username, title: self.name, description: get_summary_from_string_or_source(&self.summary, &self.source), @@ -88,6 +88,6 @@ impl Group { followers_url: Some(self.followers.into()), inbox_url: Some(self.inbox.into()), shared_inbox_url: Some(self.endpoints.shared_inbox.map(|s| s.into())), - }) + } } } From c21c142a9a5414fbd6859cf22cb2d459b9e1503f Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Mon, 8 Nov 2021 16:04:02 +0100 Subject: [PATCH 10/10] Include apub context from file, so that it can be embedded in docs --- crates/apub/assets/lemmy/context.json | 19 +++++++++++++++++ crates/apub/src/context.rs | 30 +++------------------------ 2 files changed, 22 insertions(+), 27 deletions(-) create mode 100644 crates/apub/assets/lemmy/context.json diff --git a/crates/apub/assets/lemmy/context.json b/crates/apub/assets/lemmy/context.json new file mode 100644 index 000000000..88f3a6586 --- /dev/null +++ b/crates/apub/assets/lemmy/context.json @@ -0,0 +1,19 @@ +[ + "https://www.w3.org/ns/activitystreams", + { + "stickied": "as:stickied", + "pt": "https://join-lemmy.org#", + "sc": "http://schema.org#", + "matrixUserId": { + "type": "sc:Text", + "id": "as:alsoKnownAs" + }, + "sensitive": "as:sensitive", + "comments_enabled": { + "type": "sc:Boolean", + "id": "pt:commentsEnabled" + }, + "moderators": "as:moderators" + }, + "https://w3id.org/security/v1" +] \ No newline at end of file diff --git a/crates/apub/src/context.rs b/crates/apub/src/context.rs index cf4b704fc..55486872f 100644 --- a/crates/apub/src/context.rs +++ b/crates/apub/src/context.rs @@ -1,33 +1,9 @@ -use activitystreams::{base::AnyBase, context, primitives::OneOrMany}; +use activitystreams::{base::AnyBase, primitives::OneOrMany}; use serde::{Deserialize, Serialize}; -use serde_json::json; -use url::Url; lazy_static! { - static ref CONTEXT: OneOrMany = { - let context_ext = AnyBase::from_arbitrary_json(json!( - { - "sc": "http://schema.org#", - "sensitive": "as:sensitive", - "stickied": "as:stickied", - "pt": "https://join-lemmy.org#", - "comments_enabled": { - "type": "sc:Boolean", - "id": "pt:commentsEnabled" - }, - "moderators": "as:moderators", - "matrixUserId": { - "type": "sc:Text", - "id": "as:alsoKnownAs" - }, - })) - .expect("parse context"); - OneOrMany::from(vec![ - AnyBase::from(context()), - context_ext, - AnyBase::from(Url::parse("https://w3id.org/security/v1").expect("parse context")), - ]) - }; + static ref CONTEXT: OneOrMany = + serde_json::from_str(include_str!("../assets/lemmy/context.json")).expect("parse context"); } #[derive(Serialize, Deserialize)]