From ddf1db0980e7558ba567f0153b9f17763649d6b5 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Sun, 15 Aug 2021 15:41:29 +0200 Subject: [PATCH] Simplify inbox --- .../apub/src/activities/community/update.rs | 1 + crates/apub/src/http/community.rs | 30 ++++++- crates/apub/src/http/inbox_enums.rs | 82 ------------------- crates/apub/src/http/mod.rs | 45 +++++++--- crates/apub/src/http/person.rs | 36 +++++++- 5 files changed, 93 insertions(+), 101 deletions(-) delete mode 100644 crates/apub/src/http/inbox_enums.rs diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index 3b60981e3..db4b141ba 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -29,6 +29,7 @@ use url::Url; #[serde(rename_all = "camelCase")] pub struct UpdateCommunity { to: PublicUrl, + // TODO: would be nice to use a separate struct here, which only contains the fields updated here object: Group, cc: [Url; 1], #[serde(rename = "type")] diff --git a/crates/apub/src/http/community.rs b/crates/apub/src/http/community.rs index 587c6cfb8..6c8bcb658 100644 --- a/crates/apub/src/http/community.rs +++ b/crates/apub/src/http/community.rs @@ -1,10 +1,13 @@ use crate::{ + activities::{ + community::announce::AnnouncableActivities, + following::{follow::FollowCommunity, undo::UndoFollowCommunity}, + }, extensions::context::lemmy_context, generate_moderators_url, http::{ create_apub_response, create_apub_tombstone_response, - inbox_enums::GroupInboxActivities, payload_to_string, receive_activity, }, @@ -18,6 +21,7 @@ use activitystreams::{ }; use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse}; use lemmy_api_common::blocking; +use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler}; use lemmy_db_queries::source::{activity::Activity_, community::Community_}; use lemmy_db_schema::source::{activity::Activity, community::Community}; use lemmy_db_views_actor::{ @@ -26,7 +30,8 @@ use lemmy_db_views_actor::{ }; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; -use serde::Deserialize; +use log::trace; +use serde::{Deserialize, Serialize}; #[derive(Deserialize)] pub(crate) struct CommunityQuery { @@ -52,6 +57,14 @@ pub(crate) async fn get_apub_community_http( } } +#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] +#[serde(untagged)] +pub enum GroupInboxActivities { + FollowCommunity(FollowCommunity), + UndoFollowCommunity(UndoFollowCommunity), + AnnouncableActivities(AnnouncableActivities), +} + /// Handler for all incoming receive to community inboxes. pub async fn community_inbox( request: HttpRequest, @@ -60,7 +73,18 @@ pub async fn community_inbox( context: web::Data, ) -> Result { let unparsed = payload_to_string(payload).await?; - receive_activity::(request, &unparsed, context).await + trace!("Received community inbox activity {}", unparsed); + let activity = serde_json::from_str::(&unparsed)?; + + receive_group_inbox(activity.clone(), request, context).await +} + +pub(in crate::http) async fn receive_group_inbox( + activity: GroupInboxActivities, + request: HttpRequest, + context: web::Data, +) -> Result { + receive_activity(request, activity.clone(), context.get_ref()).await } /// Returns an empty followers collection, only populating the size (for privacy). diff --git a/crates/apub/src/http/inbox_enums.rs b/crates/apub/src/http/inbox_enums.rs deleted file mode 100644 index e3726e95e..000000000 --- a/crates/apub/src/http/inbox_enums.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::activities::{ - comment::create_or_update::CreateOrUpdateComment, - community::{ - add_mod::AddMod, - announce::AnnounceActivity, - block_user::BlockUserFromCommunity, - remove_mod::RemoveMod, - undo_block_user::UndoBlockUserFromCommunity, - update::UpdateCommunity, - }, - deletion::{delete::Delete, undo_delete::UndoDelete}, - following::{accept::AcceptFollowCommunity, follow::FollowCommunity, undo::UndoFollowCommunity}, - post::create_or_update::CreateOrUpdatePost, - private_message::{ - create_or_update::CreateOrUpdatePrivateMessage, - delete::DeletePrivateMessage, - undo_delete::UndoDeletePrivateMessage, - }, - undo_remove::UndoRemovePostCommentOrCommunity, - voting::{undo_vote::UndoVote, vote::Vote}, -}; -use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler}; -use lemmy_utils::LemmyError; -use lemmy_websocket::LemmyContext; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] -#[serde(untagged)] -pub enum PersonInboxActivities { - AcceptFollowCommunity(AcceptFollowCommunity), - CreateOrUpdatePrivateMessage(CreateOrUpdatePrivateMessage), - DeletePrivateMessage(DeletePrivateMessage), - UndoDeletePrivateMessage(UndoDeletePrivateMessage), - AnnounceActivity(Box), -} - -#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] -#[serde(untagged)] -pub enum GroupInboxActivities { - FollowCommunity(FollowCommunity), - UndoFollowCommunity(UndoFollowCommunity), - CreateOrUpdateComment(CreateOrUpdateComment), - CreateOrUpdatePost(Box), - Vote(Vote), - UndoVote(UndoVote), - DeletePostCommentOrCommunity(Delete), - UndoDeletePostCommentOrCommunity(UndoDelete), - UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity), - UpdateCommunity(Box), - BlockUserFromCommunity(BlockUserFromCommunity), - UndoBlockUserFromCommunity(UndoBlockUserFromCommunity), - AddMod(AddMod), - RemoveMod(RemoveMod), -} - -#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] -#[serde(untagged)] -pub enum SharedInboxActivities { - // received by group - FollowCommunity(FollowCommunity), - UndoFollowCommunity(UndoFollowCommunity), - CreateOrUpdateComment(CreateOrUpdateComment), - CreateOrUpdatePost(Box), - Vote(Vote), - UndoVote(UndoVote), - Delete(Delete), - UndoDelete(UndoDelete), - UndoRemovePostCommentOrCommunity(UndoRemovePostCommentOrCommunity), - UpdateCommunity(Box), - BlockUserFromCommunity(BlockUserFromCommunity), - UndoBlockUserFromCommunity(UndoBlockUserFromCommunity), - AddMod(AddMod), - RemoveMod(RemoveMod), - // received by person - AcceptFollowCommunity(AcceptFollowCommunity), - // 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. - CreateOrUpdatePrivateMessage(CreateOrUpdatePrivateMessage), - DeletePrivateMessage(DeletePrivateMessage), - UndoDeletePrivateMessage(UndoDeletePrivateMessage), - AnnounceActivity(Box), -} diff --git a/crates/apub/src/http/mod.rs b/crates/apub/src/http/mod.rs index 477345fd4..7a372f94c 100644 --- a/crates/apub/src/http/mod.rs +++ b/crates/apub/src/http/mod.rs @@ -2,7 +2,10 @@ use crate::{ check_is_apub_id_valid, extensions::signatures::verify_signature, fetcher::get_or_fetch_and_upsert_actor, - http::inbox_enums::SharedInboxActivities, + http::{ + community::{receive_group_inbox, GroupInboxActivities}, + person::{receive_person_inbox, PersonInboxActivities}, + }, insert_activity, APUB_JSON_CONTENT_TYPE, }; @@ -17,29 +20,47 @@ use anyhow::{anyhow, Context}; use futures::StreamExt; use http::StatusCode; use lemmy_api_common::blocking; -use lemmy_apub_lib::ActivityHandler; +use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler}; use lemmy_db_queries::{source::activity::Activity_, DbPool}; use lemmy_db_schema::source::activity::Activity; use lemmy_utils::{location_info, settings::structs::Settings, LemmyError}; use lemmy_websocket::LemmyContext; +use log::{info, trace}; use serde::{Deserialize, Serialize}; use std::{fmt::Debug, io::Read}; use url::Url; mod comment; mod community; -mod inbox_enums; mod person; mod post; pub mod routes; +#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] +#[serde(untagged)] +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), +} + pub async fn shared_inbox( request: HttpRequest, payload: Payload, context: web::Data, ) -> Result { let unparsed = payload_to_string(payload).await?; - receive_activity::(request, &unparsed, context).await + trace!("Received shared inbox activity {}", unparsed); + let activity = serde_json::from_str::(&unparsed)?; + match activity { + SharedInboxActivities::GroupInboxActivities(g) => { + receive_group_inbox(g, request, context).await + } + SharedInboxActivities::PersonInboxActivities(p) => { + receive_person_inbox(p, request, context).await + } + } } async fn payload_to_string(mut payload: Payload) -> Result { @@ -55,18 +76,16 @@ async fn payload_to_string(mut payload: Payload) -> Result { // TODO: move most of this code to library async fn receive_activity<'a, T>( request: HttpRequest, - activity: &'a str, - context: web::Data, + activity: T, + context: &LemmyContext, ) -> Result where T: ActivityHandler + Clone + Deserialize<'a> + Serialize + std::fmt::Debug + Send + 'static, { - let activity = serde_json::from_str::(activity)?; let activity_data = activity.common(); let request_counter = &mut 0; - let actor = - get_or_fetch_and_upsert_actor(&activity_data.actor, &context, request_counter).await?; + let actor = get_or_fetch_and_upsert_actor(&activity_data.actor, context, request_counter).await?; verify_signature(&request, &actor.public_key().context(location_info!())?)?; // Do nothing if we received the same activity before @@ -74,11 +93,11 @@ where return Ok(HttpResponse::Ok().finish()); } check_is_apub_id_valid(&activity_data.actor, false)?; - println!( + info!( "Verifying activity {}", activity_data.id_unchecked().to_string() ); - activity.verify(&context, request_counter).await?; + activity.verify(context, request_counter).await?; assert_activity_not_local(&activity)?; // Log the activity, so we avoid receiving and parsing it twice. Note that this could still happen @@ -92,11 +111,11 @@ where ) .await?; - println!( + info!( "Receiving activity {}", activity_data.id_unchecked().to_string() ); - activity.receive(&context, request_counter).await?; + activity.receive(context, request_counter).await?; Ok(HttpResponse::Ok().finish()) } diff --git a/crates/apub/src/http/person.rs b/crates/apub/src/http/person.rs index 42f25bb62..539f05b75 100644 --- a/crates/apub/src/http/person.rs +++ b/crates/apub/src/http/person.rs @@ -1,9 +1,17 @@ use crate::{ + activities::{ + community::announce::AnnounceActivity, + following::accept::AcceptFollowCommunity, + private_message::{ + create_or_update::CreateOrUpdatePrivateMessage, + delete::DeletePrivateMessage, + undo_delete::UndoDeletePrivateMessage, + }, + }, extensions::context::lemmy_context, http::{ create_apub_response, create_apub_tombstone_response, - inbox_enums::PersonInboxActivities, payload_to_string, receive_activity, }, @@ -16,11 +24,13 @@ use activitystreams::{ }; use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse}; use lemmy_api_common::blocking; +use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler}; use lemmy_db_queries::source::person::Person_; use lemmy_db_schema::source::person::Person; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; -use serde::Deserialize; +use log::trace; +use serde::{Deserialize, Serialize}; use url::Url; #[derive(Deserialize)] @@ -49,6 +59,16 @@ pub(crate) async fn get_apub_person_http( } } +#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)] +#[serde(untagged)] +pub enum PersonInboxActivities { + AcceptFollowCommunity(AcceptFollowCommunity), + CreateOrUpdatePrivateMessage(CreateOrUpdatePrivateMessage), + DeletePrivateMessage(DeletePrivateMessage), + UndoDeletePrivateMessage(UndoDeletePrivateMessage), + AnnounceActivity(Box), +} + pub async fn person_inbox( request: HttpRequest, payload: Payload, @@ -56,7 +76,17 @@ pub async fn person_inbox( context: web::Data, ) -> Result { let unparsed = payload_to_string(payload).await?; - receive_activity::(request, &unparsed, context).await + trace!("Received person inbox activity {}", unparsed); + let activity = serde_json::from_str::(&unparsed)?; + receive_person_inbox(activity, request, context).await +} + +pub(in crate::http) async fn receive_person_inbox( + activity: PersonInboxActivities, + request: HttpRequest, + context: web::Data, +) -> Result { + receive_activity(request, activity, context.get_ref()).await } pub(crate) async fn get_apub_person_outbox(