diff --git a/crates/apub_receive/src/activities/community/announce.rs b/crates/apub_receive/src/activities/community/announce.rs index cdae448f1..7f4eaa5b1 100644 --- a/crates/apub_receive/src/activities/community/announce.rs +++ b/crates/apub_receive/src/activities/community/announce.rs @@ -19,6 +19,7 @@ use crate::{ http::is_activity_already_known, }; use activitystreams::activity::kind::AnnounceType; +use lemmy_apub::insert_activity; use lemmy_apub_lib::{ActivityCommonFields, ActivityHandlerNew, PublicUrl}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; @@ -49,7 +50,7 @@ pub enum AnnouncableActivities { pub struct AnnounceActivity { to: PublicUrl, object: AnnouncableActivities, - cc: [Url; 1], + cc: Vec, #[serde(rename = "type")] kind: AnnounceType, #[serde(flatten)] @@ -65,6 +66,7 @@ impl ActivityHandlerNew for AnnounceActivity { ) -> Result<(), LemmyError> { verify_activity(self.common())?; verify_community(&self.common.actor, context, request_counter).await?; + self.object.verify(context, request_counter).await?; Ok(()) } @@ -76,6 +78,14 @@ impl ActivityHandlerNew for AnnounceActivity { if is_activity_already_known(context.pool(), self.object.common().id_unchecked()).await? { return Ok(()); } + insert_activity( + self.object.common().id_unchecked(), + self.object.clone(), + false, + true, + context.pool(), + ) + .await?; self.object.receive(context, request_counter).await } diff --git a/crates/apub_receive/src/activities/community/block_user.rs b/crates/apub_receive/src/activities/community/block_user.rs index 2c2676bfe..a67296a24 100644 --- a/crates/apub_receive/src/activities/community/block_user.rs +++ b/crates/apub_receive/src/activities/community/block_user.rs @@ -1,11 +1,11 @@ -use crate::activities::verify_mod_action; +use crate::activities::{verify_activity, verify_mod_action, verify_person_in_community}; use activitystreams::activity::kind::BlockType; use lemmy_api_common::blocking; -use lemmy_apub::{ - check_is_apub_id_valid, - fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person}, +use lemmy_apub::fetcher::{ + community::get_or_fetch_and_upsert_community, + person::get_or_fetch_and_upsert_person, }; -use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl}; +use lemmy_apub_lib::{ActivityCommonFields, ActivityHandlerNew, PublicUrl}; use lemmy_db_queries::{Bannable, Followable}; use lemmy_db_schema::source::community::{ CommunityFollower, @@ -31,10 +31,15 @@ pub struct BlockUserFromCommunity { #[async_trait::async_trait(?Send)] impl ActivityHandlerNew for BlockUserFromCommunity { - async fn verify(&self, context: &LemmyContext, _: &mut i32) -> Result<(), LemmyError> { - verify_domains_match(&self.common.actor, self.common.id_unchecked())?; - check_is_apub_id_valid(&self.common.actor, false)?; - verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await + async fn verify( + &self, + context: &LemmyContext, + request_counter: &mut i32, + ) -> Result<(), LemmyError> { + verify_activity(self.common())?; + verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?; + verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?; + Ok(()) } async fn receive( diff --git a/crates/apub_receive/src/activities/community/undo_block_user.rs b/crates/apub_receive/src/activities/community/undo_block_user.rs index 69f7f20b8..b9257badf 100644 --- a/crates/apub_receive/src/activities/community/undo_block_user.rs +++ b/crates/apub_receive/src/activities/community/undo_block_user.rs @@ -1,11 +1,16 @@ -use crate::activities::{community::block_user::BlockUserFromCommunity, verify_mod_action}; -use activitystreams::activity::kind::BlockType; -use lemmy_api_common::blocking; -use lemmy_apub::{ - check_is_apub_id_valid, - fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person}, +use crate::activities::{ + community::block_user::BlockUserFromCommunity, + verify_activity, + verify_mod_action, + verify_person_in_community, }; -use lemmy_apub_lib::{verify_domains_match, ActivityCommonFields, ActivityHandlerNew, PublicUrl}; +use activitystreams::activity::kind::UndoType; +use lemmy_api_common::blocking; +use lemmy_apub::fetcher::{ + community::get_or_fetch_and_upsert_community, + person::get_or_fetch_and_upsert_person, +}; +use lemmy_apub_lib::{ActivityCommonFields, ActivityHandlerNew, PublicUrl}; use lemmy_db_queries::Bannable; use lemmy_db_schema::source::community::{CommunityPersonBan, CommunityPersonBanForm}; use lemmy_utils::LemmyError; @@ -19,7 +24,7 @@ pub struct UndoBlockUserFromCommunity { object: BlockUserFromCommunity, cc: [Url; 1], #[serde(rename = "type")] - kind: BlockType, + kind: UndoType, #[serde(flatten)] common: ActivityCommonFields, } @@ -31,10 +36,11 @@ impl ActivityHandlerNew for UndoBlockUserFromCommunity { context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_domains_match(&self.common.actor, self.common.id_unchecked())?; - check_is_apub_id_valid(&self.common.actor, false)?; + verify_activity(self.common())?; + verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?; verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?; - self.object.verify(context, request_counter).await + self.object.verify(context, request_counter).await?; + Ok(()) } async fn receive( diff --git a/crates/apub_receive/src/activities/post/update.rs b/crates/apub_receive/src/activities/post/update.rs index 502792a0a..ac1f02dc2 100644 --- a/crates/apub_receive/src/activities/post/update.rs +++ b/crates/apub_receive/src/activities/post/update.rs @@ -49,14 +49,13 @@ impl ActivityHandlerNew for UpdatePost { verify_activity(self.common())?; let community = verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?; - verify_domains_match_opt(&self.common.actor, self.object.id_unchecked())?; let temp_post = PostForm::from_apub( &self.object, context, self.common.actor.clone(), request_counter, - false, + true, ) .await?; let post_id: DbUrl = temp_post.ap_id.context(location_info!())?; @@ -66,9 +65,14 @@ impl ActivityHandlerNew for UpdatePost { .await??; let stickied = temp_post.stickied.context(location_info!())?; let locked = temp_post.locked.context(location_info!())?; + // community mod changed locked/sticky status if (stickied != old_post.stickied) || (locked != old_post.locked) { verify_mod_action(&self.common.actor, community.actor_id(), context).await?; } + // user edited their own post + else { + verify_domains_match_opt(&self.common.actor, self.object.id_unchecked())?; + } Ok(()) } diff --git a/crates/apub_receive/src/http/mod.rs b/crates/apub_receive/src/http/mod.rs index 36d30d84d..d15c958ec 100644 --- a/crates/apub_receive/src/http/mod.rs +++ b/crates/apub_receive/src/http/mod.rs @@ -50,6 +50,8 @@ async fn payload_to_string(mut payload: Payload) -> Result { Bytes::from(bytes).as_ref().read_to_string(&mut unparsed)?; Ok(unparsed) } + +// TODO: move most of this code to library async fn receive_activity<'a, T>( request: HttpRequest, activity: &'a str, @@ -60,19 +62,23 @@ where { let activity = serde_json::from_str::(activity)?; let activity_data = activity.common(); - // TODO: which order to check things? - // Do nothing if we received the same activity before - if is_activity_already_known(context.pool(), activity_data.id_unchecked()).await? { - return Ok(HttpResponse::Ok().finish()); - } let request_counter = &mut 0; 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 + if is_activity_already_known(context.pool(), activity_data.id_unchecked()).await? { + return Ok(HttpResponse::Ok().finish()); + } + check_is_apub_id_valid(&activity_data.actor, false)?; + println!( + "Verifying activity {}", + activity_data.id_unchecked().to_string() + ); activity.verify(&context, request_counter).await?; assert_activity_not_local(&activity)?; - check_is_apub_id_valid(&activity_data.actor, false)?; // 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. @@ -85,6 +91,10 @@ where ) .await?; + println!( + "Receiving activity {}", + activity_data.id_unchecked().to_string() + ); activity.receive(&context, request_counter).await?; Ok(HttpResponse::Ok().finish()) }