cleanup and restructure apub_receive code

This commit is contained in:
Felix Ableitner 2021-07-01 00:43:26 +02:00
parent fa7778218f
commit 51bb80a966
55 changed files with 465 additions and 394 deletions

7
Cargo.lock generated
View file

@ -1876,6 +1876,7 @@ dependencies = [
"strum_macros 0.20.1",
"thiserror",
"tokio 0.3.7",
"trait_enum",
"url",
"uuid",
]
@ -3689,6 +3690,12 @@ dependencies = [
"tracing",
]
[[package]]
name = "trait_enum"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "130dd741d3c71f76d031e58caffff3624eaaa2db9bd8c4b05406a71885300fc7"
[[package]]
name = "trust-dns-proto"
version = "0.19.6"

View file

@ -50,3 +50,4 @@ thiserror = "1.0.23"
background-jobs = "0.8.0"
reqwest = { version = "0.10.10", features = ["json"] }
backtrace = "0.3.56"
trait_enum = "0.5.0"

View file

@ -49,7 +49,6 @@ use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
use lemmy_websocket::LemmyContext;
use url::Url;
#[async_trait::async_trait(?Send)]
impl ActorType for Community {
fn is_local(&self) -> bool {
self.local
@ -57,6 +56,9 @@ impl ActorType for Community {
fn actor_id(&self) -> Url {
self.actor_id.to_owned().into_inner()
}
fn name(&self) -> String {
self.name.clone()
}
fn public_key(&self) -> Option<String> {
self.public_key.to_owned()
}

View file

@ -24,7 +24,6 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[async_trait::async_trait(?Send)]
impl ActorType for Person {
fn is_local(&self) -> bool {
self.local
@ -32,6 +31,9 @@ impl ActorType for Person {
fn actor_id(&self) -> Url {
self.actor_id.to_owned().into_inner()
}
fn name(&self) -> String {
self.name.clone()
}
fn public_key(&self) -> Option<String> {
self.public_key.to_owned()

View file

@ -40,34 +40,40 @@ where
false
}
/// Get a remote actor from its apub ID (either a person or a community). Thin wrapper around
/// `get_or_fetch_and_upsert_person()` and `get_or_fetch_and_upsert_community()`.
///
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
/// Otherwise it is fetched from the remote instance, stored and returned.
trait_enum! {
pub enum Actor: ActorType {
Person,
Community,
}
}
/*
impl ActorType for Actor {
fn is_local(&self) -> bool {
self.
self.is_local()
}
fn actor_id(&self) -> Url {
self.actor_id()
}
fn name(&self) -> String {
self.name()
}
fn public_key(&self) -> Option<String> {
self.public_key()
}
fn private_key(&self) -> Option<String> {
self.private_key()
}
fn get_shared_inbox_or_inbox_url(&self) -> Url {
self.get_shared_inbox_or_inbox_url()
}
}
*/
pub async fn get_or_fetch_and_upsert_actor(
apub_id: &Url,
context: &LemmyContext,
recursion_counter: &mut i32,
) -> Result<Box<dyn ActorType>, LemmyError> {
let community = get_or_fetch_and_upsert_community(apub_id, context, recursion_counter).await;
let actor: Box<dyn ActorType> = match community {
Ok(c) => Box::new(c),
Err(_) => Box::new(get_or_fetch_and_upsert_person(apub_id, context, recursion_counter).await?),
};
Ok(actor)
}
pub enum Actor {
Person(Person),
Community(Community),
}
// TODO: use this and get rid of ActorType
pub async fn get_or_fetch_and_upsert_actor2(
apub_id: &Url,
context: &LemmyContext,
recursion_counter: &mut i32,
) -> Result<Actor, LemmyError> {
let community = get_or_fetch_and_upsert_community(apub_id, context, recursion_counter).await;
let actor: Actor = match community {

View file

@ -1,5 +1,7 @@
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate trait_enum;
pub mod activities;
pub mod activity_queue;
@ -171,10 +173,10 @@ pub trait ApubLikeableType {
/// Common methods provided by ActivityPub actors (community and person). Not all methods are
/// implemented by all actors.
#[async_trait::async_trait(?Send)]
pub trait ActorType {
fn is_local(&self) -> bool;
fn actor_id(&self) -> Url;
fn name(&self) -> String;
// TODO: every actor should have a public key, so this shouldnt be an option (needs to be fixed in db)
fn public_key(&self) -> Option<String>;

View file

@ -1,6 +1,6 @@
use crate::{
activities::comment::{get_notif_recipients, send_websocket_message},
inbox::new_inbox_routing::Activity,
use crate::activities::{
comment::{get_notif_recipients, send_websocket_message},
LemmyActivity,
};
use activitystreams::{activity::kind::CreateType, base::BaseExt};
use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, ActorType, NoteExt};
@ -21,7 +21,7 @@ pub struct CreateComment {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<CreateComment> {
impl ActivityHandler for LemmyActivity<CreateComment> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::{activities::comment::send_websocket_message, inbox::new_inbox_routing::Activity};
use crate::activities::{comment::send_websocket_message, LemmyActivity};
use activitystreams::activity::kind::DeleteType;
use lemmy_api_common::blocking;
use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_comment};
@ -20,7 +20,7 @@ pub struct DeleteComment {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<DeleteComment> {
impl ActivityHandler for LemmyActivity<DeleteComment> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::{activities::comment::like_or_dislike_comment, inbox::new_inbox_routing::Activity};
use crate::activities::{comment::like_or_dislike_comment, LemmyActivity};
use activitystreams::activity::kind::DislikeType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityHandler, PublicUrl};
@ -18,7 +18,7 @@ pub struct DislikeComment {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<DislikeComment> {
impl ActivityHandler for LemmyActivity<DislikeComment> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::{activities::comment::like_or_dislike_comment, inbox::new_inbox_routing::Activity};
use crate::activities::{comment::like_or_dislike_comment, LemmyActivity};
use activitystreams::activity::kind::LikeType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityHandler, PublicUrl};
@ -18,7 +18,7 @@ pub struct LikeComment {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<LikeComment> {
impl ActivityHandler for LemmyActivity<LikeComment> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,7 +1,4 @@
use crate::{
activities::{comment::send_websocket_message, verify_mod_action},
inbox::new_inbox_routing::Activity,
};
use crate::activities::{comment::send_websocket_message, verify_mod_action, LemmyActivity};
use activitystreams::activity::kind::RemoveType;
use lemmy_api_common::blocking;
use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_comment};
@ -23,7 +20,7 @@ pub struct RemoveComment {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<RemoveComment> {
impl ActivityHandler for LemmyActivity<RemoveComment> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,6 @@
use crate::{
activities::comment::{delete::DeleteComment, send_websocket_message},
inbox::new_inbox_routing::Activity,
use crate::activities::{
comment::{delete::DeleteComment, send_websocket_message},
LemmyActivity,
};
use activitystreams::activity::kind::UndoType;
use lemmy_api_common::blocking;
@ -16,14 +16,14 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoDeleteComment {
to: PublicUrl,
object: Activity<DeleteComment>,
object: LemmyActivity<DeleteComment>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoDeleteComment> {
impl ActivityHandler for LemmyActivity<UndoDeleteComment> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,6 @@
use crate::{
activities::comment::{dislike::DislikeComment, undo_like_or_dislike_comment},
inbox::new_inbox_routing::Activity,
use crate::activities::{
comment::{dislike::DislikeComment, undo_like_or_dislike_comment},
LemmyActivity,
};
use activitystreams::activity::kind::UndoType;
use lemmy_apub::check_is_apub_id_valid;
@ -14,14 +14,14 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoDislikeComment {
to: PublicUrl,
object: Activity<DislikeComment>,
object: LemmyActivity<DislikeComment>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoDislikeComment> {
impl ActivityHandler for LemmyActivity<UndoDislikeComment> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,6 @@
use crate::{
activities::comment::{like::LikeComment, undo_like_or_dislike_comment},
inbox::new_inbox_routing::Activity,
use crate::activities::{
comment::{like::LikeComment, undo_like_or_dislike_comment},
LemmyActivity,
};
use activitystreams::activity::kind::UndoType;
use lemmy_apub::check_is_apub_id_valid;
@ -14,14 +14,14 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoLikeComment {
to: PublicUrl,
object: Activity<LikeComment>,
object: LemmyActivity<LikeComment>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoLikeComment> {
impl ActivityHandler for LemmyActivity<UndoLikeComment> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,9 +1,7 @@
use crate::{
activities::{
use crate::activities::{
comment::{remove::RemoveComment, send_websocket_message},
verify_mod_action,
},
inbox::new_inbox_routing::Activity,
LemmyActivity,
};
use activitystreams::activity::kind::UndoType;
use lemmy_api_common::blocking;
@ -19,14 +17,14 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoRemoveComment {
to: PublicUrl,
object: Activity<RemoveComment>,
object: LemmyActivity<RemoveComment>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoRemoveComment> {
impl ActivityHandler for LemmyActivity<UndoRemoveComment> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,6 @@
use crate::{
activities::comment::{get_notif_recipients, send_websocket_message},
inbox::new_inbox_routing::Activity,
use crate::activities::{
comment::{get_notif_recipients, send_websocket_message},
LemmyActivity,
};
use activitystreams::{activity::kind::UpdateType, base::BaseExt};
use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, ActorType, NoteExt};
@ -21,7 +21,7 @@ pub struct UpdateComment {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UpdateComment> {
impl ActivityHandler for LemmyActivity<UpdateComment> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,7 @@
use crate::{
activities::{community::verify_add_remove_moderator_target, verify_mod_action},
inbox::new_inbox_routing::Activity,
use crate::activities::{
community::verify_add_remove_moderator_target,
verify_mod_action,
LemmyActivity,
};
use activitystreams::{activity::kind::AddType, base::AnyBase};
use lemmy_api_common::blocking;
@ -31,7 +32,7 @@ pub struct AddMod {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<AddMod> {
impl ActivityHandler for LemmyActivity<AddMod> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -12,15 +12,7 @@ use crate::{
undo_remove::UndoRemoveComment,
update::UpdateComment,
},
community::{
block_user::BlockUserFromCommunity,
delete::DeleteCommunity,
remove::RemoveCommunity,
undo_block_user::UndoBlockUserFromCommunity,
undo_delete::UndoDeleteCommunity,
undo_remove::UndoRemoveCommunity,
update::UpdateCommunity,
},
community::{block_user::BlockUserFromCommunity, undo_block_user::UndoBlockUserFromCommunity},
post::{
create::CreatePost,
delete::DeletePost,
@ -33,8 +25,9 @@ use crate::{
undo_remove::UndoRemovePost,
update::UpdatePost,
},
LemmyActivity,
},
inbox::{is_activity_already_known, new_inbox_routing::Activity},
http::is_activity_already_known,
};
use activitystreams::activity::kind::RemoveType;
use lemmy_apub::{check_is_apub_id_valid, fetcher::person::get_or_fetch_and_upsert_person};
@ -66,12 +59,6 @@ pub enum AnnouncableActivities {
UndoRemovePost(UndoRemovePost),
UndoLikePost(UndoLikePost),
UndoDislikePost(UndoDislikePost),
// TODO: which of these get announced?
UpdateCommunity(UpdateCommunity),
DeleteCommunity(DeleteCommunity),
RemoveCommunity(RemoveCommunity),
UndoDeleteCommunity(UndoDeleteCommunity),
UndoRemoveCommunity(UndoRemoveCommunity),
BlockUserFromCommunity(BlockUserFromCommunity),
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
}
@ -98,14 +85,14 @@ impl ActivityHandler for AnnouncableActivities {
#[serde(rename_all = "camelCase")]
pub struct AnnounceActivity {
to: PublicUrl,
object: Activity<AnnouncableActivities>,
object: LemmyActivity<AnnouncableActivities>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: RemoveType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<AnnounceActivity> {
impl ActivityHandler for LemmyActivity<AnnounceActivity> {
type Actor = Community;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::{activities::verify_mod_action, inbox::new_inbox_routing::Activity};
use crate::activities::{verify_mod_action, LemmyActivity};
use activitystreams::activity::kind::BlockType;
use lemmy_api_common::blocking;
use lemmy_apub::{
@ -31,7 +31,7 @@ pub struct BlockUserFromCommunity {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<BlockUserFromCommunity> {
impl ActivityHandler for LemmyActivity<BlockUserFromCommunity> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,6 @@
use crate::{
activities::community::{send_websocket_message, verify_is_community_mod},
inbox::new_inbox_routing::Activity,
use crate::activities::{
community::{send_websocket_message, verify_is_community_mod},
LemmyActivity,
};
use activitystreams::activity::kind::DeleteType;
use lemmy_api_common::blocking;
@ -31,7 +31,7 @@ pub struct DeleteCommunity {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<DeleteCommunity> {
impl ActivityHandler for LemmyActivity<DeleteCommunity> {
type Actor = lemmy_apub::fetcher::Actor;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::{activities::community::send_websocket_message, inbox::new_inbox_routing::Activity};
use crate::activities::{community::send_websocket_message, LemmyActivity};
use activitystreams::activity::kind::RemoveType;
use lemmy_api_common::blocking;
use lemmy_apub::check_is_apub_id_valid;
@ -20,7 +20,7 @@ pub struct RemoveCommunity {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<RemoveCommunity> {
impl ActivityHandler for LemmyActivity<RemoveCommunity> {
type Actor = lemmy_apub::fetcher::Actor;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,7 @@
use crate::{
activities::{community::verify_add_remove_moderator_target, verify_mod_action},
inbox::new_inbox_routing::Activity,
use crate::activities::{
community::verify_add_remove_moderator_target,
verify_mod_action,
LemmyActivity,
};
use activitystreams::{activity::kind::RemoveType, base::AnyBase};
use lemmy_api_common::blocking;
@ -31,7 +32,7 @@ pub struct RemoveMod {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<RemoveMod> {
impl ActivityHandler for LemmyActivity<RemoveMod> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,7 @@
use crate::{
activities::{community::block_user::BlockUserFromCommunity, verify_mod_action},
inbox::new_inbox_routing::Activity,
use crate::activities::{
community::block_user::BlockUserFromCommunity,
verify_mod_action,
LemmyActivity,
};
use activitystreams::activity::kind::BlockType;
use lemmy_api_common::blocking;
@ -22,14 +23,14 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoBlockUserFromCommunity {
to: PublicUrl,
object: Activity<BlockUserFromCommunity>,
object: LemmyActivity<BlockUserFromCommunity>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: BlockType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoBlockUserFromCommunity> {
impl ActivityHandler for LemmyActivity<UndoBlockUserFromCommunity> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,10 +1,6 @@
use crate::{
activities::community::{
delete::DeleteCommunity,
send_websocket_message,
verify_is_community_mod,
},
inbox::new_inbox_routing::Activity,
use crate::activities::{
community::{delete::DeleteCommunity, send_websocket_message, verify_is_community_mod},
LemmyActivity,
};
use activitystreams::activity::kind::DeleteType;
use lemmy_api_common::blocking;
@ -28,14 +24,14 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoDeleteCommunity {
to: PublicUrl,
object: Activity<DeleteCommunity>,
object: LemmyActivity<DeleteCommunity>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: DeleteType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoDeleteCommunity> {
impl ActivityHandler for LemmyActivity<UndoDeleteCommunity> {
type Actor = lemmy_apub::fetcher::Actor;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,6 @@
use crate::{
activities::community::{remove::RemoveCommunity, send_websocket_message},
inbox::new_inbox_routing::Activity,
use crate::activities::{
community::{remove::RemoveCommunity, send_websocket_message},
LemmyActivity,
};
use activitystreams::activity::kind::RemoveType;
use lemmy_api_common::blocking;
@ -16,14 +16,14 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoRemoveCommunity {
to: PublicUrl,
object: Activity<RemoveCommunity>,
object: LemmyActivity<RemoveCommunity>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: RemoveType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoRemoveCommunity> {
impl ActivityHandler for LemmyActivity<UndoRemoveCommunity> {
type Actor = lemmy_apub::fetcher::Actor;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,6 @@
use crate::{
activities::community::{send_websocket_message, verify_is_community_mod},
inbox::new_inbox_routing::Activity,
use crate::activities::{
community::{send_websocket_message, verify_is_community_mod},
LemmyActivity,
};
use activitystreams::{activity::kind::UpdateType, base::BaseExt};
use lemmy_api_common::blocking;
@ -28,7 +28,7 @@ pub struct UpdateCommunity {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UpdateCommunity> {
impl ActivityHandler for LemmyActivity<UpdateCommunity> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::{activities::follow::follow::FollowCommunity, inbox::new_inbox_routing::Activity};
use crate::activities::{following::follow::FollowCommunity, LemmyActivity};
use activitystreams::activity::kind::AcceptType;
use lemmy_api_common::blocking;
use lemmy_apub::{check_is_apub_id_valid, fetcher::person::get_or_fetch_and_upsert_person};
@ -13,14 +13,14 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct AcceptFollowCommunity {
to: Url,
object: Activity<FollowCommunity>,
object: LemmyActivity<FollowCommunity>,
#[serde(rename = "type")]
kind: AcceptType,
}
/// Handle accepted follows
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<AcceptFollowCommunity> {
impl ActivityHandler for LemmyActivity<AcceptFollowCommunity> {
type Actor = Community;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::inbox::new_inbox_routing::Activity;
use crate::activities::LemmyActivity;
use activitystreams::{
activity::{kind::FollowType, Follow},
base::{AnyBase, ExtendsExt},
@ -24,13 +24,13 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct FollowCommunity {
to: Url,
pub(in crate::activities::follow) object: Url,
pub(in crate::activities::following) object: Url,
#[serde(rename = "type")]
kind: FollowType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<FollowCommunity> {
impl ActivityHandler for LemmyActivity<FollowCommunity> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::{activities::follow::follow::FollowCommunity, inbox::new_inbox_routing::Activity};
use crate::activities::{following::follow::FollowCommunity, LemmyActivity};
use activitystreams::activity::kind::UndoType;
use lemmy_api_common::blocking;
use lemmy_apub::{check_is_apub_id_valid, fetcher::community::get_or_fetch_and_upsert_community};
@ -16,13 +16,13 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoFollowCommunity {
to: Url,
object: Activity<FollowCommunity>,
object: LemmyActivity<FollowCommunity>,
#[serde(rename = "type")]
kind: UndoType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoFollowCommunity> {
impl ActivityHandler for LemmyActivity<UndoFollowCommunity> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,3 +1,4 @@
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_db_queries::ApubObject;
@ -9,10 +10,33 @@ use url::Url;
pub mod comment;
pub mod community;
pub mod follow;
pub mod following;
pub mod post;
pub mod private_message;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LemmyActivity<Kind> {
#[serde(rename = "@context")]
context: OneOrMany<AnyBase>,
id: Url,
pub(crate) actor: Url,
/// type-specific fields
#[serde(flatten)]
pub inner: Kind,
// unparsed fields
#[serde(flatten)]
unparsed: Unparsed,
}
impl<Kind> LemmyActivity<Kind> {
pub fn id_unchecked(&self) -> &Url {
&self.id
}
}
async fn verify_mod_action(
actor_id: Url,
activity_cc: Url,
@ -25,7 +49,7 @@ async fn verify_mod_action(
if community.local {
let actor = blocking(&context.pool(), move |conn| {
Person::read_from_apub_id(&conn, &actor_id.clone().into())
Person::read_from_apub_id(&conn, &actor_id.into())
})
.await??;

View file

@ -1,4 +1,4 @@
use crate::{activities::post::send_websocket_message, inbox::new_inbox_routing::Activity};
use crate::activities::{post::send_websocket_message, LemmyActivity};
use activitystreams::{activity::kind::CreateType, base::BaseExt};
use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, ActorType, PageExt};
use lemmy_apub_lib::{verify_domains_match, ActivityHandler, PublicUrl};
@ -18,7 +18,7 @@ pub struct CreatePost {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<CreatePost> {
impl ActivityHandler for LemmyActivity<CreatePost> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::{activities::post::send_websocket_message, inbox::new_inbox_routing::Activity};
use crate::activities::{post::send_websocket_message, LemmyActivity};
use activitystreams::activity::kind::DeleteType;
use lemmy_api_common::blocking;
use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_post};
@ -20,7 +20,7 @@ pub struct DeletePost {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<DeletePost> {
impl ActivityHandler for LemmyActivity<DeletePost> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::{activities::post::like_or_dislike_post, inbox::new_inbox_routing::Activity};
use crate::activities::{post::like_or_dislike_post, LemmyActivity};
use activitystreams::activity::kind::DislikeType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityHandler, PublicUrl};
@ -18,7 +18,7 @@ pub struct DislikePost {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<DislikePost> {
impl ActivityHandler for LemmyActivity<DislikePost> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::{activities::post::like_or_dislike_post, inbox::new_inbox_routing::Activity};
use crate::activities::{post::like_or_dislike_post, LemmyActivity};
use activitystreams::activity::kind::LikeType;
use lemmy_apub::check_is_apub_id_valid;
use lemmy_apub_lib::{verify_domains_match, ActivityHandler, PublicUrl};
@ -18,7 +18,7 @@ pub struct LikePost {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<LikePost> {
impl ActivityHandler for LemmyActivity<LikePost> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,7 +1,4 @@
use crate::{
activities::{post::send_websocket_message, verify_mod_action},
inbox::new_inbox_routing::Activity,
};
use crate::activities::{post::send_websocket_message, verify_mod_action, LemmyActivity};
use activitystreams::activity::kind::RemoveType;
use lemmy_api_common::blocking;
use lemmy_apub::{check_is_apub_id_valid, fetcher::objects::get_or_fetch_and_insert_post};
@ -23,7 +20,7 @@ pub struct RemovePost {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<RemovePost> {
impl ActivityHandler for LemmyActivity<RemovePost> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,6 @@
use crate::{
activities::post::{delete::DeletePost, send_websocket_message},
inbox::new_inbox_routing::Activity,
use crate::activities::{
post::{delete::DeletePost, send_websocket_message},
LemmyActivity,
};
use activitystreams::activity::kind::UndoType;
use lemmy_api_common::blocking;
@ -16,14 +16,14 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoDeletePost {
to: PublicUrl,
object: Activity<DeletePost>,
object: LemmyActivity<DeletePost>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoDeletePost> {
impl ActivityHandler for LemmyActivity<UndoDeletePost> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,6 @@
use crate::{
activities::post::{dislike::DislikePost, undo_like_or_dislike_post},
inbox::new_inbox_routing::Activity,
use crate::activities::{
post::{dislike::DislikePost, undo_like_or_dislike_post},
LemmyActivity,
};
use activitystreams::activity::kind::UndoType;
use lemmy_apub::check_is_apub_id_valid;
@ -14,14 +14,14 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoDislikePost {
to: PublicUrl,
object: Activity<DislikePost>,
object: LemmyActivity<DislikePost>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoDislikePost> {
impl ActivityHandler for LemmyActivity<UndoDislikePost> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,6 @@
use crate::{
activities::post::{like::LikePost, undo_like_or_dislike_post},
inbox::new_inbox_routing::Activity,
use crate::activities::{
post::{like::LikePost, undo_like_or_dislike_post},
LemmyActivity,
};
use activitystreams::activity::kind::UndoType;
use lemmy_apub::check_is_apub_id_valid;
@ -14,13 +14,13 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoLikePost {
to: PublicUrl,
object: Activity<LikePost>,
object: LemmyActivity<LikePost>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoLikePost> {
impl ActivityHandler for LemmyActivity<UndoLikePost> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,9 +1,7 @@
use crate::{
activities::{
use crate::activities::{
post::{remove::RemovePost, send_websocket_message},
verify_mod_action,
},
inbox::new_inbox_routing::Activity,
LemmyActivity,
};
use activitystreams::activity::kind::UndoType;
use lemmy_api_common::blocking;
@ -19,14 +17,14 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoRemovePost {
to: PublicUrl,
object: Activity<RemovePost>,
object: LemmyActivity<RemovePost>,
cc: [Url; 1],
#[serde(rename = "type")]
kind: UndoType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoRemovePost> {
impl ActivityHandler for LemmyActivity<UndoRemovePost> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,4 +1,4 @@
use crate::{activities::post::send_websocket_message, inbox::new_inbox_routing::Activity};
use crate::activities::{post::send_websocket_message, LemmyActivity};
use activitystreams::{activity::kind::UpdateType, base::BaseExt};
use anyhow::Context;
use lemmy_api_common::blocking;
@ -33,7 +33,7 @@ pub struct UpdatePost {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UpdatePost> {
impl ActivityHandler for LemmyActivity<UpdatePost> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,7 +1,4 @@
use crate::{
activities::private_message::send_websocket_message,
inbox::new_inbox_routing::Activity,
};
use crate::activities::{private_message::send_websocket_message, LemmyActivity};
use activitystreams::{activity::kind::CreateType, base::BaseExt};
use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, ActorType, NoteExt};
use lemmy_apub_lib::{verify_domains_match, ActivityHandler};
@ -20,7 +17,7 @@ pub struct CreatePrivateMessage {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<CreatePrivateMessage> {
impl ActivityHandler for LemmyActivity<CreatePrivateMessage> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,7 +1,4 @@
use crate::{
activities::private_message::send_websocket_message,
inbox::new_inbox_routing::Activity,
};
use crate::activities::{private_message::send_websocket_message, LemmyActivity};
use activitystreams::activity::kind::DeleteType;
use lemmy_api_common::blocking;
use lemmy_apub::check_is_apub_id_valid;
@ -22,7 +19,7 @@ pub struct DeletePrivateMessage {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<DeletePrivateMessage> {
impl ActivityHandler for LemmyActivity<DeletePrivateMessage> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,6 +1,6 @@
use crate::{
activities::private_message::{delete::DeletePrivateMessage, send_websocket_message},
inbox::new_inbox_routing::Activity,
use crate::activities::{
private_message::{delete::DeletePrivateMessage, send_websocket_message},
LemmyActivity,
};
use activitystreams::activity::kind::UndoType;
use lemmy_api_common::blocking;
@ -16,13 +16,13 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoDeletePrivateMessage {
to: Url,
object: Activity<DeletePrivateMessage>,
object: LemmyActivity<DeletePrivateMessage>,
#[serde(rename = "type")]
kind: UndoType,
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UndoDeletePrivateMessage> {
impl ActivityHandler for LemmyActivity<UndoDeletePrivateMessage> {
type Actor = Person;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,7 +1,4 @@
use crate::{
activities::private_message::send_websocket_message,
inbox::new_inbox_routing::Activity,
};
use crate::activities::{private_message::send_websocket_message, LemmyActivity};
use activitystreams::{activity::kind::UpdateType, base::BaseExt};
use lemmy_apub::{check_is_apub_id_valid, objects::FromApub, ActorType, NoteExt};
use lemmy_apub_lib::{verify_domains_match, ActivityHandler};
@ -20,7 +17,7 @@ pub struct UpdatePrivateMessage {
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Activity<UpdatePrivateMessage> {
impl ActivityHandler for LemmyActivity<UpdatePrivateMessage> {
type Actor = Person;
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {

View file

@ -1,10 +1,18 @@
use crate::http::{create_apub_response, create_apub_tombstone_response};
use crate::{
activities::LemmyActivity,
http::{
create_apub_response,
create_apub_tombstone_response,
inbox_enums::GroupInboxActivities,
receive_activity,
},
};
use activitystreams::{
base::{AnyBase, BaseExt},
collection::{CollectionExt, OrderedCollection, UnorderedCollection},
url::Url,
};
use actix_web::{body::Body, web, HttpResponse};
use actix_web::{body::Body, web, HttpRequest, HttpResponse};
use lemmy_api_common::blocking;
use lemmy_apub::{
extensions::context::lemmy_context,
@ -46,6 +54,16 @@ pub(crate) async fn get_apub_community_http(
}
}
/// Handler for all incoming receive to community inboxes.
pub async fn community_inbox(
request: HttpRequest,
input: web::Json<LemmyActivity<GroupInboxActivities>>,
path: web::Path<String>,
context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> {
receive_activity(request, input.into_inner(), Some(path.0), context).await
}
/// Returns an empty followers collection, only populating the size (for privacy).
pub(crate) async fn get_apub_community_followers(
info: web::Path<CommunityQuery>,

View file

@ -23,7 +23,7 @@ use crate::activities::{
undo_remove::UndoRemoveCommunity,
update::UpdateCommunity,
},
follow::{accept::AcceptFollowCommunity, follow::FollowCommunity, undo::UndoFollowCommunity},
following::{accept::AcceptFollowCommunity, follow::FollowCommunity, undo::UndoFollowCommunity},
post::{
create::CreatePost,
delete::DeletePost,
@ -43,46 +43,25 @@ use crate::activities::{
update::UpdatePrivateMessage,
},
};
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
use lemmy_apub_lib::ActivityHandler;
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
use serde::{Deserialize, Serialize};
// TODO: would be nice if we could move this to lemmy_apub_lib crate. doing that gives error:
// "only traits defined in the current crate can be implemented for arbitrary types"
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Activity<Kind> {
#[serde(rename = "@context")]
context: OneOrMany<AnyBase>,
id: Url,
pub(crate) actor: Url,
/// type-specific fields
#[serde(flatten)]
pub inner: Kind,
// unparsed fields
#[serde(flatten)]
unparsed: Unparsed,
}
impl<Kind> Activity<Kind> {
pub fn id_unchecked(&self) -> &Url {
&self.id
}
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub enum SharedInboxActivities {
FollowCommunity(FollowCommunity),
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum PersonInboxActivities {
AcceptFollowCommunity(AcceptFollowCommunity),
UndoFollowCommunity(UndoFollowCommunity),
CreatePrivateMessage(CreatePrivateMessage),
UpdatePrivateMessage(UpdatePrivateMessage),
DeletePrivateMessage(DeletePrivateMessage),
UndoDeletePrivateMessage(UndoDeletePrivateMessage),
AnnounceActivity(Box<AnnounceActivity>),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum GroupInboxActivities {
FollowCommunity(FollowCommunity),
UndoFollowCommunity(UndoFollowCommunity),
CreateComment(CreateComment),
UpdateComment(UpdateComment),
LikeComment(LikeComment),
@ -103,16 +82,58 @@ pub enum SharedInboxActivities {
UndoRemovePost(UndoRemovePost),
UndoLikePost(UndoLikePost),
UndoDislikePost(UndoDislikePost),
AnnounceActivity(AnnounceActivity),
UpdateCommunity(UpdateCommunity),
UpdateCommunity(Box<UpdateCommunity>),
DeleteCommunity(DeleteCommunity),
RemoveCommunity(RemoveCommunity),
AddMod(AddMod),
RemoveMod(RemoveMod),
UndoDeleteCommunity(UndoDeleteCommunity),
UndoRemoveCommunity(UndoRemoveCommunity),
BlockUserFromCommunity(BlockUserFromCommunity),
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
AddMod(AddMod),
RemoveMod(RemoveMod),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum SharedInboxActivities {
// received by person
AcceptFollowCommunity(AcceptFollowCommunity),
CreatePrivateMessage(CreatePrivateMessage),
UpdatePrivateMessage(UpdatePrivateMessage),
DeletePrivateMessage(DeletePrivateMessage),
UndoDeletePrivateMessage(UndoDeletePrivateMessage),
AnnounceActivity(Box<AnnounceActivity>),
// received by group
FollowCommunity(FollowCommunity),
UndoFollowCommunity(UndoFollowCommunity),
CreateComment(CreateComment),
UpdateComment(UpdateComment),
LikeComment(LikeComment),
DislikeComment(DislikeComment),
UndoLikeComment(UndoLikeComment),
UndoDislikeComment(UndoDislikeComment),
DeleteComment(DeleteComment),
UndoDeleteComment(UndoDeleteComment),
RemoveComment(RemoveComment),
UndoRemoveComment(UndoRemoveComment),
CreatePost(CreatePost),
UpdatePost(UpdatePost),
LikePost(LikePost),
DislikePost(DislikePost),
DeletePost(DeletePost),
UndoDeletePost(UndoDeletePost),
RemovePost(RemovePost),
UndoRemovePost(UndoRemovePost),
UndoLikePost(UndoLikePost),
UndoDislikePost(UndoDislikePost),
UpdateCommunity(Box<UpdateCommunity>),
DeleteCommunity(DeleteCommunity),
RemoveCommunity(RemoveCommunity),
UndoDeleteCommunity(UndoDeleteCommunity),
UndoRemoveCommunity(UndoRemoveCommunity),
BlockUserFromCommunity(BlockUserFromCommunity),
UndoBlockUserFromCommunity(UndoBlockUserFromCommunity),
AddMod(AddMod),
RemoveMod(RemoveMod),
}
#[async_trait::async_trait(?Send)]
@ -132,3 +153,39 @@ impl ActivityHandler for SharedInboxActivities {
self.receive(actor, context, request_counter).await
}
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for PersonInboxActivities {
type Actor = lemmy_apub::fetcher::Actor;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
self.verify(context).await
}
async fn receive(
&self,
actor: Self::Actor,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
self.receive(actor, context, request_counter).await
}
}
#[async_trait::async_trait(?Send)]
impl ActivityHandler for GroupInboxActivities {
type Actor = lemmy_apub::fetcher::Actor;
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
self.verify(context).await
}
async fn receive(
&self,
actor: Self::Actor,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
self.receive(actor, context, request_counter).await
}
}

View file

@ -1,19 +1,90 @@
use actix_web::{body::Body, web, HttpResponse};
use actix_web::{body::Body, web, HttpRequest, HttpResponse};
use http::StatusCode;
use lemmy_api_common::blocking;
use lemmy_apub::APUB_JSON_CONTENT_TYPE;
use lemmy_db_queries::source::activity::Activity_;
use lemmy_db_schema::source::activity::Activity;
use lemmy_utils::{settings::structs::Settings, LemmyError};
use lemmy_websocket::LemmyContext;
use serde::{Deserialize, Serialize};
use url::Url;
use crate::{activities::LemmyActivity, http::inbox_enums::SharedInboxActivities};
use anyhow::{anyhow, Context};
use lemmy_api_common::blocking;
use lemmy_apub::{
check_is_apub_id_valid,
extensions::signatures::verify_signature,
fetcher::{get_or_fetch_and_upsert_actor, Actor},
insert_activity,
APUB_JSON_CONTENT_TYPE,
};
use lemmy_apub_lib::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 std::fmt::Debug;
pub mod comment;
pub mod community;
pub mod inbox_enums;
pub mod person;
pub mod post;
pub async fn shared_inbox(
request: HttpRequest,
input: web::Json<LemmyActivity<SharedInboxActivities>>,
context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> {
receive_activity(request, input.into_inner(), None, context).await
}
async fn receive_activity<T>(
request: HttpRequest,
activity: LemmyActivity<T>,
expected_name: Option<String>,
context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError>
where
T: ActivityHandler<Actor = lemmy_apub::fetcher::Actor>
+ Clone
+ Serialize
+ std::fmt::Debug
+ Send
+ 'static,
{
// TODO: which order to check things?
// Do nothing if we received the same activity before
if is_activity_already_known(context.pool(), &activity.id_unchecked()).await? {
return Ok(HttpResponse::Ok().finish());
}
assert_activity_not_local(&activity)?;
check_is_apub_id_valid(&activity.actor, false)?;
activity.inner.verify(&context).await?;
let request_counter = &mut 0;
let actor: Actor =
get_or_fetch_and_upsert_actor(&activity.actor, &context, request_counter).await?;
if let Some(expected) = expected_name {
if expected != actor.name() {
return Ok(HttpResponse::BadRequest().finish());
}
}
verify_signature(&request, &actor.public_key().context(location_info!())?)?;
// 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.
insert_activity(
&activity.id_unchecked(),
activity.clone(),
false,
true,
context.pool(),
)
.await?;
activity
.inner
.receive(actor, &context, request_counter)
.await?;
Ok(HttpResponse::Ok().finish())
}
/// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
/// headers.
fn create_apub_response<T>(data: &T) -> HttpResponse<Body>
@ -36,14 +107,14 @@ where
}
#[derive(Deserialize)]
pub struct CommunityQuery {
pub struct ActivityQuery {
type_: String,
id: String,
}
/// Return the ActivityPub json representation of a local community over HTTP.
/// Return the ActivityPub json representation of a local activity over HTTP.
pub(crate) async fn get_activity(
info: web::Path<CommunityQuery>,
info: web::Path<ActivityQuery>,
context: web::Data<LemmyContext>,
) -> Result<HttpResponse<Body>, LemmyError> {
let settings = Settings::get();
@ -66,3 +137,35 @@ pub(crate) async fn get_activity(
Ok(create_apub_response(&activity.data))
}
}
pub(crate) async fn is_activity_already_known(
pool: &DbPool,
activity_id: &Url,
) -> Result<bool, LemmyError> {
let activity_id = activity_id.to_owned().into();
let existing = blocking(pool, move |conn| {
Activity::read_from_apub_id(&conn, &activity_id)
})
.await?;
match existing {
Ok(_) => Ok(true),
Err(_) => Ok(false),
}
}
pub(in crate::http) fn assert_activity_not_local<T: Debug>(
activity: &LemmyActivity<T>,
) -> Result<(), LemmyError> {
let activity_domain = activity.id_unchecked().domain().context(location_info!())?;
if activity_domain == Settings::get().hostname() {
return Err(
anyhow!(
"Error: received activity which was sent by local instance: {:?}",
activity
)
.into(),
);
}
Ok(())
}

View file

@ -1,9 +1,17 @@
use crate::http::{create_apub_response, create_apub_tombstone_response};
use crate::{
activities::LemmyActivity,
http::{
create_apub_response,
create_apub_tombstone_response,
inbox_enums::PersonInboxActivities,
receive_activity,
},
};
use activitystreams::{
base::BaseExt,
collection::{CollectionExt, OrderedCollection},
};
use actix_web::{body::Body, web, HttpResponse};
use actix_web::{body::Body, web, HttpRequest, HttpResponse};
use lemmy_api_common::blocking;
use lemmy_apub::{extensions::context::lemmy_context, objects::ToApub, ActorType};
use lemmy_db_queries::source::person::Person_;
@ -39,6 +47,15 @@ pub(crate) async fn get_apub_person_http(
}
}
pub async fn person_inbox(
request: HttpRequest,
input: web::Json<LemmyActivity<PersonInboxActivities>>,
path: web::Path<String>,
context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> {
receive_activity(request, input.into_inner(), Some(path.0), context).await
}
pub(crate) async fn get_apub_person_outbox(
info: web::Path<PersonQuery>,
context: web::Data<LemmyContext>,

View file

@ -1,14 +0,0 @@
use crate::inbox::new_inbox_routing::{Activity, SharedInboxActivities};
use actix_web::{web, HttpRequest, HttpResponse};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
/// Handler for all incoming receive to community inboxes.
pub async fn community_inbox(
_request: HttpRequest,
_input: web::Json<Activity<Activity<SharedInboxActivities>>>,
_path: web::Path<String>,
_context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> {
todo!()
}

View file

@ -1,45 +0,0 @@
use crate::inbox::new_inbox_routing::Activity;
use anyhow::{anyhow, Context};
use lemmy_api_common::blocking;
use lemmy_db_queries::{source::activity::Activity_, DbPool};
use lemmy_db_schema::source::activity::Activity as DbActivity;
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
use std::fmt::Debug;
use url::Url;
pub mod community_inbox;
pub mod new_inbox_routing;
pub mod person_inbox;
pub mod shared_inbox;
pub(crate) async fn is_activity_already_known(
pool: &DbPool,
activity_id: &Url,
) -> Result<bool, LemmyError> {
let activity_id = activity_id.to_owned().into();
let existing = blocking(pool, move |conn| {
DbActivity::read_from_apub_id(&conn, &activity_id)
})
.await?;
match existing {
Ok(_) => Ok(true),
Err(_) => Ok(false),
}
}
pub(in crate::inbox) fn assert_activity_not_local<T: Debug>(
activity: &Activity<T>,
) -> Result<(), LemmyError> {
let activity_domain = activity.id_unchecked().domain().context(location_info!())?;
if activity_domain == Settings::get().hostname() {
return Err(
anyhow!(
"Error: received activity which was sent by local instance: {:?}",
activity
)
.into(),
);
}
Ok(())
}

View file

@ -1,13 +0,0 @@
use crate::inbox::new_inbox_routing::{Activity, SharedInboxActivities};
use actix_web::{web, HttpRequest, HttpResponse};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
pub async fn person_inbox(
_request: HttpRequest,
_input: web::Json<Activity<Activity<SharedInboxActivities>>>,
_path: web::Path<String>,
_context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> {
todo!()
}

View file

@ -1,57 +0,0 @@
use crate::inbox::{
assert_activity_not_local,
is_activity_already_known,
new_inbox_routing::{Activity, SharedInboxActivities},
};
use actix_web::{web, HttpRequest, HttpResponse};
use anyhow::Context;
use lemmy_apub::{
check_is_apub_id_valid,
extensions::signatures::verify_signature,
fetcher::{get_or_fetch_and_upsert_actor2, Actor},
insert_activity,
};
use lemmy_apub_lib::ActivityHandler;
use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext;
pub async fn shared_inbox(
request: HttpRequest,
input: web::Json<Activity<SharedInboxActivities>>,
context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> {
let activity = input.into_inner();
// Do nothing if we received the same activity before
if is_activity_already_known(context.pool(), &activity.id_unchecked()).await? {
return Ok(HttpResponse::Ok().finish());
}
assert_activity_not_local(&activity)?;
check_is_apub_id_valid(&activity.actor, false)?;
activity.inner.verify(&context).await?;
let request_counter = &mut 0;
let actor = get_or_fetch_and_upsert_actor2(&activity.actor, &context, request_counter).await?;
let public_key = match &actor {
Actor::Person(p) => p.public_key.as_ref().context(location_info!())?,
Actor::Community(c) => c.public_key.as_ref().context(location_info!())?,
};
verify_signature(&request, &public_key)?;
// 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.
insert_activity(
&activity.id_unchecked(),
activity.clone(),
false,
true,
context.pool(),
)
.await?;
activity
.inner
.receive(actor, &context, request_counter)
.await?;
return Ok(HttpResponse::Ok().finish());
}

View file

@ -1,4 +1,3 @@
pub mod activities;
mod activities;
mod http;
mod inbox;
pub mod routes;

View file

@ -1,7 +1,7 @@
use crate::{
http::{
use crate::http::{
comment::get_apub_comment,
community::{
community_inbox,
get_apub_community_followers,
get_apub_community_http,
get_apub_community_inbox,
@ -9,14 +9,9 @@ use crate::{
get_apub_community_outbox,
},
get_activity,
person::{get_apub_person_http, get_apub_person_inbox, get_apub_person_outbox},
person::{get_apub_person_http, get_apub_person_inbox, get_apub_person_outbox, person_inbox},
post::get_apub_post,
},
inbox::{
community_inbox::community_inbox,
person_inbox::person_inbox,
shared_inbox::shared_inbox,
},
shared_inbox,
};
use actix_web::*;
use http_signature_normalization_actix::digest::middleware::VerifyDigest;