[[package]]
name = "activitypub_federation"
-version = "0.1.0"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78b34a144dc98c419543690aa8f182d8675ebe0610775982b8fdee84a00f70fe"
+checksum = "446e75aefabf78ed9cc7e175f0d90c74f478086fb9bc571a9614fb0b7cbe35d4"
dependencies = [
"activitypub_federation_derive",
"actix-web",
"http",
"http-signature-normalization-actix",
"http-signature-normalization-reqwest",
+ "itertools",
"once_cell",
"openssl",
"reqwest",
[[package]]
name = "activitypub_federation_derive"
-version = "0.1.0"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a2aaf58676b669d3b0dedf6bbb44fa518b5a6657b2959561d77899c668dec2a"
+checksum = "07520b54fc0f22ad30b90399b2a2689c6e5c113df0642ca3fa2f7ee823e54126"
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6"
dependencies = [
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"actix-router",
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
[[package]]
name = "anyhow"
-version = "1.0.56"
+version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
+checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
[[package]]
name = "arrayvec"
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
name = "async-trait"
-version = "0.1.53"
+version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600"
+checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716"
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"proc-macro2 1.0.39",
"quote 1.0.18",
"strsim",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"proc-macro2 1.0.39",
"quote 1.0.18",
"strsim",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"proc-macro2 1.0.39",
"quote 1.0.18",
"strsim",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
dependencies = [
"darling_core 0.12.4",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
dependencies = [
"darling_core 0.13.1",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
dependencies = [
"darling_core 0.14.1",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"darling 0.12.4",
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"darling 0.14.1",
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73"
dependencies = [
"derive_builder_core 0.10.2",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68"
dependencies = [
"derive_builder_core 0.11.2",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"proc-macro2 1.0.39",
"quote 1.0.18",
"rustc_version",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"darling 0.13.1",
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"markup5ever",
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
name = "http"
-version = "0.2.6"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
+checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
dependencies = [
"bytes",
"fnv",
[[package]]
name = "http-signature-normalization-reqwest"
-version = "0.5.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a15d4498e747f1cb1b0114ad651619932eac790815d2dcef0fa89bd016fd991"
+checksum = "630652b9b1f4c18064199c57cce4ad0352d1ec6ec8ad8ffcb0c71dea41ac6b79"
dependencies = [
"base64",
"bytes",
"migrations_internals",
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
[[package]]
name = "once_cell"
-version = "1.10.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
+checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
[[package]]
name = "opaque-debug"
[[package]]
name = "openssl"
-version = "0.10.38"
+version = "0.10.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
+checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
+ "openssl-macros",
"openssl-sys",
]
+[[package]]
+name = "openssl-macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
+dependencies = [
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.96",
+]
+
[[package]]
name = "openssl-probe"
version = "0.1.5"
[[package]]
name = "openssl-sys"
-version = "0.9.72"
+version = "0.9.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
+checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1"
dependencies = [
"autocfg",
"cc",
"pest_meta",
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"proc-macro-error-attr",
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
"version_check",
]
"itertools",
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
[[package]]
name = "serde"
-version = "1.0.136"
+version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
+checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.136"
+version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
+checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
name = "serde_json"
-version = "1.0.79"
+version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
+checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
dependencies = [
"indexmap",
"itoa",
"darling 0.13.1",
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"proc-macro2 1.0.39",
"quote 1.0.18",
"rustversion",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"proc-macro2 1.0.39",
"quote 1.0.18",
"rustversion",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
[[package]]
name = "syn"
-version = "1.0.95"
+version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
+checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf"
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"proc-macro2 1.0.39",
"prost-build",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
[[package]]
name = "tracing"
-version = "0.1.32"
+version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
+checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09"
dependencies = [
"cfg-if",
"log",
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
]
[[package]]
"log",
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
"wasm-bindgen-shared",
]
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
- "syn 1.0.95",
+ "syn 1.0.96",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
lemmy_api_common = { version = "=0.16.5", path = "crates/api_common" }
lemmy_websocket = { version = "=0.16.5", path = "./crates/websocket" }
lemmy_routes = { version = "=0.16.5", path = "./crates/routes" }
-activitypub_federation = "0.1.0"
+activitypub_federation = "0.2.0"
diesel = "1.4.8"
diesel_migrations = "1.4.0"
serde = { version = "1.0.136", features = ["derive"] }
#!/bin/bash
set -e
-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_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"
# see information. If running number is consistently close to the worker_count, you should
# increase it.
worker_count: 64
+ # Use federation debug mode. Allows connecting to http and localhost urls. Also sends outgoing
+ # activities synchronously for easier testing. Do not use in production.
+ debug: false
}
captcha: {
# Whether captcha is required for signup
lemmy_db_views_actor = { version = "=0.16.5", path = "../db_views_actor", features = ["full"] }
lemmy_api_common = { version = "=0.16.5", path = "../api_common", features = ["full"] }
lemmy_websocket = { version = "=0.16.5", path = "../websocket" }
-activitypub_federation = "0.1.0"
+activitypub_federation = "0.2.0"
diesel = "1.4.8"
bcrypt = "0.12.1"
chrono = { version = "0.4.19", features = ["serde"], default-features = false }
lemmy_db_views_actor = { version = "=0.16.5", path = "../db_views_actor", features = ["full"] }
lemmy_api_common = { version = "=0.16.5", path = "../api_common", features = ["full"] }
lemmy_websocket = { version = "=0.16.5", path = "../websocket" }
-activitypub_federation = "0.1.0"
+activitypub_federation = "0.2.0"
bcrypt = "0.12.1"
serde_json = { version = "1.0.79", features = ["preserve_order"] }
serde = { version = "1.0.136", features = ["derive"] }
&context.settings().get_protocol_and_hostname(),
)?;
let community_actor_id_wrapped = ObjectId::<ApubCommunity>::new(community_actor_id.clone());
- let community_dupe = community_actor_id_wrapped
- .dereference_local::<LemmyError>(context)
- .await;
+ let community_dupe = community_actor_id_wrapped.dereference_local(context).await;
if community_dupe.is_ok() {
return Err(LemmyError::from_message("community_already_exists"));
}
lemmy_db_views_actor = { version = "=0.16.5", path = "../db_views_actor", features = ["full"] }
lemmy_api_common = { version = "=0.16.5", path = "../api_common", features = ["full"] }
lemmy_websocket = { version = "=0.16.5", path = "../websocket" }
-activitypub_federation = "0.1.0"
+activitypub_federation = "0.2.0"
diesel = "1.4.8"
activitystreams-kinds = "0.2.1"
chrono = { version = "0.4.19", features = ["serde"], default-features = false }
{
"actor": "http://ds9.lemmy.ml/u/lemmy_alpha",
- "to": "http://enterprise.lemmy.ml/c/main",
+ "to": [
+ "http://enterprise.lemmy.ml/c/main"
+ ],
"object": "http://enterprise.lemmy.ml/post/7",
"summary": "report this post",
"type": "Flag",
{
"id": "http://enterprise.lemmy.ml/activities/create/987d05fa-f637-46d7-85be-13d112bc269f",
"actor": "http://enterprise.lemmy.ml/u/lemmy_beta",
- "to": "http://ds9.lemmy.ml/u/lemmy_alpha",
+ "to": [
+ "http://ds9.lemmy.ml/u/lemmy_alpha"
+ ],
"object": {
"type": "ChatMessage",
"id": "http://enterprise.lemmy.ml/private_message/1",
"attributedTo": "http://enterprise.lemmy.ml/u/lemmy_beta",
- "to": "http://ds9.lemmy.ml/u/lemmy_alpha",
+ "to": [
+ "http://ds9.lemmy.ml/u/lemmy_alpha"
+ ],
"content": "hello",
"mediaType": "text/html",
"source": {
"id": "https://enterprise.lemmy.ml/private_message/1621",
"type": "ChatMessage",
"attributedTo": "https://enterprise.lemmy.ml/u/picard",
- "to": "https://queer.hacktivis.me/users/lanodan",
+ "to": [
+ "https://queer.hacktivis.me/users/lanodan"
+ ],
"content": "<p>Hello hello, testing</p>\n",
"mediaType": "text/html",
"source": {
use crate::{
activities::{
- block::{generate_cc, generate_instance_inboxes, SiteOrCommunity},
+ block::{generate_cc, SiteOrCommunity},
community::{announce::GetCommunity, send_activity_in_community},
generate_activity_id,
send_lemmy_activity,
},
activity_lists::AnnouncableActivities,
local_instance,
- objects::{community::ApubCommunity, person::ApubPerson},
+ objects::{community::ApubCommunity, instance::remote_instance_inboxes, person::ApubPerson},
protocol::activities::block::block_user::BlockUser,
ActorType,
};
use activitypub_federation::{
core::object_id::ObjectId,
data::Data,
- traits::ActivityHandler,
+ traits::{ActivityHandler, Actor},
utils::verify_domains_match,
};
use activitystreams_kinds::{activity::BlockType, public};
context,
)
.await?;
- let block_id = block.id.clone();
match target {
SiteOrCommunity::Site(_) => {
- let inboxes = generate_instance_inboxes(user, context.pool()).await?;
- send_lemmy_activity(context, &block, &block_id, mod_, inboxes, false).await
+ let inboxes = remote_instance_inboxes(context.pool()).await?;
+ send_lemmy_activity(context, block, mod_, inboxes, false).await
}
SiteOrCommunity::Community(c) => {
let activity = AnnouncableActivities::BlockUser(block);
- let inboxes = vec![user.shared_inbox_or_inbox_url()];
- send_activity_in_community(activity, &block_id, mod_, c, inboxes, context).await
+ let inboxes = vec![user.shared_inbox_or_inbox()];
+ send_activity_in_community(activity, mod_, c, inboxes, context).await
}
}
}
verify_is_public(&self.to, &self.cc)?;
match self
.target
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?
{
SiteOrCommunity::Site(site) => {
let expires = self.expires.map(|u| u.naive_local());
let mod_person = self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let blocked_person = self
.object
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let target = self
.target
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
match target {
SiteOrCommunity::Site(_site) => {
) -> Result<ApubCommunity, LemmyError> {
let target = self
.target
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
match target {
SiteOrCommunity::Community(c) => Ok(c),
use crate::{
- objects::{community::ApubCommunity, instance::ApubSite, person::ApubPerson},
+ objects::{community::ApubCommunity, instance::ApubSite},
protocol::objects::{group::Group, instance::Instance},
ActorType,
};
SiteOrCommunity::Community(c) => vec![c.actor_id()],
})
}
-
-async fn generate_instance_inboxes(
- blocked_user: &ApubPerson,
- pool: &DbPool,
-) -> Result<Vec<Url>, LemmyError> {
- let mut inboxes: Vec<Url> = blocking(pool, Site::read_remote_sites)
- .await??
- .into_iter()
- .map(|s| s.inbox_url.into())
- .collect();
- inboxes.push(blocked_user.shared_inbox_or_inbox_url());
- Ok(inboxes)
-}
use crate::{
activities::{
- block::{generate_cc, generate_instance_inboxes, SiteOrCommunity},
+ block::{generate_cc, SiteOrCommunity},
community::{announce::GetCommunity, send_activity_in_community},
generate_activity_id,
send_lemmy_activity,
},
activity_lists::AnnouncableActivities,
local_instance,
- objects::{community::ApubCommunity, person::ApubPerson},
+ objects::{community::ApubCommunity, instance::remote_instance_inboxes, person::ApubPerson},
protocol::activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
ActorType,
};
use activitypub_federation::{
core::object_id::ObjectId,
data::Data,
- traits::ActivityHandler,
+ traits::{ActivityHandler, Actor},
utils::verify_domains_match,
};
use activitystreams_kinds::{activity::UndoType, public};
unparsed: Default::default(),
};
- let inboxes = vec![user.shared_inbox_or_inbox_url()];
+ let mut inboxes = vec![user.shared_inbox_or_inbox()];
match target {
SiteOrCommunity::Site(_) => {
- let inboxes = generate_instance_inboxes(user, context.pool()).await?;
- send_lemmy_activity(context, &undo, &id, mod_, inboxes, false).await
+ inboxes.append(&mut remote_instance_inboxes(context.pool()).await?);
+ send_lemmy_activity(context, undo, mod_, inboxes, false).await
}
SiteOrCommunity::Community(c) => {
let activity = AnnouncableActivities::UndoBlockUser(undo);
- send_activity_in_community(activity, &id, mod_, c, inboxes, context).await
+ send_activity_in_community(activity, mod_, c, inboxes, context).await
}
}
}
let expires = self.object.expires.map(|u| u.naive_local());
let mod_person = self
.actor
- .dereference::<LemmyError>(context, instance, request_counter)
+ .dereference(context, instance, request_counter)
.await?;
let blocked_person = self
.object
.object
- .dereference::<LemmyError>(context, instance, request_counter)
+ .dereference(context, instance, request_counter)
.await?;
match self
.object
.target
- .dereference::<LemmyError>(context, instance, request_counter)
+ .dereference(context, instance, request_counter)
.await?
{
SiteOrCommunity::Site(_site) => {
protocol::activities::community::add_mod::AddMod,
ActorType,
};
-use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
+use activitypub_federation::{
+ core::object_id::ObjectId,
+ data::Data,
+ traits::{ActivityHandler, Actor},
+};
use activitystreams_kinds::{activity::AddType, public};
use lemmy_api_common::utils::blocking;
use lemmy_db_schema::{
};
let activity = AnnouncableActivities::AddMod(add);
- let inboxes = vec![added_mod.shared_inbox_or_inbox_url()];
- send_activity_in_community(activity, &id, actor, community, inboxes, context).await
+ let inboxes = vec![added_mod.shared_inbox_or_inbox()];
+ send_activity_in_community(activity, actor, community, inboxes, context).await
}
}
let community = self.get_community(context, request_counter).await?;
let new_mod = self
.object
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
// If we had to refetch the community while parsing the activity, then the new mod has already
// write mod log
let actor = self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let form = ModAddCommunityForm {
mod_person_id: actor.id,
) -> Result<(), LemmyError> {
let announce = AnnounceActivity::new(object.clone(), community, context)?;
let inboxes = community.get_follower_inboxes(context).await?;
- send_lemmy_activity(
- context,
- &announce,
- &announce.id,
- community,
- inboxes.clone(),
- false,
- )
- .await?;
+ send_lemmy_activity(context, announce, community, inboxes.clone(), false).await?;
// Pleroma and Mastodon can't handle activities like Announce/Create/Page. So for
// compatibility, we also send Announce/Page so that they can follow Lemmy communities.
_ => return Ok(()),
};
let announce_compat = AnnounceActivity::new(object, community, context)?;
- send_lemmy_activity(
- context,
- &announce_compat,
- &announce_compat.id,
- community,
- inboxes,
- false,
- )
- .await?;
+ send_lemmy_activity(context, announce_compat, community, inboxes, false).await?;
Ok(())
}
}
protocol::activities::community::announce::AnnounceActivity,
ActorType,
};
-use activitypub_federation::core::object_id::ObjectId;
+use activitypub_federation::{core::object_id::ObjectId, traits::Actor};
use lemmy_utils::error::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
pub mod update;
#[tracing::instrument(skip_all)]
-pub(crate) async fn send_activity_in_community<T: ActorType>(
+pub(crate) async fn send_activity_in_community<ActorT>(
activity: AnnouncableActivities,
- activity_id: &Url,
- actor: &T,
+ actor: &ActorT,
community: &ApubCommunity,
mut inboxes: Vec<Url>,
context: &LemmyContext,
-) -> Result<(), LemmyError> {
- inboxes.push(community.shared_inbox_or_inbox_url());
- send_lemmy_activity(context, &activity, activity_id, actor, inboxes, false).await?;
+) -> Result<(), LemmyError>
+where
+ ActorT: Actor + ActorType,
+{
+ inboxes.push(community.shared_inbox_or_inbox());
+ send_lemmy_activity(context, activity.clone(), actor, inboxes, false).await?;
if community.local {
AnnounceActivity::send(activity, community, context).await?;
) -> Result<ApubCommunity, LemmyError> {
let community_id = Url::parse(&moderators.to_string().replace("/moderators", ""))?;
ObjectId::new(community_id)
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await
}
protocol::activities::community::remove_mod::RemoveMod,
ActorType,
};
-use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
+use activitypub_federation::{
+ core::object_id::ObjectId,
+ data::Data,
+ traits::{ActivityHandler, Actor},
+};
use activitystreams_kinds::{activity::RemoveType, public};
use lemmy_api_common::utils::blocking;
use lemmy_db_schema::{
};
let activity = AnnouncableActivities::RemoveMod(remove);
- let inboxes = vec![removed_mod.shared_inbox_or_inbox_url()];
- send_activity_in_community(activity, &id, actor, community, inboxes, context).await
+ let inboxes = vec![removed_mod.shared_inbox_or_inbox()];
+ send_activity_in_community(activity, actor, community, inboxes, context).await
}
}
let community = self.get_community(context, request_counter).await?;
let remove_mod = self
.object
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let form = CommunityModeratorForm {
// write mod log
let actor = self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let form = ModAddCommunityForm {
mod_person_id: actor.id,
ActorType,
PostOrComment,
};
-use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
+use activitypub_federation::{
+ core::object_id::ObjectId,
+ data::Data,
+ traits::{ActivityHandler, Actor},
+};
use activitystreams_kinds::activity::FlagType;
use lemmy_api_common::{comment::CommentReportResponse, post::PostReportResponse, utils::blocking};
use lemmy_db_schema::{
reason: String,
context: &LemmyContext,
) -> Result<(), LemmyError> {
- let community = community_id
- .dereference_local::<LemmyError>(context)
- .await?;
+ let community = community_id.dereference_local(context).await?;
let kind = FlagType::Flag;
let id = generate_activity_id(
kind.clone(),
)?;
let report = Report {
actor: ObjectId::new(actor.actor_id()),
- to: ObjectId::new(community.actor_id()),
+ to: [ObjectId::new(community.actor_id())],
object: object_id,
summary: reason,
kind,
id: id.clone(),
unparsed: Default::default(),
};
- send_lemmy_activity(
- context,
- &report,
- &id,
- actor,
- vec![community.shared_inbox_or_inbox_url()],
- false,
- )
- .await
+
+ let inbox = vec![community.shared_inbox_or_inbox()];
+ send_lemmy_activity(context, report, actor, inbox, false).await
}
}
context: &Data<LemmyContext>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- let community = self
- .to
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ let community = self.to[0]
+ .dereference(context, local_instance(context), request_counter)
.await?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
Ok(())
) -> Result<(), LemmyError> {
let actor = self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
match self
.object
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?
{
PostOrComment::Post(post) => {
};
let activity = AnnouncableActivities::UpdateCommunity(update);
- send_activity_in_community(activity, &id, actor, &community, vec![], context).await
+ send_activity_in_community(activity, actor, &community, vec![], context).await
}
}
) -> Result<ApubCommunity, LemmyError> {
let cid = ObjectId::new(self.object.id.clone());
cid
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await
}
}
use activitypub_federation::{
core::object_id::ObjectId,
data::Data,
- traits::{ActivityHandler, ApubObject},
+ traits::{ActivityHandler, Actor, ApubObject},
utils::verify_domains_match,
};
use activitystreams_kinds::public;
let mut inboxes = vec![];
for t in tagged_users {
let person = t
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
- inboxes.push(person.shared_inbox_or_inbox_url());
+ inboxes.push(person.shared_inbox_or_inbox());
}
let activity = AnnouncableActivities::CreateOrUpdateComment(create_or_update);
- send_activity_in_community(activity, &id, actor, &community, inboxes, context).await
+ send_activity_in_community(activity, actor, &community, inboxes, context).await
}
}
let post_id = comment.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
let actor = actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
// Note:
.into();
let create_or_update = CreateOrUpdatePost::new(post, actor, &community, kind, context).await?;
- let id = create_or_update.id.clone();
let activity = AnnouncableActivities::CreateOrUpdatePost(Box::new(create_or_update));
- send_activity_in_community(activity, &id, actor, &community, vec![], context).await
+ send_activity_in_community(activity, actor, &community, vec![], context).await
}
}
use activitypub_federation::{
core::object_id::ObjectId,
data::Data,
- traits::{ActivityHandler, ApubObject},
+ traits::{ActivityHandler, Actor, ApubObject},
utils::verify_domains_match,
};
use lemmy_api_common::utils::blocking;
let create_or_update = CreateOrUpdatePrivateMessage {
id: id.clone(),
actor: ObjectId::new(actor.actor_id()),
- to: ObjectId::new(recipient.actor_id()),
+ to: [ObjectId::new(recipient.actor_id())],
object: private_message.into_apub(context).await?,
kind,
unparsed: Default::default(),
};
- let inbox = vec![recipient.shared_inbox_or_inbox_url()];
- send_lemmy_activity(context, &create_or_update, &id, actor, inbox, true).await
+ let inbox = vec![recipient.shared_inbox_or_inbox()];
+ send_lemmy_activity(context, create_or_update, actor, inbox, true).await
}
}
) -> Result<(), LemmyError> {
verify_person(&self.actor, context, request_counter).await?;
verify_domains_match(self.actor.inner(), self.object.id.inner())?;
- verify_domains_match(self.to.inner(), self.object.to.inner())?;
+ verify_domains_match(self.to[0].inner(), self.object.to[0].inner())?;
ApubPrivateMessage::verify(&self.object, self.actor.inner(), context, request_counter).await?;
Ok(())
}
ModRemovePost,
ModRemovePostForm,
},
- person::Person,
post::Post,
},
traits::Crud,
receive_remove_action(
&self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?,
self.object.id(),
reason,
impl Delete {
pub(in crate::activities::deletion) fn new(
- actor: &Person,
+ actor: &ApubPerson,
object: DeletableObjects,
to: Url,
community: Option<&Community>,
use crate::{
activities::{generate_activity_id, send_lemmy_activity, verify_is_public, verify_person},
local_instance,
- objects::person::ApubPerson,
+ objects::{instance::remote_instance_inboxes, person::ApubPerson},
protocol::activities::deletion::delete_user::DeleteUser,
};
use activitypub_federation::{
utils::verify_urls_match,
};
use activitystreams_kinds::{activity::DeleteType, public};
-use lemmy_api_common::utils::{blocking, delete_user_account};
-use lemmy_db_schema::source::site::Site;
+use lemmy_api_common::utils::delete_user_account;
use lemmy_utils::error::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
) -> Result<(), LemmyError> {
let actor = self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
delete_user_account(actor.id, context.pool()).await?;
Ok(())
cc: vec![],
};
- let remote_sites = blocking(context.pool(), Site::read_remote_sites).await??;
- let inboxes = remote_sites
- .into_iter()
- .map(|s| s.inbox_url.into())
- .collect();
- send_lemmy_activity(context, &delete, &id, actor, inboxes, true).await?;
+ let inboxes = remote_instance_inboxes(context.pool()).await?;
+ send_lemmy_activity(context, delete, actor, inboxes, true).await?;
Ok(())
}
}
};
use activitypub_federation::{
core::object_id::ObjectId,
- traits::ApubObject,
+ traits::{Actor, ApubObject},
utils::verify_domains_match,
};
use activitystreams_kinds::public;
deleted: bool,
context: &LemmyContext,
) -> Result<(), LemmyError> {
- let (id, activity) = if deleted {
+ let actor = ApubPerson::from(actor);
+ let activity = if deleted {
let delete = Delete::new(&actor, object, public(), Some(&community), reason, context)?;
- (delete.id.clone(), AnnouncableActivities::Delete(delete))
+ AnnouncableActivities::Delete(delete)
} else {
let undo = UndoDelete::new(&actor, object, public(), Some(&community), reason, context)?;
- (undo.id.clone(), AnnouncableActivities::UndoDelete(undo))
+ AnnouncableActivities::UndoDelete(undo)
};
- send_activity_in_community(
- activity,
- &id,
- &ApubPerson::from(actor),
- &community.into(),
- vec![],
- context,
- )
- .await
+ send_activity_in_community(activity, &actor, &community.into(), vec![], context).await
}
#[tracing::instrument(skip_all)]
.into();
let deletable = DeletableObjects::PrivateMessage(Box::new(pm.into()));
- let inbox = vec![recipient.shared_inbox_or_inbox_url()];
+ let inbox = vec![recipient.shared_inbox_or_inbox()];
if deleted {
let delete = Delete::new(actor, deletable, recipient.actor_id(), None, None, context)?;
- let id = delete.id.clone();
- send_lemmy_activity(context, &delete, &id, actor, inbox, true).await?;
+ send_lemmy_activity(context, delete, actor, inbox, true).await?;
} else {
let undo = UndoDelete::new(actor, deletable, recipient.actor_id(), None, None, context)?;
- let id = undo.id.clone();
- send_lemmy_activity(context, &undo, &id, actor, inbox, true).await?;
+ send_lemmy_activity(context, undo, actor, inbox, true).await?;
};
Ok(())
}
DeletableObjects::Community(community) => {
if community.local {
let mod_: Person = actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?
.deref()
.clone();
ModRemovePost,
ModRemovePostForm,
},
- person::Person,
post::Post,
},
traits::Crud,
UndoDelete::receive_undo_remove_action(
&self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?,
self.object.object.id(),
context,
impl UndoDelete {
#[tracing::instrument(skip_all)]
pub(in crate::activities::deletion) fn new(
- actor: &Person,
+ actor: &ApubPerson,
object: DeletableObjects,
to: Url,
community: Option<&Community>,
use activitypub_federation::{
core::object_id::ObjectId,
data::Data,
- traits::ActivityHandler,
+ traits::{ActivityHandler, Actor},
utils::verify_urls_match,
};
use activitystreams_kinds::activity::AcceptType;
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- let community = follow
- .object
- .dereference_local::<LemmyError>(context)
- .await?;
+ let community = follow.object.dereference_local(context).await?;
let person = follow
.actor
.clone()
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let accept = AcceptFollowCommunity {
actor: ObjectId::new(community.actor_id()),
)?,
unparsed: Default::default(),
};
- let inbox = vec![person.inbox_url()];
- send_lemmy_activity(context, &accept, &accept.id, &community, inbox, true).await
+ let inbox = vec![person.shared_inbox_or_inbox()];
+ send_lemmy_activity(context, accept, &community, inbox, true).await
}
}
) -> Result<(), LemmyError> {
let person = self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let community = self
.object
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
// This will throw an error if no follow was requested
blocking(context.pool(), move |conn| {
protocol::activities::following::{accept::AcceptFollowCommunity, follow::FollowCommunity},
ActorType,
};
-use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
+use activitypub_federation::{
+ core::object_id::ObjectId,
+ data::Data,
+ traits::{ActivityHandler, Actor},
+};
use activitystreams_kinds::activity::FollowType;
use lemmy_api_common::utils::blocking;
use lemmy_db_schema::{
.await?;
let follow = FollowCommunity::new(actor, community, context)?;
- let inbox = vec![community.inbox_url.clone().into()];
- send_lemmy_activity(context, &follow, &follow.id, actor, inbox, true).await
+ let inbox = vec![community.shared_inbox_or_inbox()];
+ send_lemmy_activity(context, follow, actor, inbox, true).await
}
}
verify_person(&self.actor, context, request_counter).await?;
let community = self
.object
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
Ok(())
) -> Result<(), LemmyError> {
let person = self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let community = self
.object
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let community_follower_form = CommunityFollowerForm {
community_id: community.id,
use activitypub_federation::{
core::object_id::ObjectId,
data::Data,
- traits::ActivityHandler,
+ traits::{ActivityHandler, Actor},
utils::verify_urls_match,
};
use activitystreams_kinds::activity::UndoType;
)?,
unparsed: Default::default(),
};
- let inbox = vec![community.shared_inbox_or_inbox_url()];
- send_lemmy_activity(context, &undo, &undo.id, actor, inbox, true).await
+ let inbox = vec![community.shared_inbox_or_inbox()];
+ send_lemmy_activity(context, undo, actor, inbox, true).await
}
}
) -> Result<(), LemmyError> {
let person = self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let community = self
.object
.object
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let community_follower_form = CommunityFollowerForm {
CONTEXT,
};
use activitypub_federation::{
- core::{activity_queue::SendActivity, object_id::ObjectId},
+ core::{activity_queue::send_activity, object_id::ObjectId},
deser::context::WithContext,
+ traits::{ActivityHandler, Actor},
};
use activitystreams_kinds::public;
use anyhow::anyhow;
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let person = person_id
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
if person.banned {
let err = anyhow!("Person {} is banned", person_id);
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let person = person_id
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
if person.banned {
return Err(LemmyError::from_message("Person is banned from site"));
) -> Result<(), LemmyError> {
if community.local {
let actor = mod_id
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
// Note: this will also return true for admins in addition to mods, but as we dont know about
}
#[tracing::instrument(skip_all)]
-async fn send_lemmy_activity<T: Serialize>(
+async fn send_lemmy_activity<Activity, ActorT>(
context: &LemmyContext,
- activity: &T,
- activity_id: &Url,
- actor: &dyn ActorType,
- inboxes: Vec<Url>,
+ activity: Activity,
+ actor: &ActorT,
+ inbox: Vec<Url>,
sensitive: bool,
-) -> Result<(), LemmyError> {
- if !context.settings().federation.enabled || inboxes.is_empty() {
- return Ok(());
- }
+) -> Result<(), LemmyError>
+where
+ Activity: ActivityHandler + Serialize,
+ ActorT: Actor + ActorType,
+ Activity: ActivityHandler<Error = LemmyError>,
+{
+ info!("Sending activity {}", activity.id().to_string());
let activity = WithContext::new(activity, CONTEXT.deref().clone());
- 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
- .into_iter()
- .filter(|i| i.domain().expect("valid inbox url") != hostname)
- .collect();
-
- let serialised_activity = serde_json::to_string(&activity)?;
-
let object_value = serde_json::to_value(&activity)?;
- insert_activity(activity_id, object_value, true, sensitive, context.pool()).await?;
-
- SendActivity {
- activity_id: activity_id.clone(),
- actor_public_key: actor.get_public_key(),
- actor_private_key: actor.private_key().expect("actor has private key"),
- inboxes,
- activity: serialised_activity,
- }
- .send(local_instance(context))
+ insert_activity(activity.id(), object_value, true, sensitive, context.pool()).await?;
+
+ send_activity(
+ activity,
+ actor.get_public_key(),
+ actor.private_key().expect("actor has private key"),
+ inbox,
+ local_instance(context),
+ )
.await?;
Ok(())
unparsed: Default::default(),
};
let activity = AnnouncableActivities::UndoVote(undo_vote);
- send_activity_in_community(activity, &id, actor, &community, vec![], context).await
+ send_activity_in_community(activity, actor, &community, vec![], context).await
}
}
) -> Result<(), LemmyError> {
let actor = self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let object = self
.object
.object
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
match object {
PostOrComment::Post(p) => undo_vote_post(actor, &p, context).await,
.await??
.into();
let vote = Vote::new(object, actor, &community, kind, context)?;
- let vote_id = vote.id.clone();
let activity = AnnouncableActivities::Vote(vote);
- send_activity_in_community(activity, &vote_id, actor, &community, vec![], context).await
+ send_activity_in_community(activity, actor, &community, vec![], context).await
}
}
) -> Result<(), LemmyError> {
let actor = self
.actor
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let object = self
.object
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
match object {
PostOrComment::Post(p) => vote_post(&self.kind, actor, &p, context).await,
) -> Result<ApubCommunity, LemmyError> {
let object = self
.object
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let cid = match object {
PostOrComment::Post(p) => p.community_id,
for mod_id in apub.ordered_items {
let mod_id = ObjectId::new(mod_id);
let mod_user: ApubPerson = mod_id
- .dereference::<LemmyError>(&data.1, local_instance(&data.1), request_counter)
+ .dereference(&data.1, local_instance(&data.1), request_counter)
.await?;
if !current_moderators
match Url::parse(query) {
Ok(url) => {
ObjectId::new(url)
- .dereference::<LemmyError>(context, instance, request_counter)
+ .dereference(context, instance, request_counter)
.await
}
Err(_) => {
webfinger_resolve_actor::<ApubPerson>(identifier, context, request_counter).await?;
Ok(SearchableObjects::Person(
ObjectId::new(id)
- .dereference::<LemmyError>(context, instance, request_counter)
+ .dereference(context, instance, request_counter)
.await?,
))
}
webfinger_resolve_actor::<ApubCommunity>(identifier, context, request_counter).await?;
Ok(SearchableObjects::Community(
ObjectId::new(id)
- .dereference::<LemmyError>(context, instance, request_counter)
+ .dereference(context, instance, request_counter)
.await?,
))
}
objects::{community::ApubCommunity, person::ApubPerson},
protocol::objects::{group::Group, person::Person},
};
-use activitypub_federation::{core::inbox::ActorPublicKey, traits::ApubObject};
+use activitypub_federation::traits::{Actor, ApubObject};
use chrono::NaiveDateTime;
use lemmy_utils::error::LemmyError;
use lemmy_websocket::LemmyContext;
}
}
-impl ActorPublicKey for UserOrCommunity {
+impl Actor for UserOrCommunity {
fn public_key(&self) -> &str {
match self {
UserOrCommunity::User(p) => p.public_key(),
UserOrCommunity::Community(p) => p.public_key(),
}
}
+
+ fn inbox(&self) -> Url {
+ unimplemented!()
+ }
}
.collect();
for l in links {
let object = ObjectId::<Kind>::new(l)
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await;
if object.is_ok() {
return object.map(|o| o.actor_id().into());
let id = ObjectId::new(generate_outbox_url(&community.actor_id)?);
let outbox_data = CommunityContext(community.into(), context.get_ref().clone());
let outbox: ApubCommunityOutbox = id
- .dereference::<LemmyError>(&outbox_data, local_instance(&context), &mut 0)
+ .dereference(&outbox_data, local_instance(&context), &mut 0)
.await?;
Ok(create_apub_response(&outbox.into_apub(&outbox_data).await?))
}
let id = ObjectId::new(generate_outbox_url(&community.actor_id)?);
let outbox_data = CommunityContext(community, context.get_ref().clone());
let moderators: ApubCommunityModerators = id
- .dereference::<LemmyError>(&outbox_data, local_instance(&context), &mut 0)
+ .dereference(&outbox_data, local_instance(&context), &mut 0)
.await?;
Ok(create_apub_response(
&moderators.into_apub(&outbox_data).await?,
CONTEXT,
};
use activitypub_federation::{
- core::inbox::{receive_activity, ActorPublicKey},
+ core::inbox::receive_activity,
data::Data,
deser::context::WithContext,
- traits::{ActivityHandler, ApubObject},
+ traits::{ActivityHandler, Actor, ApubObject},
APUB_JSON_CONTENT_TYPE,
};
use actix_web::{web, HttpRequest, HttpResponse};
receive_lemmy_activity::<SharedInboxActivities, UserOrCommunity>(request, payload, context).await
}
-pub async fn receive_lemmy_activity<Activity, Actor>(
+pub async fn receive_lemmy_activity<Activity, ActorT>(
request: HttpRequest,
payload: String,
context: web::Data<LemmyContext>,
+ DeserializeOwned
+ Send
+ 'static,
- Actor: ApubObject<DataType = LemmyContext, Error = LemmyError> + ActorPublicKey + Send + 'static,
- for<'de2> <Actor as ApubObject>::ApubType: serde::Deserialize<'de2>,
+ ActorT: ApubObject<DataType = LemmyContext, Error = LemmyError> + Actor + Send + 'static,
+ for<'de2> <ActorT as ApubObject>::ApubType: serde::Deserialize<'de2>,
{
let activity_value: Value = serde_json::from_str(&payload)?;
let activity: Activity = serde_json::from_value(activity_value.clone())?;
static DATA: OnceCell<Data<LemmyContext>> = OnceCell::new();
let data = DATA.get_or_init(|| Data::new(context.get_ref().clone()));
- receive_activity::<Activity, Actor, LemmyContext, LemmyError>(
+ receive_activity::<Activity, ActorT, LemmyContext>(
request,
activity,
local_instance(&context),
use crate::fetcher::post_or_comment::PostOrComment;
use activitypub_federation::{
- core::{inbox::ActorPublicKey, signatures::PublicKey},
+ core::signatures::PublicKey,
+ traits::{Actor, ApubObject},
InstanceSettingsBuilder,
LocalInstance,
};
use lemmy_utils::{error::LemmyError, location_info, settings::structs::Settings};
use lemmy_websocket::LemmyContext;
use once_cell::sync::{Lazy, OnceCell};
-use std::env;
use url::{ParseError, Url};
pub mod activities;
let settings = InstanceSettingsBuilder::default()
.http_fetch_retry_limit(context.settings().http_fetch_retry_limit)
.worker_count(context.settings().federation.worker_count)
- .testing_send_sync(env::var("APUB_TESTING_SEND_SYNC").is_ok())
+ .debug(context.settings().federation.debug)
.verify_url_function(|url| check_apub_id_valid(url, &Settings::get()))
.build()
.expect("configure federation");
/// Common methods provided by ActivityPub actors (community and person). Not all methods are
/// implemented by all actors.
-pub trait ActorType: ActorPublicKey {
+pub trait ActorType: Actor + ApubObject {
fn actor_id(&self) -> Url;
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) -> PublicKey {
PublicKey::new_main_key(self.actor_id(), self.public_key().to_string())
}
) -> Result<ApubComment, LemmyError> {
let creator = note
.attributed_to
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let (post, parent_comment_id) = note.get_parents(context, request_counter).await?;
ActorType,
};
use activitypub_federation::{
- core::{inbox::ActorPublicKey, object_id::ObjectId},
- traits::ApubObject,
+ core::object_id::ObjectId,
+ traits::{Actor, ApubObject},
};
use activitystreams_kinds::actor::GroupType;
use chrono::NaiveDateTime;
group
.outbox
- .dereference::<LemmyError>(&outbox_data, local_instance(context), request_counter)
+ .dereference(&outbox_data, local_instance(context), request_counter)
.await
.map_err(|e| debug!("{}", e))
.ok();
if let Some(moderators) = &group.moderators {
moderators
- .dereference::<LemmyError>(&outbox_data, local_instance(context), request_counter)
+ .dereference(&outbox_data, local_instance(context), request_counter)
.await
.map_err(|e| debug!("{}", e))
.ok();
}
}
-impl ActorType for ApubCommunity {
- fn actor_id(&self) -> Url {
- self.actor_id.to_owned().into()
- }
- fn private_key(&self) -> Option<String> {
- self.private_key.to_owned()
+impl Actor for ApubCommunity {
+ fn public_key(&self) -> &str {
+ &self.public_key
}
- fn inbox_url(&self) -> Url {
+ fn inbox(&self) -> Url {
self.inbox_url.clone().into()
}
- fn shared_inbox_url(&self) -> Option<Url> {
+ fn shared_inbox(&self) -> Option<Url> {
self.shared_inbox_url.clone().map(|s| s.into())
}
}
-impl ActorPublicKey for ApubCommunity {
- fn public_key(&self) -> &str {
- &self.public_key
+impl ActorType for ApubCommunity {
+ fn actor_id(&self) -> Url {
+ self.actor_id.to_owned().into()
+ }
+ fn private_key(&self) -> Option<String> {
+ self.private_key.to_owned()
}
}
ActorType,
};
use activitypub_federation::{
- core::{inbox::ActorPublicKey, object_id::ObjectId},
+ core::object_id::ObjectId,
deser::values::MediaTypeHtml,
- traits::ApubObject,
+ traits::{Actor, ApubObject},
utils::verify_domains_match,
};
use chrono::NaiveDateTime;
use lemmy_api_common::utils::blocking;
use lemmy_db_schema::{
source::site::{Site, SiteForm},
- utils::naive_now,
+ utils::{naive_now, DbPool},
};
use lemmy_utils::{
error::LemmyError,
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> {
- None
- }
}
-impl ActorPublicKey for ApubSite {
+impl Actor for ApubSite {
fn public_key(&self) -> &str {
&self.public_key
}
+
+ fn inbox(&self) -> Url {
+ self.inbox_url.clone().into()
+ }
}
/// Instance actor is at the root path, so we simply need to clear the path and other unnecessary
// try to fetch the instance actor (to make things like instance rules available)
let instance_id = instance_actor_id_from_url(object_id);
let site = ObjectId::<ApubSite>::new(instance_id.clone())
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await;
if let Err(e) = site {
debug!("Failed to dereference site for {}: {}", instance_id, e);
}
}
+pub(crate) async fn remote_instance_inboxes(pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
+ Ok(
+ blocking(pool, Site::read_remote_sites)
+ .await??
+ .into_iter()
+ .map(|s| ApubSite::from(s).shared_inbox_or_inbox())
+ .collect(),
+ )
+}
+
#[cfg(test)]
pub(crate) mod tests {
use super::*;
ActorType,
};
use activitypub_federation::{
- core::{inbox::ActorPublicKey, object_id::ObjectId},
- traits::ApubObject,
+ core::object_id::ObjectId,
+ traits::{Actor, ApubObject},
utils::verify_domains_match,
};
use chrono::NaiveDateTime;
fn private_key(&self) -> Option<String> {
self.private_key.to_owned()
}
+}
- fn inbox_url(&self) -> Url {
- self.inbox_url.clone().into()
+impl Actor for ApubPerson {
+ fn public_key(&self) -> &str {
+ &self.public_key
}
- fn shared_inbox_url(&self) -> Option<Url> {
- self.shared_inbox_url.clone().map(|s| s.into())
+ fn inbox(&self) -> Url {
+ self.inbox_url.clone().into()
}
-}
-impl ActorPublicKey for ApubPerson {
- fn public_key(&self) -> &str {
- &self.public_key
+ fn shared_inbox(&self) -> Option<Url> {
+ self.shared_inbox_url.clone().map(|s| s.into())
}
}
) -> Result<ApubPost, LemmyError> {
let creator = page
.creator()?
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
let community = page.extract_community(context, request_counter).await?;
// read existing, local post if any (for generating mod log)
let old_post = ObjectId::<ApubPost>::new(page.id.clone())
- .dereference_local::<LemmyError>(context)
+ .dereference_local(context)
.await;
let post = blocking(context.pool(), move |conn| Post::upsert(conn, &form)).await??;
r#type: ChatMessageType::ChatMessage,
id: ObjectId::new(self.ap_id.clone()),
attributed_to: ObjectId::new(creator.actor_id),
- to: ObjectId::new(recipient.actor_id),
+ to: [ObjectId::new(recipient.actor_id)],
content: markdown_to_html(&self.content),
media_type: Some(MediaTypeHtml::Html),
source: Some(Source::new(self.content.clone())),
check_apub_id_valid_with_strictness(note.id.inner(), false, &Settings::get())?;
let person = note
.attributed_to
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
if person.banned {
return Err(LemmyError::from_message("Person is banned from site"));
) -> Result<ApubPrivateMessage, LemmyError> {
let creator = note
.attributed_to
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?;
- let recipient = note
- .to
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ let recipient = note.to[0]
+ .dereference(context, local_instance(context), request_counter)
.await?;
let form = PrivateMessageForm {
pub struct Report {
pub(crate) actor: ObjectId<ApubPerson>,
#[serde(deserialize_with = "deserialize_one")]
- pub(crate) to: ObjectId<ApubCommunity>,
+ pub(crate) to: [ObjectId<ApubCommunity>; 1],
pub(crate) object: ObjectId<PostOrComment>,
pub(crate) summary: String,
#[serde(rename = "type")]
pub(crate) id: Url,
pub(crate) actor: ObjectId<ApubPerson>,
#[serde(deserialize_with = "deserialize_one")]
- pub(crate) to: ObjectId<ApubPerson>,
+ pub(crate) to: [ObjectId<ApubPerson>; 1],
pub(crate) object: ChatMessage,
#[serde(rename = "type")]
pub(crate) kind: CreateOrUpdateType,
pub(crate) id: ObjectId<ApubPrivateMessage>,
pub(crate) attributed_to: ObjectId<ApubPerson>,
#[serde(deserialize_with = "deserialize_one")]
- pub(crate) to: ObjectId<ApubPerson>,
+ pub(crate) to: [ObjectId<ApubPerson>; 1],
pub(crate) content: String,
pub(crate) media_type: Option<MediaTypeHtml>,
let parent = Box::pin(
self
.in_reply_to
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await?,
);
match parent.deref() {
/// Both stickied and locked need to be false on a newly created post (verified in [[CreatePost]].
pub(crate) async fn is_mod_action(&self, context: &LemmyContext) -> Result<bool, LemmyError> {
let old_post = ObjectId::<ApubPost>::new(self.id.clone())
- .dereference_local::<LemmyError>(context)
+ .dereference_local(context)
.await;
let stickied_changed = Page::is_stickied_changed(&old_post, &self.stickied);
if let Some(cid) = iter.next() {
let cid = ObjectId::new(cid.clone());
if let Ok(c) = cid
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await
{
break Ok(c);
.find(|a| a.kind == PersonOrGroupType::Group)
.map(|a| ObjectId::<ApubCommunity>::new(a.id.clone().into_inner()))
.ok_or_else(|| LemmyError::from_message("page does not specify group"))?
- .dereference::<LemmyError>(context, local_instance(context), request_counter)
+ .dereference(context, local_instance(context), request_counter)
.await
}
}
strum = "0.24.0"
strum_macros = "0.24.0"
serde_json = { version = "1.0.79", features = ["preserve_order"], optional = true }
-activitypub_federation = { version = "0.1.0", optional = true }
+activitypub_federation = { version = "0.2.0", optional = true }
lemmy_utils = { version = "=0.16.5", path = "../utils", optional = true }
bcrypt = { version = "0.12.1", optional = true }
diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"], optional = true }
/// increase it.
#[default(64)]
pub worker_count: u64,
+ /// Use federation debug mode. Allows connecting to http and localhost urls. Also sends outgoing
+ /// activities synchronously for easier testing. Do not use in production.
+ #[default(false)]
+ pub debug: bool,
}
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)]
volumes:
- ./lemmy_alpha.hjson:/config/config.hjson
environment:
- - 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_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:
volumes:
- ./lemmy_beta.hjson:/config/config.hjson
environment:
- - 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_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:
volumes:
- ./lemmy_gamma.hjson:/config/config.hjson
environment:
- - 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_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:
volumes:
- ./lemmy_delta.hjson:/config/config.hjson
environment:
- - 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_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:
volumes:
- ./lemmy_epsilon.hjson:/config/config.hjson
environment:
- - 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_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:
federation: {
enabled: true
allowed_instances: ["lemmy-beta","lemmy-gamma","lemmy-delta","lemmy-epsilon"]
+ debug: true
}
captcha: {
enabled: false
federation: {
enabled: true
allowed_instances: ["lemmy-alpha","lemmy-gamma","lemmy-delta","lemmy-epsilon"]
+ debug: true
}
captcha: {
enabled: false
federation: {
enabled: true
allowed_instances: ["lemmy-beta"]
+ debug: true
}
captcha: {
enabled: false
federation: {
enabled: true
blocked_instances: ["lemmy-alpha"]
+ debug: true
}
captcha: {
enabled: false
federation: {
enabled: true
allowed_instances: ["lemmy-alpha","lemmy-beta","lemmy-delta","lemmy-epsilon"]
+ debug: true
}
captcha: {
enabled: false