From b605057e8555b292a1d202608737cf54c6a3433c Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Thu, 24 Jun 2021 03:21:05 +0200 Subject: [PATCH] implemented some more --- .../src/activities/receive/comment.rs | 67 +---------------- .../src/activities/receive/private_message.rs | 50 +------------ .../src/activities_new/comment.rs | 74 +++++++++++++++++++ .../apub_receive/src/activities_new/follow.rs | 12 +-- crates/apub_receive/src/activities_new/mod.rs | 2 + .../src/activities_new/private_message.rs | 64 ++++++++++++++++ .../src/inbox/new_inbox_routing.rs | 15 +++- crates/apub_receive/src/inbox/person_inbox.rs | 47 ++---------- .../src/inbox/receive_for_community.rs | 3 +- 9 files changed, 167 insertions(+), 167 deletions(-) create mode 100644 crates/apub_receive/src/activities_new/comment.rs create mode 100644 crates/apub_receive/src/activities_new/private_message.rs diff --git a/crates/apub_receive/src/activities/receive/comment.rs b/crates/apub_receive/src/activities/receive/comment.rs index b285f595..419fb70c 100644 --- a/crates/apub_receive/src/activities/receive/comment.rs +++ b/crates/apub_receive/src/activities/receive/comment.rs @@ -1,6 +1,6 @@ use crate::activities::receive::get_actor_as_person; use activitystreams::{ - activity::{ActorAndObjectRefExt, Create, Dislike, Like, Update}, + activity::{ActorAndObjectRefExt, Dislike, Like, Update}, base::ExtendsExt, }; use anyhow::Context; @@ -15,71 +15,6 @@ use lemmy_db_views::comment_view::CommentView; use lemmy_utils::{location_info, utils::scrape_text_for_mentions, LemmyError}; use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperation, UserOperationCrud}; -// TODO: -// - define traits for all activity types -// - implement inbox routing with these traits -// - replace context with actix style Data struct (actix_web::web::Data) -pub(crate) trait ReceiveCreate { - fn receive_create(self, create: Create, context: LemmyContext, request_counter: &mut i32); -} - -impl ReceiveCreate for Comment { - fn receive_create(self, _create: Create, _context: LemmyContext, _request_counter: &mut i32) { - unimplemented!() - } -} - -pub(crate) async fn receive_create_comment( - create: Create, - context: &LemmyContext, - request_counter: &mut i32, -) -> Result<(), LemmyError> { - let person = get_actor_as_person(&create, context, request_counter).await?; - let note = NoteExt::from_any_base(create.object().to_owned().one().context(location_info!())?)? - .context(location_info!())?; - - let comment = - Comment::from_apub(¬e, context, person.actor_id(), request_counter, false).await?; - - let post_id = comment.post_id; - let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; - - // Note: - // Although mentions could be gotten from the post tags (they are included there), or the ccs, - // Its much easier to scrape them from the comment body, since the API has to do that - // anyway. - let mentions = scrape_text_for_mentions(&comment.content); - let recipient_ids = send_local_notifs( - mentions, - comment.clone(), - person, - post, - context.pool(), - true, - ) - .await?; - - // Refetch the view - let comment_view = blocking(context.pool(), move |conn| { - CommentView::read(conn, comment.id, None) - }) - .await??; - - let res = CommentResponse { - comment_view, - recipient_ids, - form_id: None, - }; - - context.chat_server().do_send(SendComment { - op: UserOperationCrud::CreateComment, - comment: res, - websocket_id: None, - }); - - Ok(()) -} - pub(crate) async fn receive_update_comment( update: Update, context: &LemmyContext, diff --git a/crates/apub_receive/src/activities/receive/private_message.rs b/crates/apub_receive/src/activities/receive/private_message.rs index a0dcb81e..0519b681 100644 --- a/crates/apub_receive/src/activities/receive/private_message.rs +++ b/crates/apub_receive/src/activities/receive/private_message.rs @@ -1,6 +1,6 @@ use crate::activities::receive::verify_activity_domains_valid; use activitystreams::{ - activity::{ActorAndObjectRefExt, Create, Delete, Undo, Update}, + activity::{ActorAndObjectRefExt, Delete, Undo, Update}, base::{AsBase, ExtendsExt}, object::AsObject, public, @@ -21,54 +21,6 @@ use lemmy_utils::{location_info, LemmyError}; use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperationCrud}; use url::Url; -pub(crate) async fn receive_create_private_message( - context: &LemmyContext, - create: Create, - expected_domain: Url, - request_counter: &mut i32, -) -> Result<(), LemmyError> { - check_private_message_activity_valid(&create, context, request_counter).await?; - - let note = NoteExt::from_any_base( - create - .object() - .as_one() - .context(location_info!())? - .to_owned(), - )? - .context(location_info!())?; - - let private_message = - PrivateMessage::from_apub(¬e, context, expected_domain, request_counter, false).await?; - - let message = blocking(&context.pool(), move |conn| { - PrivateMessageView::read(conn, private_message.id) - }) - .await??; - - let res = PrivateMessageResponse { - private_message_view: message, - }; - - // Send notifications to the local recipient, if one exists - let recipient_id = res.private_message_view.recipient.id; - let local_recipient_id = blocking(context.pool(), move |conn| { - LocalUserView::read_person(conn, recipient_id) - }) - .await?? - .local_user - .id; - - context.chat_server().do_send(SendUserRoomMessage { - op: UserOperationCrud::CreatePrivateMessage, - response: res, - local_recipient_id, - websocket_id: None, - }); - - Ok(()) -} - pub(crate) async fn receive_update_private_message( context: &LemmyContext, update: Update, diff --git a/crates/apub_receive/src/activities_new/comment.rs b/crates/apub_receive/src/activities_new/comment.rs new file mode 100644 index 00000000..2c552f76 --- /dev/null +++ b/crates/apub_receive/src/activities_new/comment.rs @@ -0,0 +1,74 @@ +use crate::inbox::new_inbox_routing::{ReceiveActivity, Activity, PublicUrl}; +use url::Url; +use lemmy_apub::NoteExt; +use activitystreams:: + activity::kind::{CreateType}; +use lemmy_websocket::{LemmyContext, UserOperationCrud}; +use lemmy_utils::LemmyError; +use lemmy_db_views::comment_view::CommentView; +use lemmy_api_common::comment::CommentResponse; +use lemmy_websocket::messages::SendComment; +use lemmy_api_common::{send_local_notifs, blocking}; +use lemmy_db_schema::source::comment::Comment; +use lemmy_apub::objects::FromApub; +use lemmy_utils::utils::scrape_text_for_mentions; +use lemmy_db_schema::source::post::Post; +use lemmy_db_queries::Crud; +use lemmy_apub::fetcher::person::get_or_fetch_and_upsert_person; + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CreateComment { + actor: Url, + to: PublicUrl, + object: NoteExt, + #[serde(rename = "type")] + kind: CreateType, +} + +#[async_trait::async_trait(?Send)] +impl ReceiveActivity for Activity { + async fn receive(&self, context: &LemmyContext, request_counter: &mut i32) -> Result<(), LemmyError> { + let comment = + Comment::from_apub(&self.inner.object, context, self.inner.actor.clone(), request_counter, false).await?; + + let post_id = comment.post_id; + let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; + let actor = get_or_fetch_and_upsert_person(&self.inner.actor, context, request_counter).await?; + + // Note: + // Although mentions could be gotten from the post tags (they are included there), or the ccs, + // Its much easier to scrape them from the comment body, since the API has to do that + // anyway. + let mentions = scrape_text_for_mentions(&comment.content); + let recipient_ids = send_local_notifs( + mentions, + comment.clone(), + actor, + post, + context.pool(), + true, + ) + .await?; + + // Refetch the view + let comment_view = blocking(context.pool(), move |conn| { + CommentView::read(conn, comment.id, None) + }) + .await??; + + let res = CommentResponse { + comment_view, + recipient_ids, + form_id: None, + }; + + context.chat_server().do_send(SendComment { + op: UserOperationCrud::CreateComment, + comment: res, + websocket_id: None, + }); + + Ok(()) + } +} \ No newline at end of file diff --git a/crates/apub_receive/src/activities_new/follow.rs b/crates/apub_receive/src/activities_new/follow.rs index 75e83593..3fbca98e 100644 --- a/crates/apub_receive/src/activities_new/follow.rs +++ b/crates/apub_receive/src/activities_new/follow.rs @@ -1,12 +1,9 @@ use crate::{ - activities::receive::verify_activity_domains_valid, inbox::new_inbox_routing::{verify_domains_match, Activity, ReceiveActivity}, }; use activitystreams::{ activity::kind::{AcceptType, FollowType}, - base::ExtendsExt, }; -use anyhow::Context; use lemmy_api_common::blocking; use lemmy_apub::fetcher::{ community::get_or_fetch_and_upsert_community, @@ -14,14 +11,13 @@ use lemmy_apub::fetcher::{ }; use lemmy_db_queries::Followable; use lemmy_db_schema::source::community::CommunityFollower; -use lemmy_utils::{location_info, LemmyError}; +use lemmy_utils::{LemmyError}; use lemmy_websocket::LemmyContext; use url::Url; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] pub struct Follow { - // todo: implement newtypes PersonUrl, GroupUrl etc (with deref function) actor: Url, to: Url, object: Url, @@ -33,8 +29,8 @@ pub struct Follow { impl ReceiveActivity for Activity { async fn receive( &self, - context: &LemmyContext, - request_counter: &mut i32, + _context: &LemmyContext, + _request_counter: &mut i32, ) -> Result<(), LemmyError> { println!("receive follow"); todo!() @@ -44,7 +40,6 @@ impl ReceiveActivity for Activity { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] pub struct Accept { - // todo: implement newtypes PersonUrl, GroupUrl etc (with deref function) actor: Url, to: Url, object: Activity, @@ -60,6 +55,7 @@ impl ReceiveActivity for Activity { context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { + // TODO: move check for id.domain == actor.domain to library and do it automatically verify_domains_match(&self.inner.actor, self.id_unchecked())?; let follow = &self.inner.object; verify_domains_match(&follow.inner.actor, &follow.id_unchecked())?; diff --git a/crates/apub_receive/src/activities_new/mod.rs b/crates/apub_receive/src/activities_new/mod.rs index 62d6fa2b..19f1df3b 100644 --- a/crates/apub_receive/src/activities_new/mod.rs +++ b/crates/apub_receive/src/activities_new/mod.rs @@ -1 +1,3 @@ +pub mod comment; pub mod follow; +pub mod private_message; diff --git a/crates/apub_receive/src/activities_new/private_message.rs b/crates/apub_receive/src/activities_new/private_message.rs new file mode 100644 index 00000000..50a63046 --- /dev/null +++ b/crates/apub_receive/src/activities_new/private_message.rs @@ -0,0 +1,64 @@ +use crate::inbox::new_inbox_routing::{Activity, ReceiveActivity}; +use activitystreams::activity::kind::CreateType; +use lemmy_api_common::{blocking, person::PrivateMessageResponse}; +use lemmy_apub::{objects::FromApub, NoteExt}; +use lemmy_db_schema::source::private_message::PrivateMessage; +use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView}; +use lemmy_utils::LemmyError; +use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperationCrud}; +use url::Url; + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CreatePrivateMessage { + actor: Url, + to: Url, + object: NoteExt, + #[serde(rename = "type")] + kind: CreateType, +} + +#[async_trait::async_trait(?Send)] +impl ReceiveActivity for Activity { + async fn receive( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result<(), LemmyError> { + let private_message = PrivateMessage::from_apub( + &self.inner.object, + context, + self.inner.actor.clone(), + request_counter, + false, + ) + .await?; + + let message = blocking(&context.pool(), move |conn| { + PrivateMessageView::read(conn, private_message.id) + }) + .await??; + + let res = PrivateMessageResponse { + private_message_view: message, + }; + + // Send notifications to the local recipient, if one exists + let recipient_id = res.private_message_view.recipient.id; + let local_recipient_id = blocking(context.pool(), move |conn| { + LocalUserView::read_person(conn, recipient_id) + }) + .await?? + .local_user + .id; + + context.chat_server().do_send(SendUserRoomMessage { + op: UserOperationCrud::CreatePrivateMessage, + response: res, + local_recipient_id, + websocket_id: None, + }); + + Ok(()) + } +} diff --git a/crates/apub_receive/src/inbox/new_inbox_routing.rs b/crates/apub_receive/src/inbox/new_inbox_routing.rs index 0f64951d..26a010f3 100644 --- a/crates/apub_receive/src/inbox/new_inbox_routing.rs +++ b/crates/apub_receive/src/inbox/new_inbox_routing.rs @@ -9,6 +9,8 @@ use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use std::marker::PhantomData; use url::Url; +use crate::activities_new::private_message::CreatePrivateMessage; +use crate::activities_new::comment::CreateComment; // for now, limit it to activity routing only, no http sigs, parsing or any of that // need to route in this order: @@ -24,16 +26,22 @@ use url::Url; // .checkHttpSig::() // .fetchObject() - for custom http client // .checkActivity() - for common validity checks -struct InboxConfig { +pub struct InboxConfig { //actors: Vec, } impl InboxConfig { - fn shared_inbox_handler() { + pub fn shared_inbox_handler() { todo!() } } +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub enum PublicUrl { + #[serde(rename = "https://www.w3.org/ns/activitystreams#Public")] + Public, +} + pub fn verify_domains_match(a: &Url, b: &Url) -> Result<(), LemmyError> { if a.domain() != b.domain() { return Err(DomainError.into()); @@ -94,6 +102,8 @@ impl Activity { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub enum PersonAcceptedActivitiesNew { Accept(Accept), + CreatePrivateMessage(CreatePrivateMessage), + CreateComment(CreateComment) } // todo: there should be a better way to do this (maybe needs a derive macro) @@ -104,7 +114,6 @@ impl ReceiveActivity for PersonAcceptedActivitiesNew { context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { - use PersonAcceptedActivitiesNew::*; self.receive(context, request_counter).await } } diff --git a/crates/apub_receive/src/inbox/person_inbox.rs b/crates/apub_receive/src/inbox/person_inbox.rs index 9b9d6518..f7981956 100644 --- a/crates/apub_receive/src/inbox/person_inbox.rs +++ b/crates/apub_receive/src/inbox/person_inbox.rs @@ -1,6 +1,6 @@ use crate::{ activities::receive::{ - comment::{receive_create_comment, receive_update_comment}, + comment::receive_update_comment, community::{ receive_delete_community, receive_remove_community, @@ -8,7 +8,6 @@ use crate::{ receive_undo_remove_community, }, private_message::{ - receive_create_private_message, receive_delete_private_message, receive_undo_delete_private_message, receive_update_private_message, @@ -17,9 +16,6 @@ use crate::{ verify_activity_domains_valid, }, inbox::{ - assert_activity_not_local, - get_activity_id, - inbox_verify_http_signature, is_activity_already_known, is_addressed_to_community_followers, is_addressed_to_local_person, @@ -39,7 +35,7 @@ use crate::{ }, }; use activitystreams::{ - activity::{Accept, ActorAndObject, Announce, Create, Delete, Follow, Remove, Undo, Update}, + activity::{ActorAndObject, Announce, Delete, Remove, Undo, Update}, base::AnyBase, prelude::*, }; @@ -49,12 +45,10 @@ use diesel::NotFound; use lemmy_api_common::blocking; use lemmy_apub::{ check_is_apub_id_valid, - fetcher::community::get_or_fetch_and_upsert_community, get_activity_to_and_cc, - insert_activity, ActorType, }; -use lemmy_db_queries::{source::person::Person_, ApubObject, Followable}; +use lemmy_db_queries::{ApubObject, Followable}; use lemmy_db_schema::source::{ community::{Community, CommunityFollower}, person::Person, @@ -85,14 +79,14 @@ pub type PersonAcceptedActivities = ActorAndObject; /// Handler for all incoming activities to person inboxes. pub async fn person_inbox( - request: HttpRequest, + _request: HttpRequest, input: web::Json>, - path: web::Path, + _path: web::Path, context: web::Data, ) -> Result { let activity = input.into_inner(); let request_counter = &mut 0; - activity.inner.receive(&context, request_counter); + activity.inner.receive(&context, request_counter).await?; todo!() /* // First of all check the http signature @@ -134,7 +128,7 @@ pub async fn person_inbox( /// Receives Accept/Follow, Announce, private messages and community (undo) remove, (undo) delete pub(crate) async fn person_receive_message( activity: PersonAcceptedActivities, - to_person: Option, + _to_person: Option, actor: &dyn ActorType, context: &LemmyContext, request_counter: &mut i32, @@ -158,15 +152,7 @@ pub(crate) async fn person_receive_message( PersonValidTypes::Announce => { Box::pin(receive_announce(&context, any_base, actor, request_counter)).await? } - PersonValidTypes::Create => { - Box::pin(receive_create( - &context, - any_base, - actor_url, - request_counter, - )) - .await? - } + PersonValidTypes::Create => {} PersonValidTypes::Update => { Box::pin(receive_update( &context, @@ -326,23 +312,6 @@ pub async fn receive_announce( } } -/// Receive either a new private message, or a new comment mention. We distinguish them by checking -/// whether the activity is public. -async fn receive_create( - context: &LemmyContext, - activity: AnyBase, - expected_domain: Url, - request_counter: &mut i32, -) -> Result<(), LemmyError> { - let create = Create::from_any_base(activity)?.context(location_info!())?; - verify_activity_domains_valid(&create, &expected_domain, true)?; - if verify_is_addressed_to_public(&create).is_ok() { - receive_create_comment(create, context, request_counter).await - } else { - receive_create_private_message(&context, create, expected_domain, request_counter).await - } -} - /// Receive either an updated private message, or an updated comment mention. We distinguish /// them by checking whether the activity is public. async fn receive_update( diff --git a/crates/apub_receive/src/inbox/receive_for_community.rs b/crates/apub_receive/src/inbox/receive_for_community.rs index 970f80dd..776f0b54 100644 --- a/crates/apub_receive/src/inbox/receive_for_community.rs +++ b/crates/apub_receive/src/inbox/receive_for_community.rs @@ -1,7 +1,6 @@ use crate::{ activities::receive::{ comment::{ - receive_create_comment, receive_delete_comment, receive_dislike_comment, receive_like_comment, @@ -137,7 +136,7 @@ pub(in crate::inbox) async fn receive_create_for_community( .and_then(|s| s.parse().ok()); match kind { Some(ObjectTypes::Page) => receive_create_post(create, context, request_counter).await, - Some(ObjectTypes::Note) => receive_create_comment(create, context, request_counter).await, + Some(ObjectTypes::Note) => todo!(), _ => receive_unhandled_activity(create), } }