add verify trait

This commit is contained in:
Felix Ableitner 2021-06-25 17:32:59 +02:00
parent 6abfa92a60
commit fb0932e0e6
23 changed files with 276 additions and 112 deletions

View file

@ -31,13 +31,6 @@ pub enum PublicUrl {
Public, 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: later add a similar trait SendActivity
// todo: maybe add a separate method verify() // todo: maybe add a separate method verify()
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
@ -50,6 +43,19 @@ pub trait ReceiveActivity {
) -> Result<(), LemmyError>; ) -> 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<kind> to cache the fetched object (or just fetch on construction) // todo: instead of phantomdata, might use option<kind> to cache the fetched object (or just fetch on construction)
pub struct ObjectId<'a, Kind>(Url, &'a PhantomData<Kind>); pub struct ObjectId<'a, Kind>(Url, &'a PhantomData<Kind>);

View file

@ -15,7 +15,6 @@ use url::Url;
pub(crate) mod comment_undo; pub(crate) mod comment_undo;
pub(crate) mod community; pub(crate) mod community;
pub(crate) mod post_undo; pub(crate) mod post_undo;
pub(crate) mod private_message;
/// Return HTTP 501 for unsupported activities in inbox. /// Return HTTP 501 for unsupported activities in inbox.
pub(crate) fn receive_unhandled_activity<A>(activity: A) -> Result<(), LemmyError> pub(crate) fn receive_unhandled_activity<A>(activity: A) -> Result<(), LemmyError>

View file

@ -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<T, Kind>(
activity: &T,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError>
where
T: AsBase<Kind> + AsObject<Kind> + 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(())
}

View file

@ -3,11 +3,10 @@ use crate::{
inbox::new_inbox_routing::Activity, inbox::new_inbox_routing::Activity,
}; };
use activitystreams::{activity::kind::CreateType, base::BaseExt}; use activitystreams::{activity::kind::CreateType, base::BaseExt};
use anyhow::Context; use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, NoteExt};
use lemmy_apub::{objects::FromApub, NoteExt}; use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity};
use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity};
use lemmy_db_schema::source::comment::Comment; use lemmy_db_schema::source::comment::Comment;
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud}; use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url; use url::Url;
@ -21,6 +20,15 @@ pub struct CreateComment {
kind: CreateType, kind: CreateType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<CreateComment> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<CreateComment> { impl ReceiveActivity for Activity<CreateComment> {
async fn receive( async fn receive(
@ -28,12 +36,6 @@ impl ReceiveActivity for Activity<CreateComment> {
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> 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( let comment = Comment::from_apub(
&self.inner.object, &self.inner.object,
context, context,

View file

@ -1,8 +1,8 @@
use crate::{activities_new::comment::send_websocket_message, inbox::new_inbox_routing::Activity}; use crate::{activities_new::comment::send_websocket_message, inbox::new_inbox_routing::Activity};
use activitystreams::activity::kind::DeleteType; use activitystreams::activity::kind::DeleteType;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::fetcher::objects::get_or_fetch_and_insert_comment; use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_comment};
use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity};
use lemmy_db_queries::source::comment::Comment_; use lemmy_db_queries::source::comment::Comment_;
use lemmy_db_schema::source::comment::Comment; use lemmy_db_schema::source::comment::Comment;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
@ -20,6 +20,15 @@ pub struct DeleteComment {
kind: DeleteType, kind: DeleteType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<DeleteComment> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<DeleteComment> { impl ReceiveActivity for Activity<DeleteComment> {
async fn receive( async fn receive(

View file

@ -1,6 +1,7 @@
use crate::{activities_new::comment::like_or_dislike_comment, inbox::new_inbox_routing::Activity}; use crate::{activities_new::comment::like_or_dislike_comment, inbox::new_inbox_routing::Activity};
use activitystreams::activity::kind::DislikeType; 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_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use url::Url; use url::Url;
@ -16,6 +17,14 @@ pub struct DislikeComment {
kind: DislikeType, kind: DislikeType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<DislikeComment> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<DislikeComment> { impl ReceiveActivity for Activity<DislikeComment> {
async fn receive( async fn receive(

View file

@ -1,6 +1,7 @@
use crate::{activities_new::comment::like_or_dislike_comment, inbox::new_inbox_routing::Activity}; use crate::{activities_new::comment::like_or_dislike_comment, inbox::new_inbox_routing::Activity};
use activitystreams::activity::kind::LikeType; 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_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use url::Url; use url::Url;
@ -16,6 +17,14 @@ pub struct LikeComment {
kind: LikeType, kind: LikeType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<LikeComment> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<LikeComment> { impl ReceiveActivity for Activity<LikeComment> {
async fn receive( async fn receive(

View file

@ -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 activitystreams::activity::kind::RemoveType;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::fetcher::objects::get_or_fetch_and_insert_comment; use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_comment};
use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity};
use lemmy_db_queries::source::comment::Comment_; use lemmy_db_queries::source::comment::Comment_;
use lemmy_db_schema::source::comment::Comment; use lemmy_db_schema::source::comment::Comment;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
@ -20,6 +23,15 @@ pub struct RemoveComment {
kind: RemoveType, kind: RemoveType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<RemoveComment> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<RemoveComment> { impl ReceiveActivity for Activity<RemoveComment> {
async fn receive( async fn receive(

View file

@ -3,11 +3,10 @@ use crate::{
inbox::new_inbox_routing::Activity, inbox::new_inbox_routing::Activity,
}; };
use activitystreams::{activity::kind::UpdateType, base::BaseExt}; use activitystreams::{activity::kind::UpdateType, base::BaseExt};
use anyhow::Context; use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, NoteExt};
use lemmy_apub::{objects::FromApub, NoteExt}; use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity};
use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity};
use lemmy_db_schema::source::comment::Comment; use lemmy_db_schema::source::comment::Comment;
use lemmy_utils::{location_info, LemmyError}; use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud}; use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url; use url::Url;
@ -21,6 +20,15 @@ pub struct UpdateComment {
kind: UpdateType, kind: UpdateType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UpdateComment> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<UpdateComment> { impl ReceiveActivity for Activity<UpdateComment> {
async fn receive( async fn receive(
@ -28,12 +36,6 @@ impl ReceiveActivity for Activity<UpdateComment> {
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> 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( let comment = Comment::from_apub(
&self.inner.object, &self.inner.object,
context, context,

View file

@ -5,7 +5,7 @@ use lemmy_apub::fetcher::{
community::get_or_fetch_and_upsert_community, community::get_or_fetch_and_upsert_community,
person::get_or_fetch_and_upsert_person, 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_queries::Followable;
use lemmy_db_schema::source::community::CommunityFollower; use lemmy_db_schema::source::community::CommunityFollower;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
@ -22,6 +22,13 @@ pub struct FollowCommunity {
kind: FollowType, kind: FollowType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<FollowCommunity> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
todo!()
}
}
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<FollowCommunity> { impl ReceiveActivity for Activity<FollowCommunity> {
async fn receive( async fn receive(
@ -44,6 +51,14 @@ pub struct AcceptFollowCommunity {
kind: AcceptType, kind: AcceptType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<AcceptFollowCommunity> {
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 /// Handle accepted follows
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<AcceptFollowCommunity> { impl ReceiveActivity for Activity<AcceptFollowCommunity> {
@ -52,11 +67,6 @@ impl ReceiveActivity for Activity<AcceptFollowCommunity> {
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> 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 = let community =
get_or_fetch_and_upsert_community(&self.inner.actor, context, request_counter).await?; 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?; let person = get_or_fetch_and_upsert_person(&self.inner.to, context, request_counter).await?;

View file

@ -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 comment;
pub mod follow; pub mod follow;
pub mod post; pub mod post;
pub mod private_message; pub mod private_message;
async fn verify_mod_action(
actor_id: Url,
activity_cc: Vec<Url>,
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, &current.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(())
}

View file

@ -1,12 +1,13 @@
use crate::{activities_new::post::send_websocket_message, inbox::new_inbox_routing::Activity}; 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::{ use lemmy_apub::{
check_is_apub_id_valid,
fetcher::person::get_or_fetch_and_upsert_person, fetcher::person::get_or_fetch_and_upsert_person,
objects::FromApub, objects::FromApub,
ActorType, ActorType,
PageExt, 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_db_schema::source::post::Post;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud}; use lemmy_websocket::{LemmyContext, UserOperationCrud};
@ -22,6 +23,15 @@ pub struct CreatePost {
kind: CreateType, kind: CreateType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<CreatePost> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<CreatePost> { impl ReceiveActivity for Activity<CreatePost> {
async fn receive( async fn receive(

View file

@ -1,8 +1,8 @@
use crate::{activities_new::post::send_websocket_message, inbox::new_inbox_routing::Activity}; use crate::{activities_new::post::send_websocket_message, inbox::new_inbox_routing::Activity};
use activitystreams::activity::kind::DeleteType; use activitystreams::activity::kind::DeleteType;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::fetcher::objects::get_or_fetch_and_insert_post; use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_post};
use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity};
use lemmy_db_queries::source::post::Post_; use lemmy_db_queries::source::post::Post_;
use lemmy_db_schema::source::post::Post; use lemmy_db_schema::source::post::Post;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
@ -19,6 +19,15 @@ pub struct DeletePost {
kind: DeleteType, kind: DeleteType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<DeletePost> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<DeletePost> { impl ReceiveActivity for Activity<DeletePost> {
async fn receive( async fn receive(

View file

@ -1,6 +1,7 @@
use crate::{activities_new::post::like_or_dislike_post, inbox::new_inbox_routing::Activity}; use crate::{activities_new::post::like_or_dislike_post, inbox::new_inbox_routing::Activity};
use activitystreams::activity::kind::DislikeType; 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_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use url::Url; use url::Url;
@ -15,6 +16,14 @@ pub struct DislikePost {
kind: DislikeType, kind: DislikeType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<DislikePost> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<DislikePost> { impl ReceiveActivity for Activity<DislikePost> {
async fn receive( async fn receive(

View file

@ -1,6 +1,7 @@
use crate::{activities_new::post::like_or_dislike_post, inbox::new_inbox_routing::Activity}; use crate::{activities_new::post::like_or_dislike_post, inbox::new_inbox_routing::Activity};
use activitystreams::activity::kind::LikeType; 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_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use url::Url; use url::Url;
@ -15,6 +16,14 @@ pub struct LikePost {
kind: LikeType, kind: LikeType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<LikePost> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<LikePost> { impl ReceiveActivity for Activity<LikePost> {
async fn receive( async fn receive(

View file

@ -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 activitystreams::activity::kind::RemoveType;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::fetcher::objects::get_or_fetch_and_insert_post; use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_post};
use lemmy_apub_lib::{PublicUrl, ReceiveActivity}; use lemmy_apub_lib::{verify_domains_match, PublicUrl, ReceiveActivity, VerifyActivity};
use lemmy_db_queries::source::post::Post_; use lemmy_db_queries::source::post::Post_;
use lemmy_db_schema::source::post::Post; use lemmy_db_schema::source::post::Post;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
@ -15,10 +18,20 @@ pub struct RemovePost {
actor: Url, actor: Url,
to: PublicUrl, to: PublicUrl,
object: Url, object: Url,
cc: Vec<Url>,
#[serde(rename = "type")] #[serde(rename = "type")]
kind: RemoveType, kind: RemoveType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<RemovePost> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<RemovePost> { impl ReceiveActivity for Activity<RemovePost> {
async fn receive( async fn receive(

View file

@ -1,14 +1,15 @@
use crate::{activities_new::post::send_websocket_message, inbox::new_inbox_routing::Activity}; 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 anyhow::Context;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::{ use lemmy_apub::{
check_is_apub_id_valid,
fetcher::person::get_or_fetch_and_upsert_person, fetcher::person::get_or_fetch_and_upsert_person,
objects::{FromApub, FromApubToForm}, objects::{FromApub, FromApubToForm},
ActorType, ActorType,
PageExt, 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_queries::{ApubObject, Crud};
use lemmy_db_schema::{ use lemmy_db_schema::{
source::{ source::{
@ -31,6 +32,15 @@ pub struct UpdatePost {
kind: UpdateType, kind: UpdateType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UpdatePost> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<UpdatePost> { impl ReceiveActivity for Activity<UpdatePost> {
async fn receive( async fn receive(

View file

@ -2,9 +2,9 @@ use crate::{
activities_new::private_message::send_websocket_message, activities_new::private_message::send_websocket_message,
inbox::new_inbox_routing::Activity, inbox::new_inbox_routing::Activity,
}; };
use activitystreams::activity::kind::CreateType; use activitystreams::{activity::kind::CreateType, base::BaseExt};
use lemmy_apub::{objects::FromApub, NoteExt}; use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, NoteExt};
use lemmy_apub_lib::{verify_domains_match, ReceiveActivity}; use lemmy_apub_lib::{verify_domains_match, ReceiveActivity, VerifyActivity};
use lemmy_db_schema::source::private_message::PrivateMessage; use lemmy_db_schema::source::private_message::PrivateMessage;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud}; use lemmy_websocket::{LemmyContext, UserOperationCrud};
@ -20,6 +20,15 @@ pub struct CreatePrivateMessage {
kind: CreateType, kind: CreateType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<CreatePrivateMessage> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<CreatePrivateMessage> { impl ReceiveActivity for Activity<CreatePrivateMessage> {
async fn receive( async fn receive(
@ -27,8 +36,6 @@ impl ReceiveActivity for Activity<CreatePrivateMessage> {
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
let private_message = PrivateMessage::from_apub( let private_message = PrivateMessage::from_apub(
&self.inner.object, &self.inner.object,
context, context,

View file

@ -4,7 +4,8 @@ use crate::{
}; };
use activitystreams::activity::kind::DeleteType; use activitystreams::activity::kind::DeleteType;
use lemmy_api_common::blocking; 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_queries::{source::private_message::PrivateMessage_, ApubObject};
use lemmy_db_schema::source::private_message::PrivateMessage; use lemmy_db_schema::source::private_message::PrivateMessage;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
@ -14,13 +15,22 @@ use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct DeletePrivateMessage { pub struct DeletePrivateMessage {
pub(in crate::activities_new::private_message) actor: Url, actor: Url,
to: Url, to: Url,
pub(in crate::activities_new::private_message) object: Url, pub(in crate::activities_new::private_message) object: Url,
#[serde(rename = "type")] #[serde(rename = "type")]
kind: DeleteType, kind: DeleteType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<DeletePrivateMessage> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<DeletePrivateMessage> { impl ReceiveActivity for Activity<DeletePrivateMessage> {
async fn receive( async fn receive(
@ -28,9 +38,6 @@ impl ReceiveActivity for Activity<DeletePrivateMessage> {
context: &LemmyContext, context: &LemmyContext,
_request_counter: &mut i32, _request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> 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 ap_id = self.inner.object.clone();
let private_message = blocking(context.pool(), move |conn| { let private_message = blocking(context.pool(), move |conn| {
PrivateMessage::read_from_apub_id(conn, &ap_id.into()) PrivateMessage::read_from_apub_id(conn, &ap_id.into())

View file

@ -4,7 +4,8 @@ use crate::{
}; };
use activitystreams::activity::kind::UndoType; use activitystreams::activity::kind::UndoType;
use lemmy_api_common::blocking; 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_queries::{source::private_message::PrivateMessage_, ApubObject};
use lemmy_db_schema::source::private_message::PrivateMessage; use lemmy_db_schema::source::private_message::PrivateMessage;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
@ -21,6 +22,16 @@ pub struct UndoDeletePrivateMessage {
kind: UndoType, kind: UndoType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoDeletePrivateMessage> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<UndoDeletePrivateMessage> { impl ReceiveActivity for Activity<UndoDeletePrivateMessage> {
async fn receive( async fn receive(
@ -28,10 +39,6 @@ impl ReceiveActivity for Activity<UndoDeletePrivateMessage> {
context: &LemmyContext, context: &LemmyContext,
_request_counter: &mut i32, _request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> 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 ap_id = self.inner.object.inner.object.clone();
let private_message = blocking(context.pool(), move |conn| { let private_message = blocking(context.pool(), move |conn| {
PrivateMessage::read_from_apub_id(conn, &ap_id.into()) PrivateMessage::read_from_apub_id(conn, &ap_id.into())

View file

@ -2,9 +2,9 @@ use crate::{
activities_new::private_message::send_websocket_message, activities_new::private_message::send_websocket_message,
inbox::new_inbox_routing::Activity, inbox::new_inbox_routing::Activity,
}; };
use activitystreams::activity::kind::UpdateType; use activitystreams::{activity::kind::UpdateType, base::BaseExt};
use lemmy_apub::{objects::FromApub, NoteExt}; use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, NoteExt};
use lemmy_apub_lib::{verify_domains_match, ReceiveActivity}; use lemmy_apub_lib::{verify_domains_match, ReceiveActivity, VerifyActivity};
use lemmy_db_schema::source::private_message::PrivateMessage; use lemmy_db_schema::source::private_message::PrivateMessage;
use lemmy_utils::LemmyError; use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud}; use lemmy_websocket::{LemmyContext, UserOperationCrud};
@ -20,6 +20,15 @@ pub struct UpdatePrivateMessage {
kind: UpdateType, kind: UpdateType,
} }
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UpdatePrivateMessage> {
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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<UpdatePrivateMessage> { impl ReceiveActivity for Activity<UpdatePrivateMessage> {
async fn receive( async fn receive(
@ -27,8 +36,6 @@ impl ReceiveActivity for Activity<UpdatePrivateMessage> {
context: &LemmyContext, context: &LemmyContext,
request_counter: &mut i32, request_counter: &mut i32,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
let private_message = PrivateMessage::from_apub( let private_message = PrivateMessage::from_apub(
&self.inner.object, &self.inner.object,
context, context,

View file

@ -24,7 +24,7 @@ use crate::activities_new::{
}, },
}; };
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed}; 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_utils::LemmyError;
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
use url::Url; use url::Url;
@ -77,7 +77,14 @@ pub enum PersonAcceptedActivitiesNew {
RemovePost(RemovePost), 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)] #[async_trait::async_trait(?Send)]
impl ReceiveActivity for PersonAcceptedActivitiesNew { impl ReceiveActivity for PersonAcceptedActivitiesNew {
async fn receive( async fn receive(

View file

@ -35,7 +35,7 @@ use anyhow::{anyhow, Context};
use diesel::NotFound; use diesel::NotFound;
use lemmy_api_common::blocking; use lemmy_api_common::blocking;
use lemmy_apub::{check_is_apub_id_valid, get_activity_to_and_cc, ActorType}; 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_queries::{ApubObject, Followable};
use lemmy_db_schema::source::{ use lemmy_db_schema::source::{
community::{Community, CommunityFollower}, community::{Community, CommunityFollower},
@ -73,6 +73,7 @@ pub async fn person_inbox(
context: web::Data<LemmyContext>, context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let activity = input.into_inner(); let activity = input.into_inner();
activity.inner.verify(&context).await?;
let request_counter = &mut 0; let request_counter = &mut 0;
activity.inner.receive(&context, request_counter).await?; activity.inner.receive(&context, request_counter).await?;
todo!() todo!()