Move ActorType, signatures, activity_queue to apub library

This commit is contained in:
Felix Ableitner 2021-10-04 16:52:20 +02:00
parent 455e0b5760
commit d3a3cf04e7
53 changed files with 383 additions and 390 deletions

15
Cargo.lock generated
View file

@ -1746,17 +1746,13 @@ dependencies = [
"anyhow",
"async-trait",
"awc",
"background-jobs",
"base64 0.13.0",
"bcrypt",
"chrono",
"diesel",
"futures",
"http",
"http-signature-normalization-actix",
"http-signature-normalization-reqwest",
"itertools",
"lazy_static",
"lemmy_api_common",
"lemmy_apub_lib",
"lemmy_db_queries",
@ -1766,7 +1762,6 @@ dependencies = [
"lemmy_utils",
"lemmy_websocket",
"log",
"openssl",
"percent-encoding",
"rand 0.8.4",
"reqwest",
@ -1787,14 +1782,23 @@ name = "lemmy_apub_lib"
version = "0.13.0"
dependencies = [
"activitystreams",
"actix-web",
"anyhow",
"async-trait",
"background-jobs",
"base64 0.13.0",
"http",
"http-signature-normalization-actix",
"http-signature-normalization-reqwest",
"lazy_static",
"lemmy_apub_lib_derive",
"lemmy_utils",
"log",
"openssl",
"reqwest",
"serde",
"serde_json",
"sha2",
"url",
]
@ -1927,6 +1931,7 @@ dependencies = [
"lemmy_api_common",
"lemmy_api_crud",
"lemmy_apub",
"lemmy_apub_lib",
"lemmy_db_queries",
"lemmy_db_schema",
"lemmy_db_views",

View file

@ -35,6 +35,7 @@ members = [
lemmy_api = { version = "=0.13.0", path = "./crates/api" }
lemmy_api_crud = { version = "=0.13.0", path = "./crates/api_crud" }
lemmy_apub = { version = "=0.13.0", path = "./crates/apub" }
lemmy_apub_lib = { version = "=0.13.0", path = "./crates/apub_lib" }
lemmy_utils = { version = "=0.13.0", path = "./crates/utils" }
lemmy_db_schema = { version = "=0.13.0", path = "./crates/db_schema" }
lemmy_db_queries = { version = "=0.13.0", path = "./crates/db_queries" }

View file

@ -1,7 +1,7 @@
#!/bin/bash
set -e
export LEMMY_TEST_SEND_SYNC=1
export APUB_TESTING_SEND_SYNC=1
export RUST_BACKTRACE=1
export RUST_LOG="warn,lemmy_server=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_queries=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug"

View file

@ -36,11 +36,8 @@ strum = "0.21.0"
strum_macros = "0.21.1"
url = { version = "2.2.2", features = ["serde"] }
percent-encoding = "2.1.0"
openssl = "0.10.36"
http = "0.2.5"
http-signature-normalization-actix = { version = "0.5.0-beta.10", default-features = false, features = ["server", "sha-2"] }
http-signature-normalization-reqwest = { version = "0.2.0", default-features = false, features = ["sha-2"] }
base64 = "0.13.0"
tokio = "1.12.0"
futures = "0.3.17"
itertools = "0.10.1"
@ -49,7 +46,5 @@ sha2 = "0.9.8"
async-trait = "0.1.51"
anyhow = "1.0.44"
thiserror = "1.0.29"
background-jobs = "0.10.0"
reqwest = { version = "0.11.4", features = ["json"] }
lazy_static = "1.4.0"

View file

@ -1,24 +1,22 @@
use crate::{
activities::{
comment::{collect_non_local_mentions, get_notif_recipients},
community::announce::AnnouncableActivities,
community::{announce::AnnouncableActivities, send_to_community},
extract_community,
generate_activity_id,
verify_activity,
verify_person_in_community,
CreateOrUpdateType,
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
objects::{comment::Note, FromApub, ToApub},
ActorType,
};
use activitystreams::{base::AnyBase, link::Mention, primitives::OneOrMany, unparsed::Unparsed};
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
verify::verify_domains_match,
};
@ -81,7 +79,7 @@ impl CreateOrUpdateComment {
};
let activity = AnnouncableActivities::CreateOrUpdateComment(create_or_update);
send_to_community_new(activity, &id, actor, &community, maa.inboxes, context).await
send_to_community(activity, &id, actor, &community, maa.inboxes, context).await
}
}

View file

@ -1,4 +1,4 @@
use crate::{fetcher::object_id::ObjectId, ActorType};
use crate::fetcher::object_id::ObjectId;
use activitystreams::{
base::BaseExt,
link::{LinkExt, Mention},
@ -6,7 +6,7 @@ use activitystreams::{
use anyhow::anyhow;
use itertools::Itertools;
use lemmy_api_common::{blocking, send_local_notifs};
use lemmy_apub_lib::webfinger::WebfingerResponse;
use lemmy_apub_lib::{traits::ActorType, webfinger::WebfingerResponse};
use lemmy_db_queries::{Crud, DbPool};
use lemmy_db_schema::{
source::{comment::Comment, community::Community, person::Person, post::Post},
@ -68,7 +68,7 @@ pub async fn collect_non_local_mentions(
let parent_creator = get_comment_parent_creator(context.pool(), comment).await?;
let mut addressed_ccs = vec![community.actor_id(), parent_creator.actor_id()];
// Note: dont include community inbox here, as we send to it separately with `send_to_community()`
let mut inboxes = vec![parent_creator.get_shared_inbox_or_inbox_url()];
let mut inboxes = vec![parent_creator.shared_inbox_or_inbox_url()];
// Add the mention tag
let mut tags = Vec::new();
@ -88,7 +88,7 @@ pub async fn collect_non_local_mentions(
addressed_ccs.push(actor_id.to_owned().to_string().parse()?);
let mention_person = actor_id.dereference(context, &mut 0).await?;
inboxes.push(mention_person.get_shared_inbox_or_inbox_url());
inboxes.push(mention_person.shared_inbox_or_inbox_url());
let mut mention_tag = Mention::new();
mention_tag

View file

@ -1,17 +1,15 @@
use crate::{
activities::{
community::announce::AnnouncableActivities,
community::{announce::AnnouncableActivities, send_to_community},
generate_activity_id,
verify_activity,
verify_add_remove_moderator_target,
verify_mod_action,
verify_person_in_community,
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
generate_moderators_url,
ActorType,
};
use activitystreams::{
activity::kind::AddType,
@ -22,7 +20,7 @@ use activitystreams::{
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
};
use lemmy_db_queries::{source::community::CommunityModerator_, Joinable};
@ -76,8 +74,8 @@ impl AddMod {
};
let activity = AnnouncableActivities::AddMod(add);
let inboxes = vec![added_mod.get_shared_inbox_or_inbox_url()];
send_to_community_new(activity, &id, actor, community, inboxes, context).await
let inboxes = vec![added_mod.shared_inbox_or_inbox_url()];
send_to_community(activity, &id, actor, community, inboxes, context).await
}
}

View file

@ -17,12 +17,11 @@ use crate::{
verify_community,
voting::{undo_vote::UndoVote, vote::Vote},
},
activity_queue::send_activity_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
http::is_activity_already_known,
insert_activity,
ActorType,
send_lemmy_activity,
CommunityType,
};
use activitystreams::{
@ -33,7 +32,7 @@ use activitystreams::{
};
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
};
use lemmy_db_schema::source::community::Community;
@ -97,7 +96,7 @@ impl AnnounceActivity {
unparsed: Default::default(),
};
let inboxes = list_community_follower_inboxes(community, additional_inboxes, context).await?;
send_activity_new(context, &announce, &announce.id, community, inboxes, false).await
send_lemmy_activity(context, &announce, &announce.id, community, inboxes, false).await
}
}

View file

@ -1,15 +1,13 @@
use crate::{
activities::{
community::announce::AnnouncableActivities,
community::{announce::AnnouncableActivities, send_to_community},
generate_activity_id,
verify_activity,
verify_mod_action,
verify_person_in_community,
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
ActorType,
};
use activitystreams::{
activity::kind::BlockType,
@ -20,7 +18,7 @@ use activitystreams::{
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
};
use lemmy_db_queries::{Bannable, Followable};
@ -87,8 +85,8 @@ impl BlockUserFromCommunity {
let block_id = block.id.clone();
let activity = AnnouncableActivities::BlockUserFromCommunity(block);
let inboxes = vec![target.get_shared_inbox_or_inbox_url()];
send_to_community_new(activity, &block_id, actor, community, inboxes, context).await
let inboxes = vec![target.shared_inbox_or_inbox_url()];
send_to_community(activity, &block_id, actor, community, inboxes, context).await
}
}

View file

@ -1,5 +1,12 @@
use crate::{check_is_apub_id_valid, CommunityType};
use crate::{
activities::community::announce::{AnnouncableActivities, AnnounceActivity},
check_is_apub_id_valid,
insert_activity,
send_lemmy_activity,
CommunityType,
};
use itertools::Itertools;
use lemmy_apub_lib::traits::ActorType;
use lemmy_db_schema::source::community::Community;
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
@ -33,3 +40,24 @@ async fn list_community_follower_inboxes(
.collect(),
)
}
pub(crate) async fn send_to_community<T: ActorType>(
activity: AnnouncableActivities,
activity_id: &Url,
actor: &T,
community: &Community,
additional_inboxes: Vec<Url>,
context: &LemmyContext,
) -> Result<(), LemmyError> {
// if this is a local community, we need to do an announce from the community instead
if community.local {
insert_activity(activity_id, activity.clone(), true, false, context.pool()).await?;
AnnounceActivity::send(activity, community, additional_inboxes, context).await?;
} else {
let mut inboxes = additional_inboxes;
inboxes.push(community.shared_inbox_or_inbox_url());
send_lemmy_activity(context, &activity, activity_id, actor, inboxes, false).await?;
}
Ok(())
}

View file

@ -1,6 +1,6 @@
use crate::{
activities::{
community::announce::AnnouncableActivities,
community::{announce::AnnouncableActivities, send_to_community},
deletion::{delete::receive_remove_action, verify_delete_activity},
generate_activity_id,
verify_activity,
@ -8,11 +8,9 @@ use crate::{
verify_mod_action,
verify_person_in_community,
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
generate_moderators_url,
ActorType,
};
use activitystreams::{
activity::kind::RemoveType,
@ -23,7 +21,7 @@ use activitystreams::{
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
};
use lemmy_db_queries::Joinable;
@ -78,8 +76,8 @@ impl RemoveMod {
};
let activity = AnnouncableActivities::RemoveMod(remove);
let inboxes = vec![removed_mod.get_shared_inbox_or_inbox_url()];
send_to_community_new(activity, &id, actor, community, inboxes, context).await
let inboxes = vec![removed_mod.shared_inbox_or_inbox_url()];
send_to_community(activity, &id, actor, community, inboxes, context).await
}
}

View file

@ -1,15 +1,17 @@
use crate::{
activities::{
community::{announce::AnnouncableActivities, block_user::BlockUserFromCommunity},
community::{
announce::AnnouncableActivities,
block_user::BlockUserFromCommunity,
send_to_community,
},
generate_activity_id,
verify_activity,
verify_mod_action,
verify_person_in_community,
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
ActorType,
};
use activitystreams::{
activity::kind::UndoType,
@ -20,7 +22,7 @@ use activitystreams::{
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
};
use lemmy_db_queries::Bannable;
@ -74,8 +76,8 @@ impl UndoBlockUserFromCommunity {
};
let activity = AnnouncableActivities::UndoBlockUserFromCommunity(undo);
let inboxes = vec![target.get_shared_inbox_or_inbox_url()];
send_to_community_new(activity, &id, actor, community, inboxes, context).await
let inboxes = vec![target.shared_inbox_or_inbox_url()];
send_to_community(activity, &id, actor, community, inboxes, context).await
}
}

View file

@ -1,16 +1,14 @@
use crate::{
activities::{
community::announce::AnnouncableActivities,
community::{announce::AnnouncableActivities, send_to_community},
generate_activity_id,
verify_activity,
verify_mod_action,
verify_person_in_community,
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
objects::{community::Group, ToApub},
ActorType,
};
use activitystreams::{
activity::kind::UpdateType,
@ -21,7 +19,7 @@ use activitystreams::{
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
};
use lemmy_db_queries::Crud;
@ -75,7 +73,7 @@ impl UpdateCommunity {
};
let activity = AnnouncableActivities::UpdateCommunity(Box::new(update));
send_to_community_new(activity, &id, actor, community, vec![], context).await
send_to_community(activity, &id, actor, community, vec![], context).await
}
}

View file

@ -1,6 +1,6 @@
use crate::{
activities::{
community::announce::AnnouncableActivities,
community::{announce::AnnouncableActivities, send_to_community},
deletion::{
receive_delete_action,
verify_delete_activity,
@ -10,10 +10,8 @@ use crate::{
generate_activity_id,
verify_activity,
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
ActorType,
};
use activitystreams::{
activity::kind::DeleteType,
@ -25,7 +23,7 @@ use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
};
use lemmy_db_queries::{
@ -171,7 +169,7 @@ impl Delete {
let delete_id = delete.id.clone();
let activity = AnnouncableActivities::Delete(delete);
send_to_community_new(activity, &delete_id, actor, community, vec![], context).await
send_to_community(activity, &delete_id, actor, community, vec![], context).await
}
}

View file

@ -5,12 +5,11 @@ use crate::{
verify_person_in_community,
},
fetcher::object_id::ObjectId,
ActorType,
};
use diesel::PgConnection;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
traits::{ActivityFields, ApubObject},
traits::{ActivityFields, ActorType, ApubObject},
verify::verify_domains_match,
};
use lemmy_db_queries::source::{comment::Comment_, community::Community_, post::Post_};

View file

@ -1,6 +1,6 @@
use crate::{
activities::{
community::announce::AnnouncableActivities,
community::{announce::AnnouncableActivities, send_to_community},
deletion::{
delete::Delete,
receive_delete_action,
@ -11,10 +11,8 @@ use crate::{
generate_activity_id,
verify_activity,
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
ActorType,
};
use activitystreams::{
activity::kind::UndoType,
@ -26,7 +24,7 @@ use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
};
use lemmy_db_queries::source::{comment::Comment_, community::Community_, post::Post_};
@ -129,7 +127,7 @@ impl UndoDelete {
};
let activity = AnnouncableActivities::UndoDelete(undo);
send_to_community_new(activity, &id, actor, community, vec![], context).await
send_to_community(activity, &id, actor, community, vec![], context).await
}
pub(in crate::activities) async fn receive_undo_remove_action(

View file

@ -5,10 +5,9 @@ use crate::{
verify_activity,
verify_community,
},
activity_queue::send_activity_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
ActorType,
send_lemmy_activity,
};
use activitystreams::{
activity::kind::AcceptType,
@ -19,7 +18,7 @@ use activitystreams::{
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
verify::verify_urls_match,
};
use lemmy_db_queries::Followable;
@ -72,9 +71,10 @@ impl AcceptFollowCommunity {
unparsed: Default::default(),
};
let inbox = vec![person.inbox_url.into()];
send_activity_new(context, &accept, &accept.id, &community, inbox, true).await
send_lemmy_activity(context, &accept, &accept.id, &community, inbox, true).await
}
}
/// Handle accepted follows
#[async_trait::async_trait(?Send)]
impl ActivityHandler for AcceptFollowCommunity {

View file

@ -5,10 +5,9 @@ use crate::{
verify_activity,
verify_person,
},
activity_queue::send_activity_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
ActorType,
send_lemmy_activity,
};
use activitystreams::{
activity::kind::FollowType,
@ -19,7 +18,7 @@ use activitystreams::{
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
verify::verify_urls_match,
};
use lemmy_db_queries::Followable;
@ -84,7 +83,7 @@ impl FollowCommunity {
let follow = FollowCommunity::new(actor, community, context)?;
let inbox = vec![community.inbox_url.clone().into()];
send_activity_new(context, &follow, &follow.id, actor, inbox, true).await
send_lemmy_activity(context, &follow, &follow.id, actor, inbox, true).await
}
}

View file

@ -5,10 +5,9 @@ use crate::{
verify_activity,
verify_person,
},
activity_queue::send_activity_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
ActorType,
send_lemmy_activity,
};
use activitystreams::{
activity::kind::UndoType,
@ -19,7 +18,7 @@ use activitystreams::{
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
verify::verify_urls_match,
};
use lemmy_db_queries::Followable;
@ -66,8 +65,8 @@ impl UndoFollowCommunity {
context: lemmy_context(),
unparsed: Default::default(),
};
let inbox = vec![community.get_shared_inbox_or_inbox_url()];
send_activity_new(context, &undo, &undo.id, actor, inbox, true).await
let inbox = vec![community.shared_inbox_or_inbox_url()];
send_lemmy_activity(context, &undo, &undo.id, actor, inbox, true).await
}
}

View file

@ -22,7 +22,6 @@ pub mod deletion;
pub mod following;
pub mod post;
pub mod private_message;
pub mod send;
pub mod undo_remove;
pub mod voting;

View file

@ -1,24 +1,22 @@
use crate::{
activities::{
community::announce::AnnouncableActivities,
community::{announce::AnnouncableActivities, send_to_community},
generate_activity_id,
verify_activity,
verify_mod_action,
verify_person_in_community,
CreateOrUpdateType,
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
objects::{post::Page, FromApub, ToApub},
ActorType,
};
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
verify::{verify_domains_match, verify_urls_match},
};
@ -74,7 +72,7 @@ impl CreateOrUpdatePost {
};
let activity = AnnouncableActivities::CreateOrUpdatePost(Box::new(create_or_update));
send_to_community_new(activity, &id, actor, &community, vec![], context).await
send_to_community(activity, &id, actor, &community, vec![], context).await
}
}

View file

@ -1,16 +1,15 @@
use crate::{
activities::{generate_activity_id, verify_activity, verify_person, CreateOrUpdateType},
activity_queue::send_activity_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
objects::{private_message::Note, FromApub, ToApub},
ActorType,
send_lemmy_activity,
};
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
verify::verify_domains_match,
};
use lemmy_db_queries::Crud;
@ -59,8 +58,8 @@ impl CreateOrUpdatePrivateMessage {
kind,
unparsed: Default::default(),
};
let inbox = vec![recipient.get_shared_inbox_or_inbox_url()];
send_activity_new(context, &create_or_update, &id, actor, inbox, true).await
let inbox = vec![recipient.shared_inbox_or_inbox_url()];
send_lemmy_activity(context, &create_or_update, &id, actor, inbox, true).await
}
}
#[async_trait::async_trait(?Send)]

View file

@ -1,9 +1,8 @@
use crate::{
activities::{generate_activity_id, verify_activity, verify_person},
activity_queue::send_activity_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
ActorType,
send_lemmy_activity,
};
use activitystreams::{
activity::kind::DeleteType,
@ -14,7 +13,7 @@ use activitystreams::{
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
verify::verify_domains_match,
};
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
@ -69,8 +68,8 @@ impl DeletePrivateMessage {
let recipient_id = pm.recipient_id;
let recipient =
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
let inbox = vec![recipient.get_shared_inbox_or_inbox_url()];
send_activity_new(context, &delete, &delete_id, actor, inbox, true).await
let inbox = vec![recipient.shared_inbox_or_inbox_url()];
send_lemmy_activity(context, &delete, &delete_id, actor, inbox, true).await
}
}

View file

@ -5,10 +5,9 @@ use crate::{
verify_activity,
verify_person,
},
activity_queue::send_activity_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
ActorType,
send_lemmy_activity,
};
use activitystreams::{
activity::kind::UndoType,
@ -19,7 +18,7 @@ use activitystreams::{
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
verify::{verify_domains_match, verify_urls_match},
};
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
@ -68,8 +67,8 @@ impl UndoDeletePrivateMessage {
context: lemmy_context(),
unparsed: Default::default(),
};
let inbox = vec![recipient.get_shared_inbox_or_inbox_url()];
send_activity_new(context, &undo, &id, actor, inbox, true).await
let inbox = vec![recipient.shared_inbox_or_inbox_url()];
send_lemmy_activity(context, &undo, &id, actor, inbox, true).await
}
}

View file

@ -1,66 +0,0 @@
use crate::{check_is_apub_id_valid, ActorType, CommunityType};
use itertools::Itertools;
use lemmy_api_common::blocking;
use lemmy_db_queries::DbPool;
use lemmy_db_schema::source::community::Community;
use lemmy_db_views_actor::community_follower_view::CommunityFollowerView;
use lemmy_utils::{settings::structs::Settings, LemmyError};
use url::Url;
impl ActorType for Community {
fn is_local(&self) -> bool {
self.local
}
fn actor_id(&self) -> Url {
self.actor_id.to_owned().into()
}
fn name(&self) -> String {
self.name.clone()
}
fn public_key(&self) -> Option<String> {
self.public_key.to_owned()
}
fn private_key(&self) -> Option<String> {
self.private_key.to_owned()
}
fn get_shared_inbox_or_inbox_url(&self) -> Url {
self
.shared_inbox_url
.clone()
.unwrap_or_else(|| self.inbox_url.to_owned())
.into()
}
}
#[async_trait::async_trait(?Send)]
impl CommunityType for Community {
fn followers_url(&self) -> Url {
self.followers_url.clone().into()
}
/// For a given community, returns the inboxes of all followers.
async fn get_follower_inboxes(
&self,
pool: &DbPool,
settings: &Settings,
) -> Result<Vec<Url>, LemmyError> {
let id = self.id;
let follows = blocking(pool, move |conn| {
CommunityFollowerView::for_community(conn, id)
})
.await??;
let inboxes = follows
.into_iter()
.filter(|f| !f.follower.local)
.map(|f| f.follower.shared_inbox_url.unwrap_or(f.follower.inbox_url))
.map(|i| i.into_inner())
.unique()
// Don't send to blocked instances
.filter(|inbox| check_is_apub_id_valid(inbox, false, settings).is_ok())
.collect();
Ok(inboxes)
}
}

View file

@ -1,2 +0,0 @@
pub(crate) mod community;
pub(crate) mod person;

View file

@ -1,31 +0,0 @@
use crate::ActorType;
use lemmy_db_schema::source::person::Person;
use url::Url;
impl ActorType for Person {
fn is_local(&self) -> bool {
self.local
}
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()
}
fn private_key(&self) -> Option<String> {
self.private_key.to_owned()
}
fn get_shared_inbox_or_inbox_url(&self) -> Url {
self
.shared_inbox_url
.clone()
.unwrap_or_else(|| self.inbox_url.to_owned())
.into()
}
}

View file

@ -1,6 +1,6 @@
use crate::{
activities::{
community::announce::AnnouncableActivities,
community::{announce::AnnouncableActivities, send_to_community},
generate_activity_id,
verify_activity,
verify_person_in_community,
@ -10,10 +10,8 @@ use crate::{
vote::{Vote, VoteType},
},
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
ActorType,
PostOrComment,
};
use activitystreams::{
@ -25,7 +23,7 @@ use activitystreams::{
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
verify::verify_urls_match,
};
@ -85,7 +83,7 @@ impl UndoVote {
unparsed: Default::default(),
};
let activity = AnnouncableActivities::UndoVote(undo_vote);
send_to_community_new(activity, &id, actor, &community, vec![], context).await
send_to_community(activity, &id, actor, &community, vec![], context).await
}
}

View file

@ -1,15 +1,13 @@
use crate::{
activities::{
community::announce::AnnouncableActivities,
community::{announce::AnnouncableActivities, send_to_community},
generate_activity_id,
verify_activity,
verify_person_in_community,
voting::{vote_comment, vote_post},
},
activity_queue::send_to_community_new,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
ActorType,
PostOrComment,
};
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
@ -17,7 +15,7 @@ use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
traits::{ActivityFields, ActivityHandler},
traits::{ActivityFields, ActivityHandler, ActorType},
values::PublicUrl,
};
use lemmy_db_queries::Crud;
@ -110,7 +108,7 @@ impl Vote {
let vote_id = vote.id.clone();
let activity = AnnouncableActivities::Vote(vote);
send_to_community_new(activity, &vote_id, actor, &community, vec![], context).await
send_to_community(activity, &vote_id, actor, &community, vec![], context).await
}
}

View file

@ -1,2 +0,0 @@
pub mod context;
pub mod signatures;

View file

@ -1,5 +1,6 @@
use crate::{check_is_apub_id_valid, APUB_JSON_CONTENT_TYPE};
use crate::check_is_apub_id_valid;
use anyhow::anyhow;
use lemmy_apub_lib::APUB_JSON_CONTENT_TYPE;
use lemmy_utils::{request::retry, settings::structs::Settings, LemmyError};
use log::info;
use reqwest::Client;

View file

@ -5,8 +5,9 @@ pub mod object_id;
pub mod post_or_comment;
pub mod search;
use crate::{fetcher::object_id::ObjectId, ActorType};
use crate::fetcher::object_id::ObjectId;
use chrono::NaiveDateTime;
use lemmy_apub_lib::traits::ActorType;
use lemmy_db_schema::{
naive_now,
source::{community::Community, person::Person},

View file

@ -1,12 +1,11 @@
use crate::{
fetcher::{deletable_apub_object::DeletableApubObject, should_refetch_actor},
objects::FromApub,
APUB_JSON_CONTENT_TYPE,
};
use anyhow::anyhow;
use diesel::{NotFound, PgConnection};
use lemmy_api_common::blocking;
use lemmy_apub_lib::traits::ApubObject;
use lemmy_apub_lib::{traits::ApubObject, APUB_JSON_CONTENT_TYPE};
use lemmy_db_queries::DbPool;
use lemmy_db_schema::DbUrl;
use lemmy_utils::{request::retry, settings::structs::Settings, LemmyError};

View file

@ -4,8 +4,9 @@ use crate::{
extract_community,
following::{follow::FollowCommunity, undo::UndoFollowCommunity},
},
extensions::context::lemmy_context,
context::lemmy_context,
generate_moderators_url,
generate_outbox_url,
http::{
create_apub_response,
create_apub_tombstone_response,
@ -13,7 +14,6 @@ use crate::{
receive_activity,
},
objects::ToApub,
ActorType,
};
use activitystreams::{
base::{AnyBase, BaseExt},
@ -147,7 +147,7 @@ pub(crate) async fn get_apub_community_outbox(
collection
.set_many_items(activities)
.set_many_contexts(lemmy_context())
.set_id(community.get_outbox_url()?)
.set_id(generate_outbox_url(&community.actor_id)?.into())
.set_total_items(len as u64);
Ok(create_apub_response(&collection))
}

View file

@ -1,13 +1,11 @@
use crate::{
check_is_apub_id_valid,
extensions::signatures::verify_signature,
fetcher::get_or_fetch_and_upsert_actor,
http::{
community::{receive_group_inbox, GroupInboxActivities},
person::{receive_person_inbox, PersonInboxActivities},
},
insert_activity,
APUB_JSON_CONTENT_TYPE,
};
use actix_web::{
body::Body,
@ -22,7 +20,9 @@ use http::StatusCode;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
signatures::verify_signature,
traits::{ActivityFields, ActivityHandler},
APUB_JSON_CONTENT_TYPE,
};
use lemmy_db_queries::{source::activity::Activity_, DbPool};
use lemmy_db_schema::source::activity::Activity;

View file

@ -8,7 +8,8 @@ use crate::{
undo_delete::UndoDeletePrivateMessage,
},
},
extensions::context::lemmy_context,
context::lemmy_context,
generate_outbox_url,
http::{
create_apub_response,
create_apub_tombstone_response,
@ -16,7 +17,6 @@ use crate::{
receive_activity,
},
objects::ToApub,
ActorType,
};
use activitystreams::{
base::BaseExt,
@ -105,7 +105,7 @@ pub(crate) async fn get_apub_person_outbox(
collection
.set_many_items(Vec::<Url>::new())
.set_many_contexts(lemmy_context())
.set_id(person.get_outbox_url()?)
.set_id(generate_outbox_url(&person.actor_id)?.into())
.set_total_items(0_u64);
Ok(create_apub_response(&collection))
}

View file

@ -1,23 +1,21 @@
use crate::{
http::{
comment::get_apub_comment,
community::{
community_inbox,
get_apub_community_followers,
get_apub_community_http,
get_apub_community_inbox,
get_apub_community_moderators,
get_apub_community_outbox,
},
get_activity,
person::{get_apub_person_http, get_apub_person_inbox, get_apub_person_outbox, person_inbox},
post::get_apub_post,
shared_inbox,
use crate::http::{
comment::get_apub_comment,
community::{
community_inbox,
get_apub_community_followers,
get_apub_community_http,
get_apub_community_inbox,
get_apub_community_moderators,
get_apub_community_outbox,
},
APUB_JSON_CONTENT_TYPE,
get_activity,
person::{get_apub_person_http, get_apub_person_inbox, get_apub_person_outbox, person_inbox},
post::get_apub_post,
shared_inbox,
};
use actix_web::*;
use http_signature_normalization_actix::digest::middleware::VerifyDigest;
use lemmy_apub_lib::APUB_JSON_CONTENT_TYPE;
use lemmy_utils::settings::structs::Settings;
use sha2::{Digest, Sha256};

View file

@ -1,17 +1,14 @@
#[macro_use]
extern crate lazy_static;
pub mod activities;
pub mod activity_queue;
pub mod extensions;
mod context;
pub mod fetcher;
pub mod http;
pub mod migrations;
pub mod objects;
use crate::{extensions::signatures::PublicKey, fetcher::post_or_comment::PostOrComment};
use crate::fetcher::post_or_comment::PostOrComment;
use anyhow::{anyhow, Context};
use lemmy_api_common::blocking;
use lemmy_apub_lib::{activity_queue::send_activity, traits::ActorType};
use lemmy_db_queries::{source::activity::Activity_, DbPool};
use lemmy_db_schema::{
source::{activity::Activity, person::Person},
@ -20,12 +17,12 @@ use lemmy_db_schema::{
};
use lemmy_db_views_actor::community_person_ban_view::CommunityPersonBanView;
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
use lemmy_websocket::LemmyContext;
use log::info;
use serde::Serialize;
use std::net::IpAddr;
use url::{ParseError, Url};
static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json";
/// Checks if the ID is allowed for sending or receiving.
///
/// In particular, it checks for:
@ -92,39 +89,6 @@ pub(crate) fn check_is_apub_id_valid(
Ok(())
}
/// Common methods provided by ActivityPub actors (community and person). Not all methods are
/// implemented by all actors.
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>;
fn private_key(&self) -> Option<String>;
fn get_shared_inbox_or_inbox_url(&self) -> Url;
/// Outbox URL is not generally used by Lemmy, so it can be generated on the fly (but only for
/// local actors).
fn get_outbox_url(&self) -> Result<Url, LemmyError> {
/* TODO
if !self.is_local() {
return Err(anyhow!("get_outbox_url() called for remote actor").into());
}
*/
Ok(Url::parse(&format!("{}/outbox", &self.actor_id()))?)
}
fn get_public_key(&self) -> Result<PublicKey, LemmyError> {
Ok(PublicKey {
id: format!("{}#main-key", self.actor_id()),
owner: self.actor_id(),
public_key_pem: self.public_key().context(location_info!())?,
})
}
}
#[async_trait::async_trait(?Send)]
pub trait CommunityType {
fn followers_url(&self) -> Url;
@ -192,6 +156,10 @@ pub fn generate_shared_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, LemmyError>
Ok(Url::parse(&url)?.into())
}
pub fn generate_outbox_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
Ok(Url::parse(&format!("{}/outbox", actor_id))?.into())
}
fn generate_moderators_url(community_id: &DbUrl) -> Result<DbUrl, LemmyError> {
Ok(Url::parse(&format!("{}/moderators", community_id))?.into())
}
@ -254,3 +222,46 @@ async fn check_community_or_site_ban(
Ok(())
}
pub(crate) async fn send_lemmy_activity<T: Serialize>(
context: &LemmyContext,
activity: &T,
activity_id: &Url,
actor: &dyn ActorType,
inboxes: Vec<Url>,
sensitive: bool,
) -> Result<(), LemmyError> {
if !context.settings().federation.enabled || inboxes.is_empty() {
return Ok(());
}
info!("Sending activity {}", activity_id.to_string());
// Don't send anything to ourselves
// TODO: this should be a debug assert
let hostname = context.settings().get_hostname_without_port()?;
let inboxes: Vec<&Url> = inboxes
.iter()
.filter(|i| i.domain().expect("valid inbox url") != hostname)
.collect();
let serialised_activity = serde_json::to_string(&activity)?;
insert_activity(
activity_id,
serialised_activity.clone(),
true,
sensitive,
context.pool(),
)
.await?;
send_activity(
serialised_activity,
actor,
inboxes,
context.client(),
context.activity_queue(),
)
.await
}

View file

@ -1,10 +1,9 @@
use crate::{
activities::verify_person_in_community,
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
migrations::CommentInReplyToMigration,
objects::{create_tombstone, FromApub, Source, ToApub},
ActorType,
PostOrComment,
};
use activitystreams::{
@ -17,6 +16,7 @@ use anyhow::{anyhow, Context};
use chrono::{DateTime, FixedOffset};
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
traits::ActorType,
values::{MediaTypeHtml, MediaTypeMarkdown, PublicUrl},
verify::verify_domains_match,
};

View file

@ -1,9 +1,11 @@
use crate::{
extensions::{context::lemmy_context, signatures::PublicKey},
check_is_apub_id_valid,
context::lemmy_context,
fetcher::community::{fetch_community_outbox, update_community_mods},
generate_moderators_url,
generate_outbox_url,
objects::{create_tombstone, FromApub, ImageObject, Source, ToApub},
ActorType,
CommunityType,
};
use activitystreams::{
actor::{kind::GroupType, Endpoints},
@ -13,8 +15,11 @@ use activitystreams::{
unparsed::Unparsed,
};
use chrono::{DateTime, FixedOffset};
use itertools::Itertools;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
signatures::PublicKey,
traits::ActorType,
values::{MediaTypeHtml, MediaTypeMarkdown},
verify::verify_domains_match,
};
@ -23,6 +28,7 @@ use lemmy_db_schema::{
naive_now,
source::community::{Community, CommunityForm},
};
use lemmy_db_views_actor::community_follower_view::CommunityFollowerView;
use lemmy_utils::{
settings::structs::Settings,
utils::{check_slurs, check_slurs_opt, convert_datetime, markdown_to_html},
@ -143,7 +149,7 @@ impl ToApub for Community {
sensitive: Some(self.nsfw),
moderators: Some(generate_moderators_url(&self.actor_id)?.into()),
inbox: self.inbox_url.clone().into(),
outbox: self.get_outbox_url()?,
outbox: generate_outbox_url(&self.actor_id)?.into(),
followers: self.followers_url.clone().into(),
endpoints: Endpoints {
shared_inbox: self.shared_inbox_url.clone().map(|s| s.into()),
@ -189,3 +195,35 @@ impl FromApub for Community {
Ok(community)
}
}
#[async_trait::async_trait(?Send)]
impl CommunityType for Community {
fn followers_url(&self) -> Url {
self.followers_url.clone().into()
}
/// For a given community, returns the inboxes of all followers.
async fn get_follower_inboxes(
&self,
pool: &DbPool,
settings: &Settings,
) -> Result<Vec<Url>, LemmyError> {
let id = self.id;
let follows = blocking(pool, move |conn| {
CommunityFollowerView::for_community(conn, id)
})
.await??;
let inboxes = follows
.into_iter()
.filter(|f| !f.follower.local)
.map(|f| f.follower.shared_inbox_url.unwrap_or(f.follower.inbox_url))
.map(|i| i.into_inner())
.unique()
// Don't send to blocked instances
.filter(|inbox| check_is_apub_id_valid(inbox, false, settings).is_ok())
.collect();
Ok(inboxes)
}
}

View file

@ -1,8 +1,8 @@
use crate::{
check_is_apub_id_valid,
extensions::{context::lemmy_context, signatures::PublicKey},
context::lemmy_context,
generate_outbox_url,
objects::{FromApub, ImageObject, Source, ToApub},
ActorType,
};
use activitystreams::{
actor::Endpoints,
@ -14,6 +14,8 @@ use activitystreams::{
};
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
signatures::PublicKey,
traits::ActorType,
values::{MediaTypeHtml, MediaTypeMarkdown},
verify::verify_domains_match,
};
@ -113,7 +115,7 @@ impl ToApub for DbPerson {
image,
matrix_user_id: self.matrix_user_id.clone(),
published: convert_datetime(self.published),
outbox: self.get_outbox_url()?,
outbox: generate_outbox_url(&self.actor_id)?.into(),
endpoints: Endpoints {
shared_inbox: self.shared_inbox_url.clone().map(|s| s.into()),
..Default::default()

View file

@ -1,9 +1,8 @@
use crate::{
activities::{extract_community, verify_person_in_community},
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
objects::{create_tombstone, FromApub, ImageObject, Source, ToApub},
ActorType,
};
use activitystreams::{
base::AnyBase,
@ -18,6 +17,7 @@ use activitystreams::{
use chrono::{DateTime, FixedOffset};
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
traits::ActorType,
values::{MediaTypeHtml, MediaTypeMarkdown},
verify::verify_domains_match,
};

View file

@ -1,5 +1,5 @@
use crate::{
extensions::context::lemmy_context,
context::lemmy_context,
fetcher::object_id::ObjectId,
objects::{create_tombstone, FromApub, Source, ToApub},
};

View file

@ -16,3 +16,12 @@ serde_json = { version = "1.0.68", features = ["preserve_order"] }
anyhow = "1.0.44"
reqwest = { version = "0.11.4", features = ["json"] }
log = "0.4.14"
base64 = "0.13.0"
openssl = "0.10.36"
lazy_static = "1.4.0"
http = "0.2.5"
sha2 = "0.9.8"
actix-web = { version = "4.0.0-beta.9", default-features = false }
http-signature-normalization-actix = { version = "0.5.0-beta.10", default-features = false, features = ["server", "sha-2"] }
http-signature-normalization-reqwest = { version = "0.2.0", default-features = false, features = ["sha-2"] }
background-jobs = "0.10.0"

View file

@ -1,10 +1,4 @@
use crate::{
activities::community::announce::{AnnouncableActivities, AnnounceActivity},
extensions::signatures::sign_and_send,
insert_activity,
ActorType,
APUB_JSON_CONTENT_TYPE,
};
use crate::{signatures::sign_and_send, traits::ActorType, APUB_JSON_CONTENT_TYPE};
use anyhow::{anyhow, Context, Error};
use background_jobs::{
create_server,
@ -15,83 +9,31 @@ use background_jobs::{
QueueHandle,
WorkerConfig,
};
use lemmy_db_schema::source::community::Community;
use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext;
use log::{info, warn};
use log::warn;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, env, fmt::Debug, future::Future, pin::Pin};
use url::Url;
pub(crate) async fn send_to_community_new(
activity: AnnouncableActivities,
activity_id: &Url,
pub async fn send_activity(
activity: String,
actor: &dyn ActorType,
community: &Community,
additional_inboxes: Vec<Url>,
context: &LemmyContext,
inboxes: Vec<&Url>,
client: &Client,
activity_queue: &QueueHandle,
) -> Result<(), LemmyError> {
// if this is a local community, we need to do an announce from the community instead
if community.local {
insert_activity(activity_id, activity.clone(), true, false, context.pool()).await?;
AnnounceActivity::send(activity, community, additional_inboxes, context).await?;
} else {
let mut inboxes = additional_inboxes;
inboxes.push(community.get_shared_inbox_or_inbox_url());
send_activity_new(context, &activity, activity_id, actor, inboxes, false).await?;
}
Ok(())
}
pub(crate) async fn send_activity_new<T>(
context: &LemmyContext,
activity: &T,
activity_id: &Url,
actor: &dyn ActorType,
inboxes: Vec<Url>,
sensitive: bool,
) -> Result<(), LemmyError>
where
T: Serialize,
{
if !context.settings().federation.enabled || inboxes.is_empty() {
return Ok(());
}
info!("Sending activity {}", activity_id.to_string());
// Don't send anything to ourselves
// TODO: this should be a debug assert
let hostname = context.settings().get_hostname_without_port()?;
let inboxes: Vec<&Url> = inboxes
.iter()
.filter(|i| i.domain().expect("valid inbox url") != hostname)
.collect();
let serialised_activity = serde_json::to_string(&activity)?;
insert_activity(
activity_id,
serialised_activity.clone(),
true,
sensitive,
context.pool(),
)
.await?;
for i in inboxes {
let message = SendActivityTask {
activity: serialised_activity.to_owned(),
activity: activity.clone(),
inbox: i.to_owned(),
actor_id: actor.actor_id(),
private_key: actor.private_key().context(location_info!())?,
};
if env::var("LEMMY_TEST_SEND_SYNC").is_ok() {
do_send(message, context.client()).await?;
if env::var("APUB_TESTING_SEND_SYNC").is_ok() {
do_send(message, client).await?;
} else {
context.activity_queue.queue::<SendActivityTask>(message)?;
activity_queue.queue::<SendActivityTask>(message)?;
}
}

View file

@ -1,5 +1,12 @@
#[macro_use]
extern crate lazy_static;
pub mod activity_queue;
pub mod data;
pub mod signatures;
pub mod traits;
pub mod values;
pub mod verify;
pub mod webfinger;
pub static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json";

View file

@ -23,7 +23,7 @@ lazy_static! {
/// Creates an HTTP post request to `inbox_url`, with the given `client` and `headers`, and
/// `activity` as request body. The request is signed with `private_key` and then sent.
pub(crate) async fn sign_and_send(
pub async fn sign_and_send(
client: &Client,
headers: BTreeMap<String, String>,
inbox_url: &Url,
@ -62,7 +62,7 @@ pub(crate) async fn sign_and_send(
}
/// Verifies the HTTP signature on an incoming inbox request.
pub(crate) fn verify_signature(request: &HttpRequest, public_key: &str) -> Result<(), LemmyError> {
pub fn verify_signature(request: &HttpRequest, public_key: &str) -> Result<(), LemmyError> {
let verified = CONFIG2
.begin_verify(
request.method(),

View file

@ -1,7 +1,8 @@
use crate::data::Data;
use crate::{data::Data, signatures::PublicKey};
use activitystreams::chrono::NaiveDateTime;
use anyhow::Context;
pub use lemmy_apub_lib_derive::*;
use lemmy_utils::LemmyError;
use lemmy_utils::{location_info, LemmyError};
use url::Url;
pub trait ActivityFields {
@ -36,3 +37,31 @@ pub trait ApubObject {
where
Self: Sized;
}
/// Common methods provided by ActivityPub actors (community and person). Not all methods are
/// implemented by all actors.
pub trait ActorType {
fn is_local(&self) -> bool;
fn actor_id(&self) -> Url;
fn name(&self) -> String;
// TODO: this should not be an option (needs db migration in lemmy)
fn public_key(&self) -> Option<String>;
fn private_key(&self) -> Option<String>;
fn inbox_url(&self) -> Url;
fn shared_inbox_url(&self) -> Option<Url>;
fn shared_inbox_or_inbox_url(&self) -> Url {
self.shared_inbox_url().unwrap_or_else(|| self.inbox_url())
}
fn get_public_key(&self) -> Result<PublicKey, LemmyError> {
Ok(PublicKey {
id: format!("{}#main-key", self.actor_id()),
owner: self.actor_id(),
public_key_pem: self.public_key().context(location_info!())?,
})
}
}

View file

@ -6,7 +6,7 @@ use crate::{
};
use chrono::NaiveDateTime;
use diesel::{ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
use lemmy_apub_lib::traits::ApubObject;
use lemmy_apub_lib::traits::{ActorType, ApubObject};
use lemmy_utils::LemmyError;
use serde::Serialize;
use url::Url;
@ -148,3 +148,29 @@ impl ApubObject for Community {
)
}
}
impl ActorType for Community {
fn is_local(&self) -> bool {
self.local
}
fn actor_id(&self) -> Url {
self.actor_id.to_owned().into()
}
fn name(&self) -> String {
self.name.clone()
}
fn public_key(&self) -> Option<String> {
self.public_key.to_owned()
}
fn private_key(&self) -> Option<String> {
self.private_key.to_owned()
}
fn inbox_url(&self) -> Url {
self.inbox_url.clone().into()
}
fn shared_inbox_url(&self) -> Option<Url> {
self.shared_inbox_url.clone().map(|s| s.into_inner())
}
}

View file

@ -5,7 +5,7 @@ use crate::{
};
use chrono::NaiveDateTime;
use diesel::{ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
use lemmy_apub_lib::traits::ApubObject;
use lemmy_apub_lib::traits::{ActorType, ApubObject};
use lemmy_utils::LemmyError;
use serde::Serialize;
use url::Url;
@ -195,3 +195,31 @@ impl ApubObject for Person {
)
}
}
impl ActorType for Person {
fn is_local(&self) -> bool {
self.local
}
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()
}
fn private_key(&self) -> Option<String> {
self.private_key.to_owned()
}
fn inbox_url(&self) -> Url {
self.inbox_url.clone().into()
}
fn shared_inbox_url(&self) -> Option<Url> {
self.shared_inbox_url.clone().map(|s| s.into_inner())
}
}

View file

@ -40,7 +40,7 @@ services:
volumes:
- ./lemmy_alpha.hjson:/config/config.hjson
environment:
- LEMMY_TEST_SEND_SYNC=1
- APUB_TESTING_SEND_SYNC
- RUST_BACKTRACE=1
- RUST_LOG="warn,lemmy_server=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_queries=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug"
depends_on:
@ -69,7 +69,7 @@ services:
volumes:
- ./lemmy_beta.hjson:/config/config.hjson
environment:
- LEMMY_TEST_SEND_SYNC=1
- APUB_TESTING_SEND_SYNC
- RUST_BACKTRACE=1
- RUST_LOG="warn,lemmy_server=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_queries=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug"
depends_on:
@ -98,7 +98,7 @@ services:
volumes:
- ./lemmy_gamma.hjson:/config/config.hjson
environment:
- LEMMY_TEST_SEND_SYNC=1
- APUB_TESTING_SEND_SYNC
- RUST_BACKTRACE=1
- RUST_LOG="warn,lemmy_server=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_queries=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug"
depends_on:
@ -128,7 +128,7 @@ services:
volumes:
- ./lemmy_delta.hjson:/config/config.hjson
environment:
- LEMMY_TEST_SEND_SYNC=1
- APUB_TESTING_SEND_SYNC
- RUST_BACKTRACE=1
- RUST_LOG="warn,lemmy_server=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_queries=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug"
depends_on:
@ -158,7 +158,7 @@ services:
volumes:
- ./lemmy_epsilon.hjson:/config/config.hjson
environment:
- LEMMY_TEST_SEND_SYNC=1
- APUB_TESTING_SEND_SYNC
- RUST_BACKTRACE=1
- RUST_LOG="warn,lemmy_server=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_queries=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug"
depends_on:

View file

@ -10,7 +10,7 @@ use diesel::{
use lemmy_api::match_websocket_operation;
use lemmy_api_common::blocking;
use lemmy_api_crud::match_websocket_operation_crud;
use lemmy_apub::activity_queue::create_activity_queue;
use lemmy_apub_lib::activity_queue::create_activity_queue;
use lemmy_db_queries::{get_database_url_from_env, source::secret::Secret_};
use lemmy_db_schema::source::secret::Secret;
use lemmy_routes::{feeds, images, nodeinfo, webfinger};