From 20af10dddf341d8654e51ad2700d5e45579a3c48 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Tue, 26 Oct 2021 21:05:26 +0200 Subject: [PATCH] Merge traits ToApub and FromApub into ApubObject --- .../activities/comment/create_or_update.rs | 4 +- .../apub/src/activities/community/update.rs | 4 +- .../src/activities/post/create_or_update.rs | 4 +- .../private_message/create_or_update.rs | 4 +- crates/apub/src/fetcher/object_id.rs | 25 +++--- crates/apub/src/fetcher/post_or_comment.rs | 16 ++-- crates/apub/src/fetcher/search.rs | 16 ++-- crates/apub/src/http/comment.rs | 6 +- crates/apub/src/http/community.rs | 15 ++-- crates/apub/src/http/person.rs | 4 +- crates/apub/src/http/post.rs | 4 +- crates/apub/src/objects/comment.rs | 29 +++---- crates/apub/src/objects/community.rs | 73 ++++++++--------- crates/apub/src/objects/person.rs | 79 ++++++++----------- crates/apub/src/objects/post.rs | 29 +++---- crates/apub/src/objects/private_message.rs | 27 ++----- crates/apub_lib/src/traits.rs | 54 ++++++------- 17 files changed, 164 insertions(+), 229 deletions(-) diff --git a/crates/apub/src/activities/comment/create_or_update.rs b/crates/apub/src/activities/comment/create_or_update.rs index c4591c7c8..0dcf3f7d8 100644 --- a/crates/apub/src/activities/comment/create_or_update.rs +++ b/crates/apub/src/activities/comment/create_or_update.rs @@ -21,7 +21,7 @@ use activitystreams::{base::AnyBase, link::Mention, primitives::OneOrMany, unpar use lemmy_api_common::{blocking, check_post_deleted_or_removed}; use lemmy_apub_lib::{ data::Data, - traits::{ActivityFields, ActivityHandler, ActorType, FromApub, ToApub}, + traits::{ActivityFields, ActivityHandler, ActorType, ApubObject}, values::PublicUrl, verify::verify_domains_match, }; @@ -77,7 +77,7 @@ impl CreateOrUpdateComment { let create_or_update = CreateOrUpdateComment { actor: ObjectId::new(actor.actor_id()), to: [PublicUrl::Public], - object: comment.to_apub(context.pool()).await?, + object: comment.to_apub(context).await?, cc: maa.ccs, tag: maa.tags, kind, diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index 1120bd8bb..f6d693dd6 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -22,7 +22,7 @@ use activitystreams::{ use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, - traits::{ActivityFields, ActivityHandler, ActorType, ToApub}, + traits::{ActivityFields, ActivityHandler, ActorType, ApubObject}, values::PublicUrl, }; use lemmy_db_schema::{ @@ -66,7 +66,7 @@ impl UpdateCommunity { let update = UpdateCommunity { actor: ObjectId::new(actor.actor_id()), to: [PublicUrl::Public], - object: community.to_apub(context.pool()).await?, + object: community.to_apub(context).await?, cc: [ObjectId::new(community.actor_id())], kind: UpdateType::Update, id: id.clone(), diff --git a/crates/apub/src/activities/post/create_or_update.rs b/crates/apub/src/activities/post/create_or_update.rs index cc7ef5c97..1187e770f 100644 --- a/crates/apub/src/activities/post/create_or_update.rs +++ b/crates/apub/src/activities/post/create_or_update.rs @@ -21,7 +21,7 @@ use anyhow::anyhow; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, - traits::{ActivityFields, ActivityHandler, ActorType, FromApub, ToApub}, + traits::{ActivityFields, ActivityHandler, ActorType, ApubObject}, values::PublicUrl, verify::{verify_domains_match, verify_urls_match}, }; @@ -68,7 +68,7 @@ impl CreateOrUpdatePost { let create_or_update = CreateOrUpdatePost { actor: ObjectId::new(actor.actor_id()), to: [PublicUrl::Public], - object: post.to_apub(context.pool()).await?, + object: post.to_apub(context).await?, cc: [ObjectId::new(community.actor_id())], kind, id: id.clone(), 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 a1ee5598e..9ef22f0e4 100644 --- a/crates/apub/src/activities/private_message/create_or_update.rs +++ b/crates/apub/src/activities/private_message/create_or_update.rs @@ -12,7 +12,7 @@ use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed}; use lemmy_api_common::blocking; use lemmy_apub_lib::{ data::Data, - traits::{ActivityFields, ActivityHandler, ActorType, FromApub, ToApub}, + traits::{ActivityFields, ActivityHandler, ActorType, ApubObject}, verify::verify_domains_match, }; use lemmy_db_schema::{source::person::Person, traits::Crud}; @@ -58,7 +58,7 @@ impl CreateOrUpdatePrivateMessage { id: id.clone(), actor: ObjectId::new(actor.actor_id()), to: ObjectId::new(recipient.actor_id()), - object: private_message.to_apub(context.pool()).await?, + object: private_message.to_apub(context).await?, kind, unparsed: Default::default(), }; diff --git a/crates/apub/src/fetcher/object_id.rs b/crates/apub/src/fetcher/object_id.rs index 38eb14cc7..fb9107c82 100644 --- a/crates/apub/src/fetcher/object_id.rs +++ b/crates/apub/src/fetcher/object_id.rs @@ -1,10 +1,7 @@ use crate::fetcher::should_refetch_actor; use anyhow::anyhow; use diesel::NotFound; -use lemmy_apub_lib::{ - traits::{ApubObject, FromApub}, - APUB_JSON_CONTENT_TYPE, -}; +use lemmy_apub_lib::{traits::ApubObject, APUB_JSON_CONTENT_TYPE}; use lemmy_db_schema::newtypes::DbUrl; use lemmy_utils::{request::retry, settings::structs::Settings, LemmyError}; use lemmy_websocket::LemmyContext; @@ -25,13 +22,13 @@ static REQUEST_LIMIT: i32 = 25; #[serde(transparent)] pub struct ObjectId(Url, #[serde(skip)] PhantomData) where - Kind: FromApub + ApubObject + Send + 'static, - for<'de2> ::ApubType: serde::Deserialize<'de2>; + Kind: ApubObject + Send + 'static, + for<'de2> ::ApubType: serde::Deserialize<'de2>; impl ObjectId where - Kind: FromApub + ApubObject + Send + 'static, - for<'de> ::ApubType: serde::Deserialize<'de>, + Kind: ApubObject + Send + 'static, + for<'de2> ::ApubType: serde::Deserialize<'de2>, { pub fn new(url: T) -> Self where @@ -129,8 +126,8 @@ where impl Display for ObjectId where - Kind: FromApub + ApubObject + Send + 'static, - for<'de> ::ApubType: serde::Deserialize<'de>, + Kind: ApubObject + Send + 'static, + for<'de2> ::ApubType: serde::Deserialize<'de2>, { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0.to_string()) @@ -139,8 +136,8 @@ where impl From> for Url where - Kind: FromApub + ApubObject + Send + 'static, - for<'de> ::ApubType: serde::Deserialize<'de>, + Kind: ApubObject + Send + 'static, + for<'de2> ::ApubType: serde::Deserialize<'de2>, { fn from(id: ObjectId) -> Self { id.0 @@ -149,8 +146,8 @@ where impl From> for DbUrl where - Kind: FromApub + ApubObject + Send + 'static, - for<'de> ::ApubType: serde::Deserialize<'de>, + Kind: ApubObject + Send + 'static, + for<'de2> ::ApubType: serde::Deserialize<'de2>, { fn from(id: ObjectId) -> Self { id.0.into() diff --git a/crates/apub/src/fetcher/post_or_comment.rs b/crates/apub/src/fetcher/post_or_comment.rs index fd78ad79a..ff0562a6b 100644 --- a/crates/apub/src/fetcher/post_or_comment.rs +++ b/crates/apub/src/fetcher/post_or_comment.rs @@ -3,7 +3,7 @@ use crate::objects::{ post::{ApubPost, Page}, }; use activitystreams::chrono::NaiveDateTime; -use lemmy_apub_lib::traits::{ApubObject, FromApub}; +use lemmy_apub_lib::traits::ApubObject; use lemmy_db_schema::source::{comment::CommentForm, post::PostForm}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; @@ -31,6 +31,8 @@ pub enum PageOrNote { #[async_trait::async_trait(?Send)] impl ApubObject for PostOrComment { type DataType = LemmyContext; + type ApubType = PageOrNote; + type TombstoneType = (); fn last_refreshed_at(&self) -> Option { None @@ -59,12 +61,14 @@ impl ApubObject for PostOrComment { PostOrComment::Comment(c) => c.delete(data).await, } } -} -#[async_trait::async_trait(?Send)] -impl FromApub for PostOrComment { - type ApubType = PageOrNote; - type DataType = LemmyContext; + async fn to_apub(&self, _data: &Self::DataType) -> Result { + unimplemented!() + } + + fn to_tombstone(&self) -> Result { + unimplemented!() + } async fn from_apub( apub: &PageOrNote, diff --git a/crates/apub/src/fetcher/search.rs b/crates/apub/src/fetcher/search.rs index c67eaa0ff..86cdcbe07 100644 --- a/crates/apub/src/fetcher/search.rs +++ b/crates/apub/src/fetcher/search.rs @@ -12,7 +12,7 @@ use anyhow::anyhow; use itertools::Itertools; use lemmy_api_common::blocking; use lemmy_apub_lib::{ - traits::{ApubObject, FromApub}, + traits::ApubObject, webfinger::{webfinger_resolve_actor, WebfingerType}, }; use lemmy_db_schema::{ @@ -110,6 +110,8 @@ pub enum SearchableApubTypes { #[async_trait::async_trait(?Send)] impl ApubObject for SearchableObjects { type DataType = LemmyContext; + type ApubType = SearchableApubTypes; + type TombstoneType = (); fn last_refreshed_at(&self) -> Option { match self { @@ -156,12 +158,14 @@ impl ApubObject for SearchableObjects { SearchableObjects::Comment(c) => c.delete(data).await, } } -} -#[async_trait::async_trait(?Send)] -impl FromApub for SearchableObjects { - type ApubType = SearchableApubTypes; - type DataType = LemmyContext; + async fn to_apub(&self, _data: &Self::DataType) -> Result { + unimplemented!() + } + + fn to_tombstone(&self) -> Result { + unimplemented!() + } async fn from_apub( apub: &Self::ApubType, diff --git a/crates/apub/src/http/comment.rs b/crates/apub/src/http/comment.rs index 58543a5bb..3086f2fd9 100644 --- a/crates/apub/src/http/comment.rs +++ b/crates/apub/src/http/comment.rs @@ -5,7 +5,7 @@ use crate::{ use actix_web::{body::Body, web, web::Path, HttpResponse}; use diesel::result::Error::NotFound; use lemmy_api_common::blocking; -use lemmy_apub_lib::traits::ToApub; +use lemmy_apub_lib::traits::ApubObject; use lemmy_db_schema::{newtypes::CommentId, source::comment::Comment, traits::Crud}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; @@ -30,9 +30,7 @@ pub(crate) async fn get_apub_comment( } if !comment.deleted { - Ok(create_apub_response( - &comment.to_apub(context.pool()).await?, - )) + Ok(create_apub_response(&comment.to_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 7c66ca9db..1b398a56b 100644 --- a/crates/apub/src/http/community.rs +++ b/crates/apub/src/http/community.rs @@ -6,13 +6,9 @@ use crate::{ report::Report, }, context::lemmy_context, - generate_moderators_url, - generate_outbox_url, + generate_moderators_url, generate_outbox_url, http::{ - create_apub_response, - create_apub_tombstone_response, - payload_to_string, - receive_activity, + create_apub_response, create_apub_tombstone_response, payload_to_string, receive_activity, }, objects::community::ApubCommunity, }; @@ -23,11 +19,10 @@ use activitystreams::{ }; use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse}; use lemmy_api_common::blocking; -use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler, ToApub}; +use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler, ApubObject}; use lemmy_db_schema::source::{activity::Activity, community::Community}; use lemmy_db_views_actor::{ - community_follower_view::CommunityFollowerView, - community_moderator_view::CommunityModeratorView, + community_follower_view::CommunityFollowerView, community_moderator_view::CommunityModeratorView, }; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; @@ -51,7 +46,7 @@ pub(crate) async fn get_apub_community_http( .into(); if !community.deleted { - let apub = community.to_apub(context.pool()).await?; + let apub = community.to_apub(&**context).await?; Ok(create_apub_response(&apub)) } else { diff --git a/crates/apub/src/http/person.rs b/crates/apub/src/http/person.rs index 16f1bc5c4..470ff4749 100644 --- a/crates/apub/src/http/person.rs +++ b/crates/apub/src/http/person.rs @@ -24,7 +24,7 @@ use activitystreams::{ }; use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse}; use lemmy_api_common::blocking; -use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler, ToApub}; +use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler, ApubObject}; use lemmy_db_schema::source::person::Person; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; @@ -51,7 +51,7 @@ pub(crate) async fn get_apub_person_http( .into(); if !person.deleted { - let apub = person.to_apub(context.pool()).await?; + let apub = person.to_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 2ce712bc9..0459942a9 100644 --- a/crates/apub/src/http/post.rs +++ b/crates/apub/src/http/post.rs @@ -5,7 +5,7 @@ use crate::{ use actix_web::{body::Body, web, HttpResponse}; use diesel::result::Error::NotFound; use lemmy_api_common::blocking; -use lemmy_apub_lib::traits::ToApub; +use lemmy_apub_lib::traits::ApubObject; use lemmy_db_schema::{newtypes::PostId, source::post::Post, traits::Crud}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; @@ -30,7 +30,7 @@ pub(crate) async fn get_apub_post( } if !post.deleted { - Ok(create_apub_response(&post.to_apub(context.pool()).await?)) + Ok(create_apub_response(&post.to_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 5fe4fa690..9ac6797b6 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -18,7 +18,7 @@ use chrono::{DateTime, FixedOffset}; use html2md::parse_html; use lemmy_api_common::blocking; use lemmy_apub_lib::{ - traits::{ApubObject, FromApub, ToApub}, + traits::ApubObject, values::{MediaTypeHtml, MediaTypeMarkdown}, verify::verify_domains_match, }; @@ -31,7 +31,6 @@ use lemmy_db_schema::{ post::Post, }, traits::Crud, - DbPool, }; use lemmy_utils::{ utils::{convert_datetime, remove_slurs}, @@ -159,6 +158,8 @@ impl From for ApubComment { #[async_trait::async_trait(?Send)] impl ApubObject for ApubComment { type DataType = LemmyContext; + type ApubType = Note; + type TombstoneType = Tombstone; fn last_refreshed_at(&self) -> Option { None @@ -184,23 +185,17 @@ impl ApubObject for ApubComment { .await??; Ok(()) } -} -#[async_trait::async_trait(?Send)] -impl ToApub for ApubComment { - type ApubType = Note; - type TombstoneType = Tombstone; - type DataType = DbPool; - - async fn to_apub(&self, pool: &DbPool) -> Result { + async fn to_apub(&self, context: &LemmyContext) -> Result { let creator_id = self.creator_id; - let creator = blocking(pool, move |conn| Person::read(conn, creator_id)).await??; + let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??; let post_id = self.post_id; - let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; let in_reply_to = if let Some(comment_id) = self.parent_id { - let parent_comment = blocking(pool, move |conn| Comment::read(conn, comment_id)).await??; + let parent_comment = + blocking(context.pool(), move |conn| Comment::read(conn, comment_id)).await??; ObjectId::::new(parent_comment.ap_id.into_inner()) } else { ObjectId::::new(post.ap_id.into_inner()) @@ -235,12 +230,6 @@ impl ToApub for ApubComment { NoteType::Note, ) } -} - -#[async_trait::async_trait(?Send)] -impl FromApub for ApubComment { - type ApubType = Note; - type DataType = LemmyContext; /// Converts a `Note` to `Comment`. /// @@ -339,7 +328,7 @@ mod tests { assert!(!comment.local); assert_eq!(request_counter, 0); - let to_apub = comment.to_apub(context.pool()).await.unwrap(); + let to_apub = comment.to_apub(&context).await.unwrap(); assert_json_include!(actual: json, expected: to_apub); Comment::delete(&*context.pool().get().unwrap(), comment.id).unwrap(); diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index 74d417c39..3c0fa38c6 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -20,7 +20,7 @@ use itertools::Itertools; use lemmy_api_common::blocking; use lemmy_apub_lib::{ signatures::PublicKey, - traits::{ActorType, ApubObject, FromApub, ToApub}, + traits::{ActorType, ApubObject}, values::MediaTypeMarkdown, verify::verify_domains_match, }; @@ -138,6 +138,8 @@ impl From for ApubCommunity { #[async_trait::async_trait(?Send)] impl ApubObject for ApubCommunity { type DataType = LemmyContext; + type ApubType = Group; + type TombstoneType = Tombstone; fn last_refreshed_at(&self) -> Option { Some(self.last_refreshed_at) @@ -163,41 +165,8 @@ impl ApubObject for ApubCommunity { .await??; Ok(()) } -} -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() - } - fn private_key(&self) -> Option { - self.private_key.to_owned() - } - - fn inbox_url(&self) -> Url { - self.inbox_url.clone().into() - } - - fn shared_inbox_url(&self) -> Option { - self.shared_inbox_url.clone().map(|s| s.into_inner()) - } -} - -#[async_trait::async_trait(?Send)] -impl ToApub for ApubCommunity { - type ApubType = Group; - type TombstoneType = Tombstone; - type DataType = DbPool; - - async fn to_apub(&self, _pool: &DbPool) -> Result { + async fn to_apub(&self, _context: &LemmyContext) -> Result { let source = self.description.clone().map(|bio| Source { content: bio, media_type: MediaTypeMarkdown::Markdown, @@ -246,12 +215,6 @@ impl ToApub for ApubCommunity { GroupType::Group, ) } -} - -#[async_trait::async_trait(?Send)] -impl FromApub for ApubCommunity { - type ApubType = Group; - type DataType = LemmyContext; /// Converts a `Group` to `Community`, inserts it into the database and updates moderators. async fn from_apub( @@ -280,6 +243,32 @@ impl FromApub 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() + } + fn private_key(&self) -> Option { + self.private_key.to_owned() + } + + fn inbox_url(&self) -> Url { + self.inbox_url.clone().into() + } + + fn shared_inbox_url(&self) -> Option { + self.shared_inbox_url.clone().map(|s| s.into_inner()) + } +} + #[async_trait::async_trait(?Send)] impl CommunityType for Community { fn followers_url(&self) -> Url { @@ -345,7 +334,7 @@ mod tests { // this makes two requests to the (intentionally) broken outbox/moderators collections assert_eq!(request_counter, 2); - let to_apub = community.to_apub(context.pool()).await.unwrap(); + let to_apub = community.to_apub(&context).await.unwrap(); assert_json_include!(actual: json_orig, expected: to_apub); Community::delete(&*context.pool().get().unwrap(), community.id).unwrap(); diff --git a/crates/apub/src/objects/person.rs b/crates/apub/src/objects/person.rs index 99847562f..fd98f87ad 100644 --- a/crates/apub/src/objects/person.rs +++ b/crates/apub/src/objects/person.rs @@ -16,14 +16,13 @@ use chrono::{DateTime, FixedOffset}; use lemmy_api_common::blocking; use lemmy_apub_lib::{ signatures::PublicKey, - traits::{ActorType, ApubObject, FromApub, ToApub}, + traits::{ActorType, ApubObject}, values::MediaTypeMarkdown, verify::verify_domains_match, }; use lemmy_db_schema::{ naive_now, source::person::{Person as DbPerson, PersonForm}, - DbPool, }; use lemmy_utils::{ utils::{check_slurs, check_slurs_opt, convert_datetime, markdown_to_html}, @@ -99,6 +98,8 @@ impl From for ApubPerson { #[async_trait::async_trait(?Send)] impl ApubObject for ApubPerson { type DataType = LemmyContext; + type ApubType = Person; + type TombstoneType = Tombstone; fn last_refreshed_at(&self) -> Option { Some(self.last_refreshed_at) @@ -124,43 +125,8 @@ impl ApubObject for ApubPerson { .await??; Ok(()) } -} -impl ActorType for ApubPerson { - fn is_local(&self) -> bool { - self.local - } - fn actor_id(&self) -> Url { - self.actor_id.to_owned().into_inner() - } - fn name(&self) -> String { - self.name.clone() - } - - fn public_key(&self) -> Option { - self.public_key.to_owned() - } - - fn private_key(&self) -> Option { - self.private_key.to_owned() - } - - fn inbox_url(&self) -> Url { - self.inbox_url.clone().into() - } - - fn shared_inbox_url(&self) -> Option { - self.shared_inbox_url.clone().map(|s| s.into_inner()) - } -} - -#[async_trait::async_trait(?Send)] -impl ToApub for ApubPerson { - type ApubType = Person; - type TombstoneType = Tombstone; - type DataType = DbPool; - - async fn to_apub(&self, _pool: &DbPool) -> Result { + async fn to_apub(&self, _pool: &LemmyContext) -> Result { let kind = if self.bot_account { UserTypes::Service } else { @@ -203,15 +169,10 @@ impl ToApub for ApubPerson { }; Ok(person) } + fn to_tombstone(&self) -> Result { unimplemented!() } -} - -#[async_trait::async_trait(?Send)] -impl FromApub for ApubPerson { - type ApubType = Person; - type DataType = LemmyContext; async fn from_apub( person: &Person, @@ -265,6 +226,34 @@ impl FromApub for ApubPerson { } } +impl ActorType for ApubPerson { + fn is_local(&self) -> bool { + self.local + } + fn actor_id(&self) -> Url { + self.actor_id.to_owned().into_inner() + } + fn name(&self) -> String { + self.name.clone() + } + + fn public_key(&self) -> Option { + self.public_key.to_owned() + } + + fn private_key(&self) -> Option { + self.private_key.to_owned() + } + + fn inbox_url(&self) -> Url { + self.inbox_url.clone().into() + } + + fn shared_inbox_url(&self) -> Option { + self.shared_inbox_url.clone().map(|s| s.into_inner()) + } +} + #[cfg(test)] mod tests { use super::*; @@ -291,7 +280,7 @@ mod tests { assert_eq!(person.bio.as_ref().unwrap().len(), 39); assert_eq!(request_counter, 0); - let to_apub = person.to_apub(context.pool()).await.unwrap(); + let to_apub = person.to_apub(&context).await.unwrap(); assert_json_include!(actual: json, expected: to_apub); DbPerson::delete(&*context.pool().get().unwrap(), person.id).unwrap(); diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index a56bbd590..0814bf46d 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -17,7 +17,7 @@ use activitystreams::{ use chrono::{DateTime, FixedOffset, NaiveDateTime}; use lemmy_api_common::blocking; use lemmy_apub_lib::{ - traits::{ActorType, ApubObject, FromApub, ToApub}, + traits::{ActorType, ApubObject}, values::{MediaTypeHtml, MediaTypeMarkdown}, verify::verify_domains_match, }; @@ -29,7 +29,6 @@ use lemmy_db_schema::{ post::{Post, PostForm}, }, traits::Crud, - DbPool, }; use lemmy_utils::{ request::fetch_site_data, @@ -133,6 +132,8 @@ impl From for ApubPost { #[async_trait::async_trait(?Send)] impl ApubObject for ApubPost { type DataType = LemmyContext; + type ApubType = Page; + type TombstoneType = Tombstone; fn last_refreshed_at(&self) -> Option { None @@ -158,20 +159,16 @@ impl ApubObject for ApubPost { .await??; Ok(()) } -} - -#[async_trait::async_trait(?Send)] -impl ToApub for ApubPost { - type ApubType = Page; - type TombstoneType = Tombstone; - type DataType = DbPool; // Turn a Lemmy post into an ActivityPub page that can be sent out over the network. - async fn to_apub(&self, pool: &DbPool) -> Result { + async fn to_apub(&self, context: &LemmyContext) -> Result { let creator_id = self.creator_id; - let creator = blocking(pool, move |conn| Person::read(conn, creator_id)).await??; + let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??; let community_id = self.community_id; - let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; + let community = blocking(context.pool(), move |conn| { + Community::read(conn, community_id) + }) + .await??; let source = self.body.clone().map(|body| Source { content: body, @@ -212,12 +209,6 @@ impl ToApub for ApubPost { PageType::Page, ) } -} - -#[async_trait::async_trait(?Send)] -impl FromApub for ApubPost { - type ApubType = Page; - type DataType = LemmyContext; async fn from_apub( page: &Page, @@ -315,7 +306,7 @@ mod tests { assert!(post.stickied); assert_eq!(request_counter, 0); - let to_apub = post.to_apub(context.pool()).await.unwrap(); + let to_apub = post.to_apub(&context).await.unwrap(); assert_json_include!(actual: json, expected: to_apub); Post::delete(&*context.pool().get().unwrap(), post.id).unwrap(); diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs index bd9cc1da4..146dd7125 100644 --- a/crates/apub/src/objects/private_message.rs +++ b/crates/apub/src/objects/private_message.rs @@ -15,7 +15,7 @@ use chrono::{DateTime, FixedOffset}; use html2md::parse_html; use lemmy_api_common::blocking; use lemmy_apub_lib::{ - traits::{ApubObject, FromApub, ToApub}, + traits::ApubObject, values::{MediaTypeHtml, MediaTypeMarkdown}, verify::verify_domains_match, }; @@ -25,7 +25,6 @@ use lemmy_db_schema::{ private_message::{PrivateMessage, PrivateMessageForm}, }, traits::Crud, - DbPool, }; use lemmy_utils::{utils::convert_datetime, LemmyError}; use lemmy_websocket::LemmyContext; @@ -104,6 +103,8 @@ impl From for ApubPrivateMessage { #[async_trait::async_trait(?Send)] impl ApubObject for ApubPrivateMessage { type DataType = LemmyContext; + type ApubType = Note; + type TombstoneType = Tombstone; fn last_refreshed_at(&self) -> Option { None @@ -126,20 +127,14 @@ impl ApubObject for ApubPrivateMessage { // do nothing, because pm can't be fetched over http unimplemented!() } -} -#[async_trait::async_trait(?Send)] -impl ToApub for ApubPrivateMessage { - type ApubType = Note; - type TombstoneType = Tombstone; - type DataType = DbPool; - - async fn to_apub(&self, pool: &DbPool) -> Result { + async fn to_apub(&self, context: &LemmyContext) -> Result { let creator_id = self.creator_id; - let creator = blocking(pool, move |conn| Person::read(conn, creator_id)).await??; + let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??; let recipient_id = self.recipient_id; - let recipient = blocking(pool, move |conn| Person::read(conn, recipient_id)).await??; + let recipient = + blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??; let note = Note { context: lemmy_context(), @@ -168,12 +163,6 @@ impl ToApub for ApubPrivateMessage { NoteType::Note, ) } -} - -#[async_trait::async_trait(?Send)] -impl FromApub for ApubPrivateMessage { - type ApubType = Note; - type DataType = LemmyContext; async fn from_apub( note: &Note, @@ -253,7 +242,7 @@ mod tests { assert_eq!(pm.content.len(), 20); assert_eq!(request_counter, 0); - let to_apub = pm.to_apub(context.pool()).await.unwrap(); + let to_apub = pm.to_apub(&context).await.unwrap(); assert_json_include!(actual: json, expected: to_apub); PrivateMessage::delete(&*context.pool().get().unwrap(), pm.id).unwrap(); diff --git a/crates/apub_lib/src/traits.rs b/crates/apub_lib/src/traits.rs index c2c1d02a3..2240946d4 100644 --- a/crates/apub_lib/src/traits.rs +++ b/crates/apub_lib/src/traits.rs @@ -30,6 +30,9 @@ pub trait ActivityHandler { #[async_trait::async_trait(?Send)] pub trait ApubObject { type DataType; + type ApubType; + type TombstoneType; + /// If this object should be refetched after a certain interval, it should return the last refresh /// time here. This is mainly used to update remote actors. fn last_refreshed_at(&self) -> Option; @@ -42,6 +45,25 @@ pub trait ApubObject { Self: Sized; /// Marks the object as deleted in local db. Called when a tombstone is received. 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; + fn to_tombstone(&self) -> Result; + + /// Converts an object from ActivityPub type to Lemmy internal type. + /// + /// * `apub` The object to read from + /// * `context` LemmyContext which holds DB pool, HTTP client etc + /// * `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, + data: &Self::DataType, + expected_domain: &Url, + request_counter: &mut i32, + ) -> Result + where + Self: Sized; } /// Common methods provided by ActivityPub actors (community and person). Not all methods are @@ -71,35 +93,3 @@ pub trait ActorType { }) } } - -/// Trait for converting an object or actor into the respective ActivityPub type. -#[async_trait::async_trait(?Send)] -pub trait ToApub { - type ApubType; - type TombstoneType; - type DataType; - - async fn to_apub(&self, data: &Self::DataType) -> Result; - fn to_tombstone(&self) -> Result; -} - -#[async_trait::async_trait(?Send)] -pub trait FromApub { - type ApubType; - type DataType; - - /// Converts an object from ActivityPub type to Lemmy internal type. - /// - /// * `apub` The object to read from - /// * `context` LemmyContext which holds DB pool, HTTP client etc - /// * `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, - data: &Self::DataType, - expected_domain: &Url, - request_counter: &mut i32, - ) -> Result - where - Self: Sized; -}