diff --git a/crates/apub_lib/src/lib.rs b/crates/apub_lib/src/lib.rs index a0e9980ef..990854c92 100644 --- a/crates/apub_lib/src/lib.rs +++ b/crates/apub_lib/src/lib.rs @@ -31,13 +31,6 @@ pub enum PublicUrl { Public, } -pub fn verify_domains_match(a: &Url, b: &Url) -> Result<(), LemmyError> { - if a.domain() != b.domain() { - return Err(DomainError.into()); - } - Ok(()) -} - // todo: later add a similar trait SendActivity // todo: maybe add a separate method verify() #[async_trait::async_trait(?Send)] @@ -50,6 +43,19 @@ pub trait ReceiveActivity { ) -> Result<(), LemmyError>; } +pub fn verify_domains_match(a: &Url, b: &Url) -> Result<(), LemmyError> { + if a.domain() != b.domain() { + return Err(DomainError.into()); + } + Ok(()) +} + +#[async_trait::async_trait(?Send)] +pub trait VerifyActivity { + // TODO: also need to check for instance/actor blocks in here i think + async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError>; +} + // todo: instead of phantomdata, might use option to cache the fetched object (or just fetch on construction) pub struct ObjectId<'a, Kind>(Url, &'a PhantomData); diff --git a/crates/apub_receive/src/activities/receive/mod.rs b/crates/apub_receive/src/activities/receive/mod.rs index 1fe073cf8..01e3f3b5f 100644 --- a/crates/apub_receive/src/activities/receive/mod.rs +++ b/crates/apub_receive/src/activities/receive/mod.rs @@ -15,7 +15,6 @@ use url::Url; pub(crate) mod comment_undo; pub(crate) mod community; pub(crate) mod post_undo; -pub(crate) mod private_message; /// Return HTTP 501 for unsupported activities in inbox. pub(crate) fn receive_unhandled_activity(activity: A) -> Result<(), LemmyError> diff --git a/crates/apub_receive/src/activities/receive/private_message.rs b/crates/apub_receive/src/activities/receive/private_message.rs deleted file mode 100644 index 37a94bb19..000000000 --- a/crates/apub_receive/src/activities/receive/private_message.rs +++ /dev/null @@ -1,37 +0,0 @@ -use activitystreams::{activity::ActorAndObjectRefExt, base::AsBase, object::AsObject, public}; -use anyhow::{anyhow, Context}; -use lemmy_apub::{ - check_is_apub_id_valid, - fetcher::person::get_or_fetch_and_upsert_person, - get_activity_to_and_cc, -}; -use lemmy_utils::{location_info, LemmyError}; -use lemmy_websocket::LemmyContext; - -// TODO: which of this do we still need? -async fn check_private_message_activity_valid( - activity: &T, - context: &LemmyContext, - request_counter: &mut i32, -) -> Result<(), LemmyError> -where - T: AsBase + AsObject + ActorAndObjectRefExt, -{ - let to_and_cc = get_activity_to_and_cc(activity); - if to_and_cc.len() != 1 { - return Err(anyhow!("Private message can only be addressed to one person").into()); - } - if to_and_cc.contains(&public()) { - return Err(anyhow!("Private message cant be public").into()); - } - let person_id = activity - .actor()? - .to_owned() - .single_xsd_any_uri() - .context(location_info!())?; - check_is_apub_id_valid(&person_id, false)?; - // check that the sender is a person, not a community - get_or_fetch_and_upsert_person(&person_id, &context, request_counter).await?; - - Ok(()) -} diff --git a/crates/apub_receive/src/activities_new/comment/create.rs b/crates/apub_receive/src/activities_new/comment/create.rs index 8c764af08..74a367e41 100644 --- a/crates/apub_receive/src/activities_new/comment/create.rs +++ b/crates/apub_receive/src/activities_new/comment/create.rs @@ -3,11 +3,10 @@ use crate::{ inbox::new_inbox_routing::Activity, }; use activitystreams::{activity::kind::CreateType, base::BaseExt}; -use anyhow::Context; -use lemmy_apub::{objects::FromApub, NoteExt}; -use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity}; +use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, NoteExt}; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_db_schema::source::comment::Comment; -use lemmy_utils::{location_info, LemmyError}; +use lemmy_utils::LemmyError; use lemmy_websocket::{LemmyContext, UserOperationCrud}; use url::Url; @@ -21,6 +20,15 @@ pub struct CreateComment { kind: CreateType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(self.id_unchecked(), &self.inner.actor)?; + self.inner.object.id(self.inner.actor.as_str())?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( @@ -28,12 +36,6 @@ impl ReceiveActivity for Activity { context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_domains_match(&self.inner.actor, self.id_unchecked())?; - verify_domains_match( - &self.inner.actor, - self.inner.object.id_unchecked().context(location_info!())?, - )?; - let comment = Comment::from_apub( &self.inner.object, context, diff --git a/crates/apub_receive/src/activities_new/comment/delete.rs b/crates/apub_receive/src/activities_new/comment/delete.rs index b9ba675bc..391665500 100644 --- a/crates/apub_receive/src/activities_new/comment/delete.rs +++ b/crates/apub_receive/src/activities_new/comment/delete.rs @@ -1,8 +1,8 @@ use crate::{activities_new::comment::send_websocket_message, inbox::new_inbox_routing::Activity}; use activitystreams::activity::kind::DeleteType; use lemmy_api_common::blocking; -use lemmy_apub::fetcher::objects::get_or_fetch_and_insert_comment; -use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; +use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_comment}; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_db_queries::source::comment::Comment_; use lemmy_db_schema::source::comment::Comment; use lemmy_utils::LemmyError; @@ -20,6 +20,15 @@ pub struct DeleteComment { kind: DeleteType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(&self.inner.actor, self.id_unchecked())?; + verify_domains_match(&self.inner.actor, &self.inner.object)?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( diff --git a/crates/apub_receive/src/activities_new/comment/dislike.rs b/crates/apub_receive/src/activities_new/comment/dislike.rs index ce71a214e..d2dbb2101 100644 --- a/crates/apub_receive/src/activities_new/comment/dislike.rs +++ b/crates/apub_receive/src/activities_new/comment/dislike.rs @@ -1,6 +1,7 @@ use crate::{activities_new::comment::like_or_dislike_comment, inbox::new_inbox_routing::Activity}; use activitystreams::activity::kind::DislikeType; -use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; +use lemmy_apub::check_is_apub_id_valid; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use url::Url; @@ -16,6 +17,14 @@ pub struct DislikeComment { kind: DislikeType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(&self.inner.actor, self.id_unchecked())?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( diff --git a/crates/apub_receive/src/activities_new/comment/like.rs b/crates/apub_receive/src/activities_new/comment/like.rs index fea69e38b..f9882d5a8 100644 --- a/crates/apub_receive/src/activities_new/comment/like.rs +++ b/crates/apub_receive/src/activities_new/comment/like.rs @@ -1,6 +1,7 @@ use crate::{activities_new::comment::like_or_dislike_comment, inbox::new_inbox_routing::Activity}; use activitystreams::activity::kind::LikeType; -use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; +use lemmy_apub::check_is_apub_id_valid; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use url::Url; @@ -16,6 +17,14 @@ pub struct LikeComment { kind: LikeType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(&self.inner.actor, self.id_unchecked())?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( diff --git a/crates/apub_receive/src/activities_new/comment/remove.rs b/crates/apub_receive/src/activities_new/comment/remove.rs index 5027a8717..e23d3b4de 100644 --- a/crates/apub_receive/src/activities_new/comment/remove.rs +++ b/crates/apub_receive/src/activities_new/comment/remove.rs @@ -1,8 +1,11 @@ -use crate::{activities_new::comment::send_websocket_message, inbox::new_inbox_routing::Activity}; +use crate::{ + activities_new::{comment::send_websocket_message, verify_mod_action}, + inbox::new_inbox_routing::Activity, +}; use activitystreams::activity::kind::RemoveType; use lemmy_api_common::blocking; -use lemmy_apub::fetcher::objects::get_or_fetch_and_insert_comment; -use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; +use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_comment}; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_db_queries::source::comment::Comment_; use lemmy_db_schema::source::comment::Comment; use lemmy_utils::LemmyError; @@ -20,6 +23,15 @@ pub struct RemoveComment { kind: RemoveType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(&self.inner.actor, self.id_unchecked())?; + check_is_apub_id_valid(&self.inner.actor, false)?; + verify_mod_action(self.inner.actor.clone(), self.inner.cc.clone(), context).await + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( diff --git a/crates/apub_receive/src/activities_new/comment/update.rs b/crates/apub_receive/src/activities_new/comment/update.rs index f4e50c947..540ec2a3d 100644 --- a/crates/apub_receive/src/activities_new/comment/update.rs +++ b/crates/apub_receive/src/activities_new/comment/update.rs @@ -3,11 +3,10 @@ use crate::{ inbox::new_inbox_routing::Activity, }; use activitystreams::{activity::kind::UpdateType, base::BaseExt}; -use anyhow::Context; -use lemmy_apub::{objects::FromApub, NoteExt}; -use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity}; +use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, NoteExt}; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_db_schema::source::comment::Comment; -use lemmy_utils::{location_info, LemmyError}; +use lemmy_utils::LemmyError; use lemmy_websocket::{LemmyContext, UserOperationCrud}; use url::Url; @@ -21,6 +20,15 @@ pub struct UpdateComment { kind: UpdateType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(self.id_unchecked(), &self.inner.actor)?; + self.inner.object.id(self.inner.actor.as_str())?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( @@ -28,12 +36,6 @@ impl ReceiveActivity for Activity { context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_domains_match(&self.inner.actor, self.id_unchecked())?; - verify_domains_match( - &self.inner.actor, - self.inner.object.id_unchecked().context(location_info!())?, - )?; - let comment = Comment::from_apub( &self.inner.object, context, diff --git a/crates/apub_receive/src/activities_new/follow.rs b/crates/apub_receive/src/activities_new/follow.rs index b984b1161..5be063541 100644 --- a/crates/apub_receive/src/activities_new/follow.rs +++ b/crates/apub_receive/src/activities_new/follow.rs @@ -5,7 +5,7 @@ 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, ReceiveActivity}; +use lemmy_apub_lib::{verify_domains_match, ReceiveActivity, VerifyActivity}; use lemmy_db_queries::Followable; use lemmy_db_schema::source::community::CommunityFollower; use lemmy_utils::LemmyError; @@ -22,6 +22,13 @@ pub struct FollowCommunity { kind: FollowType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + todo!() + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( @@ -44,6 +51,14 @@ pub struct AcceptFollowCommunity { kind: AcceptType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(self.id_unchecked(), &self.inner.actor)?; + self.inner.object.verify(context).await + } +} + /// Handle accepted follows #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { @@ -52,11 +67,6 @@ 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())?; - let community = get_or_fetch_and_upsert_community(&self.inner.actor, context, request_counter).await?; let person = get_or_fetch_and_upsert_person(&self.inner.to, context, request_counter).await?; diff --git a/crates/apub_receive/src/activities_new/mod.rs b/crates/apub_receive/src/activities_new/mod.rs index 1235106d8..95cd394ad 100644 --- a/crates/apub_receive/src/activities_new/mod.rs +++ b/crates/apub_receive/src/activities_new/mod.rs @@ -1,4 +1,51 @@ +use anyhow::{anyhow, Context}; +use lemmy_api_common::blocking; +use lemmy_db_queries::ApubObject; +use lemmy_db_schema::source::{community::Community, person::Person}; +use lemmy_db_views_actor::community_view::CommunityView; +use lemmy_utils::{location_info, LemmyError}; +use lemmy_websocket::LemmyContext; +use url::Url; + pub mod comment; pub mod follow; pub mod post; pub mod private_message; + +async fn verify_mod_action( + actor_id: Url, + activity_cc: Vec, + context: &LemmyContext, +) -> Result<(), LemmyError> { + let mut cc = activity_cc.into_iter(); + let community: Community = loop { + let current = cc.next().context(location_info!())?; + let community = blocking(context.pool(), move |conn| { + Community::read_from_apub_id(conn, ¤t.into()) + }) + .await?; + if let Ok(c) = community { + break c; + } + }; + + if community.local { + let actor = blocking(&context.pool(), move |conn| { + Person::read_from_apub_id(&conn, &actor_id.clone().into()) + }) + .await??; + + // Note: this will also return true for admins in addition to mods, but as we dont know about + // remote admins, it doesnt make any difference. + let community_id = community.id; + let actor_id = actor.id; + let is_mod_or_admin = blocking(context.pool(), move |conn| { + CommunityView::is_mod_or_admin(conn, actor_id, community_id) + }) + .await?; + if !is_mod_or_admin { + return Err(anyhow!("Not a mod").into()); + } + } + Ok(()) +} diff --git a/crates/apub_receive/src/activities_new/post/create.rs b/crates/apub_receive/src/activities_new/post/create.rs index baa477bb9..76872214e 100644 --- a/crates/apub_receive/src/activities_new/post/create.rs +++ b/crates/apub_receive/src/activities_new/post/create.rs @@ -1,12 +1,13 @@ use crate::{activities_new::post::send_websocket_message, inbox::new_inbox_routing::Activity}; -use activitystreams::activity::kind::CreateType; +use activitystreams::{activity::kind::CreateType, base::BaseExt}; use lemmy_apub::{ + check_is_apub_id_valid, fetcher::person::get_or_fetch_and_upsert_person, objects::FromApub, ActorType, PageExt, }; -use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_db_schema::source::post::Post; use lemmy_utils::LemmyError; use lemmy_websocket::{LemmyContext, UserOperationCrud}; @@ -22,6 +23,15 @@ pub struct CreatePost { kind: CreateType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(self.id_unchecked(), &self.inner.actor)?; + self.inner.object.id(self.inner.actor.as_str())?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( diff --git a/crates/apub_receive/src/activities_new/post/delete.rs b/crates/apub_receive/src/activities_new/post/delete.rs index 744bb50d2..b52ddd7d0 100644 --- a/crates/apub_receive/src/activities_new/post/delete.rs +++ b/crates/apub_receive/src/activities_new/post/delete.rs @@ -1,8 +1,8 @@ use crate::{activities_new::post::send_websocket_message, inbox::new_inbox_routing::Activity}; use activitystreams::activity::kind::DeleteType; use lemmy_api_common::blocking; -use lemmy_apub::fetcher::objects::get_or_fetch_and_insert_post; -use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; +use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_post}; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_db_queries::source::post::Post_; use lemmy_db_schema::source::post::Post; use lemmy_utils::LemmyError; @@ -19,6 +19,15 @@ pub struct DeletePost { kind: DeleteType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(&self.inner.actor, self.id_unchecked())?; + verify_domains_match(&self.inner.actor, &self.inner.object)?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( diff --git a/crates/apub_receive/src/activities_new/post/dislike.rs b/crates/apub_receive/src/activities_new/post/dislike.rs index 4f8529c3e..a46b7164e 100644 --- a/crates/apub_receive/src/activities_new/post/dislike.rs +++ b/crates/apub_receive/src/activities_new/post/dislike.rs @@ -1,6 +1,7 @@ use crate::{activities_new::post::like_or_dislike_post, inbox::new_inbox_routing::Activity}; use activitystreams::activity::kind::DislikeType; -use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; +use lemmy_apub::check_is_apub_id_valid; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use url::Url; @@ -15,6 +16,14 @@ pub struct DislikePost { kind: DislikeType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(&self.inner.actor, self.id_unchecked())?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( diff --git a/crates/apub_receive/src/activities_new/post/like.rs b/crates/apub_receive/src/activities_new/post/like.rs index 125636f9a..3154ac685 100644 --- a/crates/apub_receive/src/activities_new/post/like.rs +++ b/crates/apub_receive/src/activities_new/post/like.rs @@ -1,6 +1,7 @@ use crate::{activities_new::post::like_or_dislike_post, inbox::new_inbox_routing::Activity}; use activitystreams::activity::kind::LikeType; -use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; +use lemmy_apub::check_is_apub_id_valid; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use url::Url; @@ -15,6 +16,14 @@ pub struct LikePost { kind: LikeType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(&self.inner.actor, self.id_unchecked())?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( diff --git a/crates/apub_receive/src/activities_new/post/remove.rs b/crates/apub_receive/src/activities_new/post/remove.rs index a63cfc62f..5f738d5e8 100644 --- a/crates/apub_receive/src/activities_new/post/remove.rs +++ b/crates/apub_receive/src/activities_new/post/remove.rs @@ -1,8 +1,11 @@ -use crate::{activities_new::post::send_websocket_message, inbox::new_inbox_routing::Activity}; +use crate::{ + activities_new::{post::send_websocket_message, verify_mod_action}, + inbox::new_inbox_routing::Activity, +}; use activitystreams::activity::kind::RemoveType; use lemmy_api_common::blocking; -use lemmy_apub::fetcher::objects::get_or_fetch_and_insert_post; -use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; +use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_post}; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_db_queries::source::post::Post_; use lemmy_db_schema::source::post::Post; use lemmy_utils::LemmyError; @@ -15,10 +18,20 @@ pub struct RemovePost { actor: Url, to: PublicUrl, object: Url, + cc: Vec, #[serde(rename = "type")] kind: RemoveType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(&self.inner.actor, self.id_unchecked())?; + check_is_apub_id_valid(&self.inner.actor, false)?; + verify_mod_action(self.inner.actor.clone(), self.inner.cc.clone(), context).await + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( diff --git a/crates/apub_receive/src/activities_new/post/update.rs b/crates/apub_receive/src/activities_new/post/update.rs index d917609ed..20b0f8803 100644 --- a/crates/apub_receive/src/activities_new/post/update.rs +++ b/crates/apub_receive/src/activities_new/post/update.rs @@ -1,14 +1,15 @@ use crate::{activities_new::post::send_websocket_message, inbox::new_inbox_routing::Activity}; -use activitystreams::activity::kind::UpdateType; +use activitystreams::{activity::kind::UpdateType, base::BaseExt}; use anyhow::Context; use lemmy_api_common::blocking; use lemmy_apub::{ + check_is_apub_id_valid, fetcher::person::get_or_fetch_and_upsert_person, objects::{FromApub, FromApubToForm}, ActorType, PageExt, }; -use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; +use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity}; use lemmy_db_queries::{ApubObject, Crud}; use lemmy_db_schema::{ source::{ @@ -31,6 +32,15 @@ pub struct UpdatePost { kind: UpdateType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(self.id_unchecked(), &self.inner.actor)?; + self.inner.object.id(self.inner.actor.as_str())?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( diff --git a/crates/apub_receive/src/activities_new/private_message/create.rs b/crates/apub_receive/src/activities_new/private_message/create.rs index 66d64c437..3a87472e7 100644 --- a/crates/apub_receive/src/activities_new/private_message/create.rs +++ b/crates/apub_receive/src/activities_new/private_message/create.rs @@ -2,9 +2,9 @@ use crate::{ activities_new::private_message::send_websocket_message, inbox::new_inbox_routing::Activity, }; -use activitystreams::activity::kind::CreateType; -use lemmy_apub::{objects::FromApub, NoteExt}; -use lemmy_apub_lib::{verify_domains_match, ReceiveActivity}; +use activitystreams::{activity::kind::CreateType, base::BaseExt}; +use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, NoteExt}; +use lemmy_apub_lib::{verify_domains_match, ReceiveActivity, VerifyActivity}; use lemmy_db_schema::source::private_message::PrivateMessage; use lemmy_utils::LemmyError; use lemmy_websocket::{LemmyContext, UserOperationCrud}; @@ -20,6 +20,15 @@ pub struct CreatePrivateMessage { kind: CreateType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(self.id_unchecked(), &self.inner.actor)?; + self.inner.object.id(self.inner.actor.as_str())?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( @@ -27,8 +36,6 @@ impl ReceiveActivity for Activity { context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_domains_match(&self.inner.actor, self.id_unchecked())?; - let private_message = PrivateMessage::from_apub( &self.inner.object, context, diff --git a/crates/apub_receive/src/activities_new/private_message/delete.rs b/crates/apub_receive/src/activities_new/private_message/delete.rs index 21eaff0a8..1e8cc3523 100644 --- a/crates/apub_receive/src/activities_new/private_message/delete.rs +++ b/crates/apub_receive/src/activities_new/private_message/delete.rs @@ -4,7 +4,8 @@ use crate::{ }; use activitystreams::activity::kind::DeleteType; use lemmy_api_common::blocking; -use lemmy_apub_lib::{verify_domains_match, ReceiveActivity}; +use lemmy_apub::check_is_apub_id_valid; +use lemmy_apub_lib::{verify_domains_match, ReceiveActivity, VerifyActivity}; use lemmy_db_queries::{source::private_message::PrivateMessage_, ApubObject}; use lemmy_db_schema::source::private_message::PrivateMessage; use lemmy_utils::LemmyError; @@ -14,13 +15,22 @@ use url::Url; #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "camelCase")] pub struct DeletePrivateMessage { - pub(in crate::activities_new::private_message) actor: Url, + actor: Url, to: Url, pub(in crate::activities_new::private_message) object: Url, #[serde(rename = "type")] kind: DeleteType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(&self.inner.actor, self.id_unchecked())?; + verify_domains_match(&self.inner.actor, &self.inner.object)?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( @@ -28,9 +38,6 @@ impl ReceiveActivity for Activity { context: &LemmyContext, _request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_domains_match(&self.inner.actor, self.id_unchecked())?; - verify_domains_match(&self.inner.actor, &self.inner.object)?; - let ap_id = self.inner.object.clone(); let private_message = blocking(context.pool(), move |conn| { PrivateMessage::read_from_apub_id(conn, &ap_id.into()) diff --git a/crates/apub_receive/src/activities_new/private_message/undo_delete.rs b/crates/apub_receive/src/activities_new/private_message/undo_delete.rs index 1c1fdb8c2..3fde4914f 100644 --- a/crates/apub_receive/src/activities_new/private_message/undo_delete.rs +++ b/crates/apub_receive/src/activities_new/private_message/undo_delete.rs @@ -4,7 +4,8 @@ use crate::{ }; use activitystreams::activity::kind::UndoType; use lemmy_api_common::blocking; -use lemmy_apub_lib::{verify_domains_match, ReceiveActivity}; +use lemmy_apub::check_is_apub_id_valid; +use lemmy_apub_lib::{verify_domains_match, ReceiveActivity, VerifyActivity}; use lemmy_db_queries::{source::private_message::PrivateMessage_, ApubObject}; use lemmy_db_schema::source::private_message::PrivateMessage; use lemmy_utils::LemmyError; @@ -21,6 +22,16 @@ pub struct UndoDeletePrivateMessage { kind: UndoType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(&self.inner.actor, self.id_unchecked())?; + verify_domains_match(&self.inner.actor, &self.inner.object.id_unchecked())?; + check_is_apub_id_valid(&self.inner.actor, false)?; + self.inner.object.verify(context).await + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( @@ -28,10 +39,6 @@ impl ReceiveActivity for Activity { context: &LemmyContext, _request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_domains_match(&self.inner.actor, self.id_unchecked())?; - verify_domains_match(&self.inner.actor, &self.inner.object.id_unchecked())?; - verify_domains_match(&self.inner.actor, &self.inner.object.inner.actor)?; - let ap_id = self.inner.object.inner.object.clone(); let private_message = blocking(context.pool(), move |conn| { PrivateMessage::read_from_apub_id(conn, &ap_id.into()) diff --git a/crates/apub_receive/src/activities_new/private_message/update.rs b/crates/apub_receive/src/activities_new/private_message/update.rs index 2ec1853d6..e28e1d81d 100644 --- a/crates/apub_receive/src/activities_new/private_message/update.rs +++ b/crates/apub_receive/src/activities_new/private_message/update.rs @@ -2,9 +2,9 @@ use crate::{ activities_new::private_message::send_websocket_message, inbox::new_inbox_routing::Activity, }; -use activitystreams::activity::kind::UpdateType; -use lemmy_apub::{objects::FromApub, NoteExt}; -use lemmy_apub_lib::{verify_domains_match, ReceiveActivity}; +use activitystreams::{activity::kind::UpdateType, base::BaseExt}; +use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, NoteExt}; +use lemmy_apub_lib::{verify_domains_match, ReceiveActivity, VerifyActivity}; use lemmy_db_schema::source::private_message::PrivateMessage; use lemmy_utils::LemmyError; use lemmy_websocket::{LemmyContext, UserOperationCrud}; @@ -20,6 +20,15 @@ pub struct UpdatePrivateMessage { kind: UpdateType, } +#[async_trait::async_trait(?Send)] +impl VerifyActivity for Activity { + async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> { + verify_domains_match(self.id_unchecked(), &self.inner.actor)?; + self.inner.object.id(self.inner.actor.as_str())?; + check_is_apub_id_valid(&self.inner.actor, false) + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for Activity { async fn receive( @@ -27,8 +36,6 @@ impl ReceiveActivity for Activity { context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> { - verify_domains_match(&self.inner.actor, self.id_unchecked())?; - let private_message = PrivateMessage::from_apub( &self.inner.object, context, diff --git a/crates/apub_receive/src/inbox/new_inbox_routing.rs b/crates/apub_receive/src/inbox/new_inbox_routing.rs index 71afad41f..c70af9d95 100644 --- a/crates/apub_receive/src/inbox/new_inbox_routing.rs +++ b/crates/apub_receive/src/inbox/new_inbox_routing.rs @@ -24,7 +24,7 @@ use crate::activities_new::{ }, }; use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed}; -use lemmy_apub_lib::ReceiveActivity; +use lemmy_apub_lib::{ReceiveActivity, VerifyActivity}; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use url::Url; @@ -77,7 +77,14 @@ pub enum PersonAcceptedActivitiesNew { RemovePost(RemovePost), } -// todo: can probably get rid of this? +// todo: can probably get rid of these? +#[async_trait::async_trait(?Send)] +impl VerifyActivity for PersonAcceptedActivitiesNew { + async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> { + self.verify(context).await + } +} + #[async_trait::async_trait(?Send)] impl ReceiveActivity for PersonAcceptedActivitiesNew { async fn receive( diff --git a/crates/apub_receive/src/inbox/person_inbox.rs b/crates/apub_receive/src/inbox/person_inbox.rs index 4bf36e486..3ed365dec 100644 --- a/crates/apub_receive/src/inbox/person_inbox.rs +++ b/crates/apub_receive/src/inbox/person_inbox.rs @@ -35,7 +35,7 @@ use anyhow::{anyhow, Context}; use diesel::NotFound; use lemmy_api_common::blocking; use lemmy_apub::{check_is_apub_id_valid, get_activity_to_and_cc, ActorType}; -use lemmy_apub_lib::ReceiveActivity; +use lemmy_apub_lib::{ReceiveActivity, VerifyActivity}; use lemmy_db_queries::{ApubObject, Followable}; use lemmy_db_schema::source::{ community::{Community, CommunityFollower}, @@ -73,6 +73,7 @@ pub async fn person_inbox( context: web::Data, ) -> Result { let activity = input.into_inner(); + activity.inner.verify(&context).await?; let request_counter = &mut 0; activity.inner.receive(&context, request_counter).await?; todo!()