start to implement apub inbox routing lib

This commit is contained in:
Felix Ableitner 2021-06-22 14:19:25 +02:00
parent 469a2b5c90
commit 388b80d64e
7 changed files with 157 additions and 18 deletions

53
Cargo.lock generated
View file

@ -1762,8 +1762,8 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"sha2", "sha2",
"strum", "strum 0.20.0",
"strum_macros", "strum_macros 0.20.1",
"thiserror", "thiserror",
"tokio 0.3.7", "tokio 0.3.7",
"url", "url",
@ -1825,8 +1825,8 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"sha2", "sha2",
"strum", "strum 0.20.0",
"strum_macros", "strum_macros 0.20.1",
"thiserror", "thiserror",
"tokio 0.3.7", "tokio 0.3.7",
"url", "url",
@ -1872,8 +1872,8 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"sha2", "sha2",
"strum", "strum 0.20.0",
"strum_macros", "strum_macros 0.20.1",
"thiserror", "thiserror",
"tokio 0.3.7", "tokio 0.3.7",
"url", "url",
@ -1917,8 +1917,8 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"sha2", "sha2",
"strum", "strum 0.21.0",
"strum_macros", "strum_macros 0.21.1",
"thiserror", "thiserror",
"tokio 0.3.7", "tokio 0.3.7",
"url", "url",
@ -1941,8 +1941,8 @@ dependencies = [
"serde_json", "serde_json",
"serial_test", "serial_test",
"sha2", "sha2",
"strum", "strum 0.20.0",
"strum_macros", "strum_macros 0.20.1",
"url", "url",
] ]
@ -2015,7 +2015,7 @@ dependencies = [
"rss", "rss",
"serde", "serde",
"sha2", "sha2",
"strum", "strum 0.20.0",
"url", "url",
] ]
@ -2053,7 +2053,7 @@ dependencies = [
"reqwest", "reqwest",
"serde", "serde",
"serde_json", "serde_json",
"strum", "strum 0.20.0",
"tokio 0.3.7", "tokio 0.3.7",
"url", "url",
] ]
@ -2085,8 +2085,8 @@ dependencies = [
"reqwest", "reqwest",
"serde", "serde",
"serde_json", "serde_json",
"strum", "strum 0.20.0",
"strum_macros", "strum_macros 0.20.1",
"thiserror", "thiserror",
"tokio 0.3.7", "tokio 0.3.7",
"url", "url",
@ -2112,8 +2112,8 @@ dependencies = [
"reqwest", "reqwest",
"serde", "serde",
"serde_json", "serde_json",
"strum", "strum 0.20.0",
"strum_macros", "strum_macros 0.20.1",
"tokio 0.3.7", "tokio 0.3.7",
] ]
@ -3373,6 +3373,15 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c" checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c"
[[package]]
name = "strum"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2"
dependencies = [
"strum_macros 0.21.1",
]
[[package]] [[package]]
name = "strum_macros" name = "strum_macros"
version = "0.20.1" version = "0.20.1"
@ -3385,6 +3394,18 @@ dependencies = [
"syn 1.0.60", "syn 1.0.60",
] ]
[[package]]
name = "strum_macros"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec"
dependencies = [
"heck",
"proc-macro2 1.0.24",
"quote 1.0.8",
"syn 1.0.60",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "0.14.9" version = "0.14.9"

View file

@ -52,6 +52,7 @@ pub type GroupExt =
/// Activitystreams type for person /// Activitystreams type for person
type PersonExt = type PersonExt =
Ext2<actor::ApActor<ApObject<actor::Actor<UserTypes>>>, PersonExtension, PublicKeyExtension>; Ext2<actor::ApActor<ApObject<actor::Actor<UserTypes>>>, PersonExtension, PublicKeyExtension>;
pub type SiteExt = actor::ApActor<ApObject<actor::Service>>;
/// Activitystreams type for post /// Activitystreams type for post
pub type PageExt = Ext1<ApObject<Page>, PageExtension>; pub type PageExt = Ext1<ApObject<Page>, PageExtension>;
pub type NoteExt = ApObject<Note>; pub type NoteExt = ApObject<Note>;

View file

@ -25,8 +25,8 @@ actix-rt = { version = "1.1.1", default-features = false }
awc = { version = "2.0.3", default-features = false } awc = { version = "2.0.3", default-features = false }
log = "0.4.14" log = "0.4.14"
rand = "0.8.3" rand = "0.8.3"
strum = "0.20.0" strum = { version = "0.21", features = ["derive"] }
strum_macros = "0.20.1" strum_macros = "0.21"
url = { version = "2.2.1", features = ["serde"] } url = { version = "2.2.1", features = ["serde"] }
percent-encoding = "2.1.0" percent-encoding = "2.1.0"
openssl = "0.10.32" openssl = "0.10.32"

View file

@ -15,6 +15,20 @@ use lemmy_db_views::comment_view::CommentView;
use lemmy_utils::{location_info, utils::scrape_text_for_mentions, LemmyError}; use lemmy_utils::{location_info, utils::scrape_text_for_mentions, LemmyError};
use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperation, UserOperationCrud}; use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperation, UserOperationCrud};
// TODO:
// - define traits for all activity types
// - implement inbox routing with these traits
// - replace context with actix style Data struct (actix_web::web::Data)
pub(crate) trait ReceiveCreate {
fn receive_create(self, create: Create, context: LemmyContext, request_counter: &mut i32);
}
impl ReceiveCreate for Comment {
fn receive_create(self, _create: Create, _context: LemmyContext, _request_counter: &mut i32) {
unimplemented!()
}
}
pub(crate) async fn receive_create_comment( pub(crate) async fn receive_create_comment(
create: Create, create: Create,
context: &LemmyContext, context: &LemmyContext,

View file

@ -5,6 +5,7 @@ use crate::{
get_activity_id, get_activity_id,
inbox_verify_http_signature, inbox_verify_http_signature,
is_activity_already_known, is_activity_already_known,
new_inbox_routing::receive_activity,
receive_for_community::{ receive_for_community::{
receive_add_for_community, receive_add_for_community,
receive_block_user_for_community, receive_block_user_for_community,
@ -136,6 +137,7 @@ pub(crate) async fn community_receive_message(
let any_base = activity.clone().into_any_base()?; let any_base = activity.clone().into_any_base()?;
let actor_url = actor.actor_id(); let actor_url = actor.actor_id();
let activity_kind = activity.kind().context(location_info!())?; let activity_kind = activity.kind().context(location_info!())?;
receive_activity(any_base.clone(), context)?;
let do_announce = match activity_kind { let do_announce = match activity_kind {
CommunityValidTypes::Follow => { CommunityValidTypes::Follow => {
Box::pin(handle_follow( Box::pin(handle_follow(

View file

@ -27,6 +27,7 @@ use std::fmt::Debug;
use url::Url; use url::Url;
pub mod community_inbox; pub mod community_inbox;
pub mod new_inbox_routing;
pub mod person_inbox; pub mod person_inbox;
pub(crate) mod receive_for_community; pub(crate) mod receive_for_community;
pub mod shared_inbox; pub mod shared_inbox;

View file

@ -0,0 +1,100 @@
use activitystreams::base::AnyBase;
use anyhow::Context;
use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext;
use std::{collections::HashMap, str::FromStr};
use strum_macros::EnumString;
// for now, limit it to activity routing only, no http sigs, parsing or any of that
// need to route in this order:
// 1. recipient actor
// 2. activity type
// 3. inner object (recursively until object is empty or an url)
// library part
/// macro shorthand to create hashmap
/// usage: `let counts = hashmap!['A' => 0, 'C' => 0, 'G' => 0, 'T' => 0];`
/// from https://stackoverflow.com/questions/28392008/more-concise-hashmap-initialization
macro_rules! hashmap {
($( $key: expr => $val: expr ),*) => {{
let mut map = ::std::collections::HashMap::new();
$( map.insert($key, $val); )*
map
}}
}
#[derive(Hash, Eq, PartialEq, EnumString)]
enum ActivityTypes {
Follow,
Announce,
Create,
}
#[derive(Eq, PartialEq)]
enum ObjectTypes {
Page,
Note,
Url, // we dont dereference urls in object field, so we dont know what exactly it refers to
None, // object field doesnt exist
}
struct InboxConfig {
actors: Vec<ActorConfig>,
}
impl InboxConfig {
fn shared_inbox_handler() {
todo!()
}
}
type AcceptedTypes = HashMap<ActivityTypes, InnerType>;
// TODO: need to provide a handler function for each value
enum InnerType {
Simple(ObjectTypes),
Nested(AcceptedTypes),
}
struct ActorConfig {
accepted_types: AcceptedTypes,
}
impl ActorConfig {
pub(crate) fn actor_inbox_handler(
self,
activity: AnyBase,
_context: &LemmyContext,
) -> Result<(), LemmyError> {
// TODO: probably better to define our own struct with the fields we need + unparsed, and later
// convert to activity (needs id_unchecked(), kind, object)
let kind = ActivityTypes::from_str(activity.kind_str().context(location_info!())?)?;
use InnerType::*;
match self.accepted_types.get(&kind).context(location_info!())? {
Simple(o) => {}
Nested(a) => {}
}
// TODO: correctly route the activity to handle_follow, receive_create_comment or receive_create_post
todo!()
}
}
// application part
pub(crate) fn receive_activity(
activity: AnyBase,
context: &LemmyContext,
) -> Result<(), LemmyError> {
use ActivityTypes::*;
use InnerType::*;
use ObjectTypes::*;
let accepted_types = hashmap![Follow => Simple(Url),
Announce =>
Nested(hashmap![Create => Simple(Note), Create => Simple(Page)])];
let community_inbox_config = ActorConfig { accepted_types };
let inbox_config = InboxConfig { actors: vec![] };
community_inbox_config.actor_inbox_handler(activity, context)?;
Ok(())
}