Split apub code into multiple crates, other changes for faster building (#6031)

* Comment out joins for faster compile (ref #6012)

* cleanup

* revert report_combined

* comments

* add clean-workspace

* move api code out

* compile site view earlier

* compile post view earlier

* move code

* rename

* move activities to separate crate

* subfolder

* revert migrations

* fix tests

* fmt

* Use Box::pin for large futures

* move server to crates

* Move api_routes to separate crate

* fix tests
This commit is contained in:
Nutomic
2025-10-01 15:57:38 +00:00
committed by GitHub
parent 334fee01dd
commit 794993767a
281 changed files with 995 additions and 932 deletions

View File

@@ -1,2 +0,0 @@
[resolver]
incompatible-rust-versions = "fallback"

View File

@@ -16,7 +16,6 @@ variables:
include: [
# rust source code
"crates/**",
"src/**",
"**/Cargo.toml",
"Cargo.lock",
# database migrations

137
Cargo.lock generated
View File

@@ -939,9 +939,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.47"
version = "4.5.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931"
checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae"
dependencies = [
"clap_builder",
"clap_derive",
@@ -949,9 +949,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.47"
version = "4.5.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6"
checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9"
dependencies = [
"anstream",
"anstyle",
@@ -3133,12 +3133,16 @@ dependencies = [
"bcrypt",
"captcha",
"chrono",
"diesel",
"diesel-async",
"either",
"elementtree",
"futures",
"hound",
"itertools 0.14.0",
"lemmy_api_crud",
"lemmy_api_utils",
"lemmy_apub_objects",
"lemmy_db_schema",
"lemmy_db_schema_file",
"lemmy_db_views_comment",
@@ -3157,12 +3161,15 @@ dependencies = [
"lemmy_db_views_post",
"lemmy_db_views_registration_applications",
"lemmy_db_views_report_combined",
"lemmy_db_views_search_combined",
"lemmy_db_views_site",
"lemmy_db_views_vote",
"lemmy_email",
"lemmy_utils",
"pretty_assertions",
"regex",
"serde",
"serde_json",
"serial_test",
"sitemap-rs",
"tokio",
@@ -3239,6 +3246,17 @@ dependencies = [
"uuid",
]
[[package]]
name = "lemmy_api_routes"
version = "1.0.0-alpha.9"
dependencies = [
"actix-web",
"lemmy_api",
"lemmy_api_crud",
"lemmy_routes",
"lemmy_utils",
]
[[package]]
name = "lemmy_api_utils"
version = "1.0.0-alpha.9"
@@ -3298,6 +3316,33 @@ version = "1.0.0-alpha.9"
dependencies = [
"activitypub_federation",
"actix-web",
"async-trait",
"either",
"futures",
"futures-util",
"lemmy_api_utils",
"lemmy_apub_activities",
"lemmy_apub_objects",
"lemmy_db_schema",
"lemmy_db_schema_file",
"lemmy_db_views_community_follower",
"lemmy_db_views_community_moderator",
"lemmy_db_views_post",
"lemmy_utils",
"pretty_assertions",
"serde",
"serde_json",
"serial_test",
"tokio",
"tracing",
"url",
]
[[package]]
name = "lemmy_apub_activities"
version = "1.0.0-alpha.9"
dependencies = [
"activitypub_federation",
"anyhow",
"async-trait",
"chrono",
@@ -3306,31 +3351,22 @@ dependencies = [
"enum_delegate",
"futures",
"futures-util",
"itertools 0.14.0",
"lemmy_api_utils",
"lemmy_apub_objects",
"lemmy_db_schema",
"lemmy_db_schema_file",
"lemmy_db_views_comment",
"lemmy_db_views_community",
"lemmy_db_views_community_follower",
"lemmy_db_views_community_moderator",
"lemmy_db_views_community_person_ban",
"lemmy_db_views_local_user",
"lemmy_db_views_person",
"lemmy_db_views_person_content_combined",
"lemmy_db_views_post",
"lemmy_db_views_private_message",
"lemmy_db_views_search_combined",
"lemmy_db_views_site",
"lemmy_utils",
"pretty_assertions",
"serde",
"serde_json",
"serde_with",
"serial_test",
"strum",
"tokio",
"tracing",
"url",
"uuid",
@@ -3374,6 +3410,40 @@ dependencies = [
"url",
]
[[package]]
name = "lemmy_apub_send"
version = "1.0.0-alpha.9"
dependencies = [
"activitypub_federation",
"actix-web",
"anyhow",
"async-trait",
"chrono",
"diesel",
"diesel-async",
"either",
"futures",
"lemmy_api_utils",
"lemmy_apub_objects",
"lemmy_db_schema",
"lemmy_db_schema_file",
"lemmy_db_views_community_follower",
"lemmy_utils",
"mockall",
"moka",
"reqwest 0.12.23",
"serde",
"serde_json",
"serial_test",
"test-context",
"tokio",
"tokio-util",
"tracing",
"tracing-test",
"url",
"uuid",
]
[[package]]
name = "lemmy_db_schema"
version = "1.0.0-alpha.9"
@@ -3715,7 +3785,6 @@ dependencies = [
"i-love-jesus",
"lemmy_db_schema",
"lemmy_db_schema_file",
"lemmy_db_views_community",
"lemmy_db_views_local_user",
"lemmy_db_views_vote",
"lemmy_utils",
@@ -3834,7 +3903,6 @@ dependencies = [
"lemmy_db_views_community_moderator",
"lemmy_db_views_local_user",
"lemmy_db_views_person",
"lemmy_db_views_post",
"lemmy_db_views_readable_federation_state",
"lemmy_utils",
"serde",
@@ -3876,40 +3944,6 @@ dependencies = [
"uuid",
]
[[package]]
name = "lemmy_federate"
version = "1.0.0-alpha.9"
dependencies = [
"activitypub_federation",
"actix-web",
"anyhow",
"async-trait",
"chrono",
"diesel",
"diesel-async",
"either",
"futures",
"lemmy_api_utils",
"lemmy_apub_objects",
"lemmy_db_schema",
"lemmy_db_schema_file",
"lemmy_db_views_community_follower",
"lemmy_utils",
"mockall",
"moka",
"reqwest 0.12.23",
"serde",
"serde_json",
"serial_test",
"test-context",
"tokio",
"tokio-util",
"tracing",
"tracing-test",
"url",
"uuid",
]
[[package]]
name = "lemmy_routes"
version = "1.0.0-alpha.9"
@@ -3960,14 +3994,15 @@ dependencies = [
"actix-web",
"clap",
"lemmy_api",
"lemmy_api_crud",
"lemmy_api_routes",
"lemmy_api_utils",
"lemmy_apub",
"lemmy_apub_activities",
"lemmy_apub_objects",
"lemmy_apub_send",
"lemmy_db_schema",
"lemmy_db_schema_setup",
"lemmy_db_views_site",
"lemmy_federate",
"lemmy_routes",
"lemmy_utils",
"mimalloc",

View File

@@ -8,24 +8,6 @@ documentation = "https://join-lemmy.org/docs/en/index.html"
repository = "https://github.com/LemmyNet/lemmy"
rust-version = "1.81"
[package]
name = "lemmy_server"
version.workspace = true
edition.workspace = true
description.workspace = true
license.workspace = true
homepage.workspace = true
documentation.workspace = true
repository.workspace = true
rust-version.workspace = true
publish = false
[lib]
doctest = false
[lints]
workspace = true
# See https://github.com/johnthagen/min-sized-rust for additional optimizations
[profile.release]
lto = "fat"
@@ -37,9 +19,6 @@ codegen-units = 1 # Reduce parallel code generation.
[profile.dev]
debug = 0
[features]
default = []
[workspace]
members = [
"crates/utils",
@@ -72,11 +51,17 @@ members = [
"crates/api/api_crud",
"crates/api/api_common",
"crates/api/api_utils",
"crates/apub",
"crates/apub_objects",
"crates/federate",
"crates/api/routes",
"crates/apub/apub",
"crates/apub/activities",
"crates/apub/objects",
"crates/apub/send",
"crates/routes",
"crates/server",
]
resolver = "2"
# This line can be removed after upgrading to resolver = 3
incompatible-rust-versions = "fallback"
[workspace.lints.clippy]
cast_lossless = "deny"
@@ -104,19 +89,22 @@ unused_async = "deny"
map_err_ignore = "deny"
expect_used = "deny"
as_conversions = "deny"
large_futures = "deny"
[workspace.dependencies]
lemmy_api = { version = "=1.0.0-alpha.9", path = "./crates/api/api" }
lemmy_api_crud = { version = "=1.0.0-alpha.9", path = "./crates/api/api_crud" }
lemmy_apub = { version = "=1.0.0-alpha.9", path = "./crates/apub" }
lemmy_apub_objects = { version = "=1.0.0-alpha.9", path = "./crates/apub_objects" }
lemmy_api_routes = { version = "=1.0.0-alpha.9", path = "./crates/api/routes" }
lemmy_apub = { version = "=1.0.0-alpha.9", path = "./crates/apub/apub" }
lemmy_apub_activities = { version = "=1.0.0-alpha.9", path = "./crates/apub/activities" }
lemmy_apub_objects = { version = "=1.0.0-alpha.9", path = "./crates/apub/objects" }
lemmy_utils = { version = "=1.0.0-alpha.9", path = "./crates/utils", default-features = false }
lemmy_db_schema = { version = "=1.0.0-alpha.9", path = "./crates/db_schema" }
lemmy_db_schema_file = { version = "=1.0.0-alpha.9", path = "./crates/db_schema_file" }
lemmy_db_schema_setup = { version = "=1.0.0-alpha.9", path = "./crates/db_schema_setup" }
lemmy_api_utils = { version = "=1.0.0-alpha.9", path = "./crates/api/api_utils" }
lemmy_routes = { version = "=1.0.0-alpha.9", path = "./crates/routes" }
lemmy_federate = { version = "=1.0.0-alpha.9", path = "./crates/federate" }
lemmy_apub_send = { version = "=1.0.0-alpha.9", path = "./crates/apub/send" }
lemmy_email = { version = "=1.0.0-alpha.9", path = "./crates/email" }
lemmy_db_views_comment = { version = "=1.0.0-alpha.9", path = "./crates/db_views/comment" }
lemmy_db_views_community = { version = "=1.0.0-alpha.9", path = "./crates/db_views/community" }
@@ -225,33 +213,6 @@ extism-convert = "1.12.0"
unified-diff = "0.2.1"
diesel-uplete = { version = "0.2.0" }
[dependencies]
lemmy_api = { workspace = true }
lemmy_api_crud = { workspace = true }
lemmy_apub = { workspace = true }
lemmy_apub_objects = { workspace = true }
lemmy_utils = { workspace = true }
lemmy_db_schema = { workspace = true }
lemmy_db_schema_setup = { workspace = true }
lemmy_api_utils = { workspace = true }
lemmy_routes = { workspace = true }
lemmy_federate = { workspace = true }
lemmy_db_views_site = { workspace = true }
activitypub_federation = { workspace = true }
actix-web = { workspace = true }
tracing = { workspace = true }
tracing-actix-web = { workspace = true }
tracing-subscriber = { workspace = true }
reqwest-middleware = { workspace = true }
reqwest-tracing = { workspace = true }
serde_json = { workspace = true }
rustls = { workspace = true }
tokio.workspace = true
clap = { workspace = true }
[target.'cfg(target_arch = "x86_64")'.dependencies]
mimalloc = "0.1.48"
# Speedup RSA key generation
# https://github.com/RustCrypto/RSA/blob/master/README.md#example
[profile.dev.package.num-bigint-dig]

View File

@@ -26,10 +26,12 @@ lemmy_db_views_comment = { workspace = true, features = ["full"] }
lemmy_db_views_community = { workspace = true, features = ["full"] }
lemmy_db_views_community_moderator = { workspace = true, features = ["full"] }
lemmy_db_views_community_follower = { workspace = true, features = ["full"] }
lemmy_apub_objects = { workspace = true, features = ["full"] }
lemmy_db_views_community_person_ban = { workspace = true, features = ["full"] }
lemmy_db_views_post = { workspace = true, features = ["full"] }
lemmy_db_views_vote = { workspace = true, features = ["full"] }
lemmy_db_views_local_user = { workspace = true, features = ["full"] }
lemmy_db_views_search_combined = { workspace = true, features = ["full"] }
lemmy_db_views_person = { workspace = true, features = ["full"] }
lemmy_db_views_local_image = { workspace = true, features = ["full"] }
lemmy_db_views_notification = { workspace = true, features = ["full"] }
@@ -64,6 +66,11 @@ sitemap-rs = "0.2.2"
totp-rs = { version = "5.7.0", features = ["gen_secret", "otpauth"] }
diesel-async = { workspace = true, features = ["deadpool", "postgres"] }
either = { workspace = true }
futures = { workspace = true }
serde = { workspace = true }
itertools = { workspace = true }
serde_json = { workspace = true }
diesel = { workspace = true }
[dev-dependencies]
serial_test = { workspace = true }

View File

@@ -4,16 +4,12 @@ use activitypub_federation::{
traits::{Actor, Object},
};
use diesel::NotFound;
use either::Either::*;
use itertools::Itertools;
use lemmy_api_utils::context::LemmyContext;
use lemmy_apub_objects::objects::SiteOrMultiOrCommunityOrUser;
use lemmy_db_schema::{newtypes::InstanceId, traits::ApubActor};
use lemmy_db_schema::traits::ApubActor;
use lemmy_db_views_local_user::LocalUserView;
use lemmy_utils::error::{LemmyError, LemmyErrorType, LemmyResult};
pub mod search;
/// Resolve actor identifier like `!news@example.com` to user or community object.
///
/// In case the requesting user is logged in and the object was not found locally, it is attempted
@@ -65,12 +61,3 @@ where
)
}
}
pub(crate) fn get_instance_id(s: &SiteOrMultiOrCommunityOrUser) -> InstanceId {
match s {
Left(Left(s)) => s.instance_id,
Left(Right(m)) => m.instance_id,
Right(Left(u)) => u.instance_id,
Right(Right(c)) => c.instance_id,
}
}

View File

@@ -1,11 +1,9 @@
use super::comment_sort_type_with_default;
use crate::{
api::{
fetch_limit_with_default,
listing_type_with_default,
post_time_range_seconds_with_default,
},
use crate::federation::{
comment_sort_type_with_default,
fetch_limit_with_default,
fetcher::resolve_ap_identifier,
listing_type_with_default,
post_time_range_seconds_with_default,
};
use activitypub_federation::config::Data;
use actix_web::web::{Json, Query};

View File

@@ -1,4 +1,4 @@
use super::resolve_person_id_from_id_or_username;
use crate::federation::resolve_person_id_from_id_or_username;
use activitypub_federation::config::Data;
use actix_web::web::{Json, Query};
use lemmy_api_utils::{context::LemmyContext, utils::check_private_instance};

View File

@@ -1,11 +1,9 @@
use crate::{
api::{
fetch_limit_with_default,
listing_type_with_default,
post_sort_type_with_default,
post_time_range_seconds_with_default,
},
use crate::federation::{
fetch_limit_with_default,
fetcher::resolve_ap_identifier,
listing_type_with_default,
post_sort_type_with_default,
post_time_range_seconds_with_default,
};
use activitypub_federation::config::Data;
use actix_web::web::{Json, Query};

View File

@@ -1,4 +1,4 @@
use crate::fetcher::resolve_ap_identifier;
use crate::federation::fetcher::resolve_ap_identifier;
use activitypub_federation::config::Data;
use lemmy_api_utils::context::LemmyContext;
use lemmy_apub_objects::objects::person::ApubPerson;
@@ -10,6 +10,7 @@ use lemmy_db_schema_file::enums::{CommentSortType, ListingType, PostSortType};
use lemmy_db_views_local_user::LocalUserView;
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
mod fetcher;
pub mod list_comments;
pub mod list_person_content;
pub mod list_posts;

View File

@@ -1,4 +1,4 @@
use crate::fetcher::resolve_ap_identifier;
use crate::federation::fetcher::resolve_ap_identifier;
use activitypub_federation::config::Data;
use actix_web::web::{Json, Query};
use lemmy_api_utils::{

View File

@@ -1,4 +1,4 @@
use super::resolve_person_id_from_id_or_username;
use crate::federation::resolve_person_id_from_id_or_username;
use activitypub_federation::config::Data;
use actix_web::web::{Json, Query};
use lemmy_api_utils::{

View File

@@ -1,8 +1,11 @@
use crate::fetcher::search::{search_query_to_object_id, search_query_to_object_id_local};
use activitypub_federation::config::Data;
use activitypub_federation::{
config::Data,
fetch::{object_id::ObjectId, webfinger::webfinger_resolve_actor},
};
use actix_web::web::{Json, Query};
use either::Either::*;
use lemmy_api_utils::{context::LemmyContext, utils::check_private_instance};
use lemmy_apub_objects::objects::{SearchableObjects, UserOrCommunity};
use lemmy_db_views_comment::CommentView;
use lemmy_db_views_community::{CommunityView, MultiCommunityView};
use lemmy_db_views_local_user::LocalUserView;
@@ -11,6 +14,7 @@ use lemmy_db_views_post::PostView;
use lemmy_db_views_search_combined::{SearchCombinedView, SearchResponse};
use lemmy_db_views_site::{api::ResolveObject, SiteView};
use lemmy_utils::error::{LemmyErrorExt2, LemmyErrorType, LemmyResult};
use url::Url;
pub async fn resolve_object(
data: Query<ResolveObject>,
@@ -68,6 +72,41 @@ pub(super) async fn resolve_object_internal(
})
}
/// Converts search query to object id. The query can either be an URL, which will be treated as
/// ObjectId directly, or a webfinger identifier (@user@example.com or !community@example.com)
/// which gets resolved to an URL.
async fn search_query_to_object_id(
mut query: String,
context: &Data<LemmyContext>,
) -> LemmyResult<SearchableObjects> {
Ok(match Url::parse(&query) {
Ok(url) => {
// its already an url, just go with it
ObjectId::from(url).dereference(context).await?
}
Err(_) => {
// not an url, try to resolve via webfinger
if query.starts_with('!') || query.starts_with('@') {
query.remove(0);
}
Left(Right(
webfinger_resolve_actor::<LemmyContext, UserOrCommunity>(&query, context).await?,
))
}
})
}
/// Converts a search query to an object id. The query MUST bbe a URL which will bbe treated
/// as the ObjectId directly. If the query is a webfinger identifier (@user@example.com or
/// !community@example.com) this method will return an error.
async fn search_query_to_object_id_local(
query: &str,
context: &Data<LemmyContext>,
) -> LemmyResult<SearchableObjects> {
let url = Url::parse(query)?;
ObjectId::from(url).dereference_local(context).await
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -1,4 +1,4 @@
use crate::{api::resolve_object::resolve_object_internal, fetcher::resolve_ap_identifier};
use crate::federation::{fetcher::resolve_ap_identifier, resolve_object::resolve_object_internal};
use activitypub_federation::config::Data;
use actix_web::web::{Json, Query};
use futures::future::join;

View File

@@ -267,7 +267,7 @@ where
#[expect(clippy::indexing_slicing)]
pub(crate) mod tests {
use super::*;
use crate::api::user_settings_backup::{export_settings, import_settings};
use crate::federation::user_settings_backup::{export_settings, import_settings};
use actix_web::web::Json;
use lemmy_api_utils::context::LemmyContext;
use lemmy_db_schema::{

View File

@@ -11,6 +11,7 @@ use totp_rs::{Secret, TOTP};
pub mod comment;
pub mod community;
pub mod federation;
pub mod local_user;
pub mod post;
pub mod reports;

View File

@@ -3,8 +3,8 @@ use actix_web::web::{Json, Query};
use lemmy_api_utils::context::LemmyContext;
use lemmy_db_schema::source::post::PostActions;
use lemmy_db_views_local_user::LocalUserView;
use lemmy_db_views_person_content_combined::api::{ListPersonHidden, ListPersonHiddenResponse};
use lemmy_db_views_post::PostView;
use lemmy_db_views_site::api::{ListPersonHidden, ListPersonHiddenResponse};
use lemmy_utils::error::LemmyResult;
pub async fn list_person_hidden(

View File

@@ -3,8 +3,8 @@ use actix_web::web::{Json, Query};
use lemmy_api_utils::context::LemmyContext;
use lemmy_db_schema::source::post::PostActions;
use lemmy_db_views_local_user::LocalUserView;
use lemmy_db_views_person_content_combined::api::{ListPersonRead, ListPersonReadResponse};
use lemmy_db_views_post::PostView;
use lemmy_db_views_site::api::{ListPersonRead, ListPersonReadResponse};
use lemmy_utils::error::LemmyResult;
pub async fn list_person_read(

View File

@@ -252,14 +252,14 @@ async fn test_application_approval() -> LemmyResult<()> {
expected_total_applications,
);
update_site(
Box::pin(update_site(
Json(EditSite {
require_email_verification: Some(false),
..Default::default()
}),
context.clone(),
admin_local_user_view.clone(),
)
))
.await?;
// TODO: There is probably a better way to ensure cache invalidation
@@ -359,14 +359,14 @@ async fn test_application_approval() -> LemmyResult<()> {
expected_total_applications,
);
update_site(
Box::pin(update_site(
Json(EditSite {
registration_mode: Some(RegistrationMode::Open),
..Default::default()
}),
context.clone(),
admin_local_user_view.clone(),
)
))
.await?;
// TODO: There is probably a better way to ensure cache invalidation

View File

@@ -1,3 +1,9 @@
pub use lemmy_db_views_person_content_combined::api::{
ListPersonHidden,
ListPersonHiddenResponse,
ListPersonRead,
ListPersonReadResponse,
};
pub use lemmy_db_views_person_liked_combined::{
ListPersonLiked,
ListPersonLikedResponse,
@@ -8,16 +14,7 @@ pub use lemmy_db_views_person_saved_combined::{
ListPersonSavedResponse,
PersonSavedCombinedView,
};
pub use lemmy_db_views_site::api::{
DeleteAccount,
ListPersonHidden,
ListPersonHiddenResponse,
ListPersonRead,
ListPersonReadResponse,
MyUserInfo,
SaveUserSettings,
};
pub use lemmy_db_views_site::api::{DeleteAccount, MyUserInfo, SaveUserSettings};
pub mod auth {
pub use lemmy_db_schema::source::login_token::LoginToken;
pub use lemmy_db_views_registration_applications::api::Register;

View File

@@ -6,8 +6,6 @@ pub use lemmy_db_schema::{
pub use lemmy_db_schema_file::enums::{PostListingMode, PostNotificationsMode};
pub use lemmy_db_views_post::{
api::{
GetPost,
GetPostResponse,
GetPosts,
GetPostsResponse,
GetSiteMetadata,
@@ -18,7 +16,7 @@ pub use lemmy_db_views_post::{
},
PostView,
};
pub use lemmy_db_views_search_combined::api::{GetPost, GetPostResponse};
pub mod actions {
pub use lemmy_db_views_post::api::{
CreatePost,

View File

@@ -13,11 +13,11 @@ use lemmy_db_schema::{
};
use lemmy_db_views_community::CommunityView;
use lemmy_db_views_local_user::LocalUserView;
use lemmy_db_views_post::{
use lemmy_db_views_post::PostView;
use lemmy_db_views_search_combined::{
api::{GetPost, GetPostResponse},
PostView,
impls::SearchCombinedQuery,
};
use lemmy_db_views_search_combined::impls::SearchCombinedQuery;
use lemmy_db_views_site::SiteView;
use lemmy_utils::error::{LemmyErrorType, LemmyResult};

View File

@@ -19,8 +19,7 @@ pub async fn get_site(
) -> LemmyResult<Json<GetSiteResponse>> {
// This data is independent from the user account so we can cache it across requests
static CACHE: CacheLock<GetSiteResponse> = LazyLock::new(build_cache);
let mut site_response = CACHE
.try_get_with((), read_site(&context))
let mut site_response = Box::pin(CACHE.try_get_with((), read_site(&context)))
.await
.map_err(|e| anyhow::anyhow!("Failed to construct site response: {e}"))?;

View File

@@ -0,0 +1,27 @@
[package]
name = "lemmy_api_routes"
version.workspace = true
edition.workspace = true
description.workspace = true
license.workspace = true
homepage.workspace = true
documentation.workspace = true
repository.workspace = true
rust-version.workspace = true
publish = false
[lib]
doctest = false
[lints]
workspace = true
[features]
default = []
[dependencies]
lemmy_api = { workspace = true }
lemmy_api_crud = { workspace = true }
lemmy_utils = { workspace = true }
lemmy_routes = { workspace = true }
actix-web = { workspace = true }

View File

@@ -23,6 +23,16 @@ use lemmy_api::{
transfer::transfer_community,
update_notifications::update_community_notifications,
},
federation::{
list_comments::{list_comments, list_comments_slim},
list_person_content::list_person_content,
list_posts::list_posts,
read_community::get_community,
read_person::read_person,
resolve_object::resolve_object,
search::search,
user_settings_backup::{export_settings, import_settings},
},
local_user::{
add_admin::add_admin,
ban_person::ban_from_site,
@@ -157,16 +167,6 @@ use lemmy_api_crud::{
my_user::get_my_user,
},
};
use lemmy_apub::api::{
list_comments::{list_comments, list_comments_slim},
list_person_content::list_person_content,
list_posts::list_posts,
read_community::get_community,
read_person::read_person,
resolve_object::resolve_object,
search::search,
user_settings_backup::{export_settings, import_settings},
};
use lemmy_routes::images::{
delete::{
delete_community_banner,

View File

@@ -1,5 +1,5 @@
[package]
name = "lemmy_apub"
name = "lemmy_apub_activities"
publish = false
version.workspace = true
edition.workspace = true
@@ -11,7 +11,7 @@ repository.workspace = true
rust-version.workspace = true
[lib]
name = "lemmy_apub"
name = "lemmy_apub_activities"
path = "src/lib.rs"
doctest = false
@@ -22,19 +22,12 @@ full = []
workspace = true
[dependencies]
lemmy_db_views_comment = { workspace = true, features = ["full"] }
lemmy_db_views_community = { workspace = true, features = ["full"] }
lemmy_db_views_community_moderator = { workspace = true, features = ["full"] }
lemmy_db_views_community_follower = { workspace = true, features = ["full"] }
lemmy_db_views_post = { workspace = true, features = ["full"] }
lemmy_db_views_local_user = { workspace = true, features = ["full"] }
lemmy_db_views_person = { workspace = true, features = ["full"] }
lemmy_db_views_private_message = { workspace = true, features = ["full"] }
lemmy_db_views_site = { workspace = true, features = ["full"] }
lemmy_db_views_person_content_combined = { workspace = true, features = [
"full",
] }
lemmy_db_views_search_combined = { workspace = true, features = ["full"] }
lemmy_db_views_community_person_ban = { workspace = true, features = ["full"] }
lemmy_utils = { workspace = true, features = ["full"] }
lemmy_db_schema = { workspace = true, features = ["full"] }
@@ -46,14 +39,11 @@ diesel = { workspace = true }
chrono = { workspace = true }
serde_json = { workspace = true }
serde = { workspace = true }
actix-web = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
strum = { workspace = true }
url = { workspace = true }
futures = { workspace = true }
futures-util = { workspace = true }
itertools = { workspace = true }
uuid = { workspace = true }
async-trait = { workspace = true }
anyhow = { workspace = true }
@@ -62,8 +52,6 @@ enum_delegate = "0.2.0"
either = { workspace = true }
[dev-dependencies]
serial_test = { workspace = true }
pretty_assertions = { workspace = true }
[package.metadata.cargo-shear]
ignored = ["futures", "futures-util"]

View File

@@ -1,4 +1,4 @@
use crate::protocol::activities::{
use crate::protocol::{
block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
community::{
announce::{AnnounceActivity, RawAnnouncableActivities},
@@ -38,7 +38,7 @@ use url::Url;
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(untagged)]
#[enum_delegate::implement(Activity)]
pub(crate) enum SharedInboxActivities {
pub enum SharedInboxActivities {
Follow(Follow),
AcceptFollow(AcceptFollow),
RejectFollow(RejectFollow),
@@ -107,24 +107,24 @@ mod tests {
#[test]
fn test_shared_inbox() -> LemmyResult<()> {
test_parse_lemmy_item::<SharedInboxActivities>(
"assets/lemmy/activities/deletion/delete_user.json",
"../apub/assets/lemmy/activities/deletion/delete_user.json",
)?;
test_parse_lemmy_item::<SharedInboxActivities>(
"assets/lemmy/activities/following/accept.json",
"../apub/assets/lemmy/activities/following/accept.json",
)?;
test_parse_lemmy_item::<SharedInboxActivities>(
"assets/lemmy/activities/create_or_update/create_comment.json",
"../apub/assets/lemmy/activities/create_or_update/create_comment.json",
)?;
test_parse_lemmy_item::<SharedInboxActivities>(
"assets/lemmy/activities/create_or_update/create_private_message.json",
"../apub/assets/lemmy/activities/create_or_update/create_private_message.json",
)?;
test_parse_lemmy_item::<SharedInboxActivities>(
"assets/lemmy/activities/following/follow.json",
"../apub/assets/lemmy/activities/following/follow.json",
)?;
test_parse_lemmy_item::<SharedInboxActivities>(
"assets/lemmy/activities/create_or_update/create_comment.json",
"../apub/assets/lemmy/activities/create_or_update/create_comment.json",
)?;
test_json::<SharedInboxActivities>("assets/mastodon/activities/follow.json")?;
test_json::<SharedInboxActivities>("../apub/assets/mastodon/activities/follow.json")?;
Ok(())
}
}

View File

@@ -1,14 +1,12 @@
use super::{to, update_removed_for_instance};
use crate::{
activities::{
block::{generate_cc, SiteOrCommunity},
community::send_activity_in_community,
generate_activity_id,
send_lemmy_activity,
MOD_ACTION_DEFAULT_REASON,
},
activity_lists::AnnouncableActivities,
protocol::activities::block::block_user::BlockUser,
block::{generate_cc, SiteOrCommunity},
community::send_activity_in_community,
generate_activity_id,
protocol::block::block_user::BlockUser,
send_lemmy_activity,
MOD_ACTION_DEFAULT_REASON,
};
use activitypub_federation::{
config::Data,
@@ -46,7 +44,7 @@ use lemmy_utils::error::{LemmyError, LemmyResult};
use url::Url;
impl BlockUser {
pub(in crate::activities::block) async fn new(
pub(in crate::block) async fn new(
target: &SiteOrCommunity,
user: &ApubPerson,
mod_: &ApubPerson,

View File

@@ -1,4 +1,4 @@
use crate::protocol::activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser};
use crate::protocol::block::{block_user::BlockUser, undo_block_user::UndoBlockUser};
use activitypub_federation::{config::Data, kinds::public, traits::Object};
use either::Either;
use lemmy_api_utils::{context::LemmyContext, utils::check_expire_time};

View File

@@ -1,14 +1,12 @@
use super::{to, update_removed_for_instance};
use crate::{
activities::{
block::{generate_cc, SiteOrCommunity},
community::send_activity_in_community,
generate_activity_id,
send_lemmy_activity,
MOD_ACTION_DEFAULT_REASON,
},
activity_lists::AnnouncableActivities,
protocol::activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
block::{generate_cc, SiteOrCommunity},
community::send_activity_in_community,
generate_activity_id,
protocol::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
send_lemmy_activity,
MOD_ACTION_DEFAULT_REASON,
};
use activitypub_federation::{
config::Data,

View File

@@ -1,10 +1,12 @@
use crate::{
activities::{generate_activity_id, generate_announce_activity_id, send_lemmy_activity},
activity_lists::AnnouncableActivities,
generate_activity_id,
generate_announce_activity_id,
protocol::{
activities::community::announce::{AnnounceActivity, RawAnnouncableActivities},
community::announce::{AnnounceActivity, RawAnnouncableActivities},
IdOrNestedObject,
},
send_lemmy_activity,
};
use activitypub_federation::{
config::Data,
@@ -77,7 +79,7 @@ impl Id for RawAnnouncableActivities {
}
impl AnnounceActivity {
pub(crate) fn new(
pub fn new(
object: RawAnnouncableActivities,
community: &ApubCommunity,
context: &Data<LemmyContext>,

View File

@@ -1,10 +1,8 @@
use crate::{
activities::{community::send_activity_in_community, generate_activity_id},
activity_lists::AnnouncableActivities,
protocol::activities::community::{
collection_add::CollectionAdd,
collection_remove::CollectionRemove,
},
community::send_activity_in_community,
generate_activity_id,
protocol::community::{collection_add::CollectionAdd, collection_remove::CollectionRemove},
};
use activitypub_federation::{
config::Data,

View File

@@ -1,7 +1,8 @@
use crate::{
activities::{community::send_activity_in_community, generate_activity_id},
activity_lists::AnnouncableActivities,
protocol::activities::community::collection_remove::CollectionRemove,
community::send_activity_in_community,
generate_activity_id,
protocol::community::collection_remove::CollectionRemove,
};
use activitypub_federation::{
config::Data,

View File

@@ -1,13 +1,11 @@
use crate::{
activities::{
check_community_deleted_or_removed,
community::send_activity_in_community,
generate_activity_id,
MOD_ACTION_DEFAULT_REASON,
},
activity_lists::AnnouncableActivities,
check_community_deleted_or_removed,
community::send_activity_in_community,
generate_activity_id,
post_or_comment_community,
protocol::activities::community::lock::{LockPageOrNote, LockType, UndoLockPageOrNote},
protocol::community::lock::{LockPageOrNote, LockType, UndoLockPageOrNote},
MOD_ACTION_DEFAULT_REASON,
};
use activitypub_federation::{
config::Data,

View File

@@ -1,7 +1,7 @@
use crate::{
activities::send_lemmy_activity,
activity_lists::AnnouncableActivities,
protocol::activities::community::announce::AnnounceActivity,
protocol::community::announce::AnnounceActivity,
send_lemmy_activity,
};
use activitypub_federation::{config::Data, fetch::object_id::ObjectId, traits::Actor};
use either::Either;

View File

@@ -1,11 +1,12 @@
use super::{local_community, report_inboxes};
use crate::{
activities::{generate_activity_id, send_lemmy_activity},
activity_lists::AnnouncableActivities,
protocol::activities::community::{
generate_activity_id,
protocol::community::{
announce::AnnounceActivity,
report::{Report, ReportObject},
},
send_lemmy_activity,
};
use activitypub_federation::{
config::Data,

View File

@@ -1,12 +1,13 @@
use super::{local_community, report_inboxes, verify_mod_or_admin_action};
use crate::{
activities::{generate_activity_id, send_lemmy_activity},
activity_lists::AnnouncableActivities,
protocol::activities::community::{
generate_activity_id,
protocol::community::{
announce::AnnounceActivity,
report::Report,
resolve_report::{ResolveReport, ResolveType},
},
send_lemmy_activity,
};
use activitypub_federation::{
config::Data,

View File

@@ -1,7 +1,8 @@
use crate::{
activities::{community::send_activity_in_community, generate_activity_id, send_lemmy_activity},
activity_lists::AnnouncableActivities,
protocol::activities::community::update::Update,
community::{send_activity_in_community, AnnouncableActivities},
generate_activity_id,
protocol::community::update::Update,
send_lemmy_activity,
};
use activitypub_federation::{
config::Data,

View File

@@ -1,11 +1,9 @@
use crate::{
activities::{
check_community_deleted_or_removed,
community::send_activity_in_community,
generate_activity_id,
},
activity_lists::AnnouncableActivities,
protocol::activities::{create_or_update::note::CreateOrUpdateNote, CreateOrUpdateType},
check_community_deleted_or_removed,
community::send_activity_in_community,
generate_activity_id,
protocol::{create_or_update::note::CreateOrUpdateNote, CreateOrUpdateType},
};
use activitypub_federation::{
config::Data,

View File

@@ -1,4 +1,4 @@
use crate::protocol::activities::create_or_update::{
use crate::protocol::create_or_update::{
note::CreateOrUpdateNote,
note_wrapper::CreateOrUpdateNoteWrapper,
private_message::CreateOrUpdatePrivateMessage,

View File

@@ -1,11 +1,9 @@
use crate::{
activities::{
check_community_deleted_or_removed,
community::send_activity_in_community,
generate_activity_id,
},
activity_lists::AnnouncableActivities,
protocol::activities::{create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType},
check_community_deleted_or_removed,
community::send_activity_in_community,
generate_activity_id,
protocol::{create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType},
};
use activitypub_federation::{
config::Data,
@@ -40,7 +38,7 @@ use lemmy_utils::error::{LemmyError, LemmyResult};
use url::Url;
impl CreateOrUpdatePage {
pub(crate) async fn new(
pub async fn new(
post: ApubPost,
actor: &ApubPerson,
community: &ApubCommunity,

View File

@@ -1,9 +1,8 @@
use crate::{
activities::{generate_activity_id, send_lemmy_activity, verify_person},
protocol::activities::{
create_or_update::private_message::CreateOrUpdatePrivateMessage,
CreateOrUpdateType,
},
generate_activity_id,
protocol::{create_or_update::private_message::CreateOrUpdatePrivateMessage, CreateOrUpdateType},
send_lemmy_activity,
verify_person,
};
use activitypub_federation::{
config::Data,

View File

@@ -1,10 +1,8 @@
use crate::{
activities::{
deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
generate_activity_id,
MOD_ACTION_DEFAULT_REASON,
},
protocol::{activities::deletion::delete::Delete, IdOrNestedObject},
deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
generate_activity_id,
protocol::{deletion::delete::Delete, IdOrNestedObject},
MOD_ACTION_DEFAULT_REASON,
};
use activitypub_federation::{config::Data, kinds::activity::DeleteType, traits::Activity};
use lemmy_api_utils::{context::LemmyContext, notify::notify_mod_action};
@@ -76,7 +74,7 @@ impl Activity for Delete {
}
impl Delete {
pub(in crate::activities::deletion) fn new(
pub(in crate::deletion) fn new(
actor: &ApubPerson,
object: DeletableObjects,
to: Vec<Url>,
@@ -99,7 +97,7 @@ impl Delete {
}
}
pub(in crate::activities) async fn receive_remove_action(
pub(crate) async fn receive_remove_action(
actor: &ApubPerson,
object: &Url,
reason: Option<String>,

View File

@@ -1,7 +1,9 @@
use crate::{
activities::{community::send_activity_in_community, send_lemmy_activity, verify_person},
activity_lists::AnnouncableActivities,
protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
community::send_activity_in_community,
protocol::deletion::{delete::Delete, undo_delete::UndoDelete},
send_lemmy_activity,
verify_person,
};
use activitypub_federation::{
config::Data,
@@ -176,7 +178,7 @@ impl DeletableObjects {
}
}
pub(in crate::activities) async fn verify_delete_activity(
pub(crate) async fn verify_delete_activity(
activity: &Delete,
is_mod_action: bool,
context: &Data<LemmyContext>,

View File

@@ -1,9 +1,7 @@
use crate::{
activities::{
deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
generate_activity_id,
},
protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
generate_activity_id,
protocol::deletion::{delete::Delete, undo_delete::UndoDelete},
};
use activitypub_federation::{config::Data, kinds::activity::UndoType, traits::Activity};
use lemmy_api_utils::context::LemmyContext;
@@ -58,7 +56,7 @@ impl Activity for UndoDelete {
}
impl UndoDelete {
pub(in crate::activities::deletion) fn new(
pub(in crate::deletion) fn new(
actor: &ApubPerson,
object: DeletableObjects,
to: Vec<Url>,
@@ -80,7 +78,7 @@ impl UndoDelete {
})
}
pub(in crate::activities) async fn receive_undo_remove_action(
pub(crate) async fn receive_undo_remove_action(
actor: &ApubPerson,
object: &Url,
reason: String,

View File

@@ -1,6 +1,7 @@
use crate::{
activities::{generate_activity_id, send_lemmy_activity},
protocol::activities::following::{accept::AcceptFollow, follow::Follow},
generate_activity_id,
protocol::following::{accept::AcceptFollow, follow::Follow},
send_lemmy_activity,
};
use activitypub_federation::{
config::Data,

View File

@@ -1,6 +1,7 @@
use crate::{
activities::{generate_activity_id, send_lemmy_activity},
protocol::activities::following::{accept::AcceptFollow, follow::Follow},
generate_activity_id,
protocol::following::{accept::AcceptFollow, follow::Follow},
send_lemmy_activity,
};
use activitypub_federation::{
config::Data,
@@ -28,7 +29,7 @@ use lemmy_utils::error::{FederationError, LemmyError, LemmyErrorType, LemmyResul
use url::Url;
impl Follow {
pub(in crate::activities::following) fn new(
pub(in crate::following) fn new(
actor: &ApubPerson,
target: &CommunityOrMulti,
context: &Data<LemmyContext>,

View File

@@ -1,5 +1,5 @@
use super::{generate_activity_id, send_lemmy_activity};
use crate::protocol::activities::following::{
use crate::protocol::following::{
accept::AcceptFollow,
follow::Follow,
reject::RejectFollow,

View File

@@ -1,7 +1,7 @@
use super::send_activity_from_user_or_community_or_multi;
use crate::{
activities::generate_activity_id,
protocol::activities::following::{follow::Follow, reject::RejectFollow},
generate_activity_id,
protocol::following::{follow::Follow, reject::RejectFollow},
};
use activitypub_federation::{
config::Data,

View File

@@ -1,6 +1,7 @@
use crate::{
activities::{generate_activity_id, send_lemmy_activity},
protocol::activities::following::{follow::Follow, undo_follow::UndoFollow},
generate_activity_id,
protocol::following::{follow::Follow, undo_follow::UndoFollow},
send_lemmy_activity,
};
use activitypub_federation::{
config::Data,

View File

@@ -1,26 +1,24 @@
use crate::{
activities::{
block::{send_ban_from_community, send_ban_from_site},
community::{
collection_add::{send_add_mod_to_community, send_feature_post},
lock::send_lock,
update::{send_update_community, send_update_multi_community},
},
create_or_update::private_message::send_create_or_update_pm,
deletion::{
send_apub_delete_in_community,
send_apub_delete_private_message,
send_apub_delete_user,
DeletableObjects,
},
following::send_follow,
voting::send_like_activity,
block::{send_ban_from_community, send_ban_from_site},
community::{
collection_add::{send_add_mod_to_community, send_feature_post},
lock::send_lock,
update::{send_update_community, send_update_multi_community},
},
protocol::activities::{
create_or_update::private_message::send_create_or_update_pm,
deletion::{
send_apub_delete_in_community,
send_apub_delete_private_message,
send_apub_delete_user,
DeletableObjects,
},
following::send_follow,
protocol::{
community::{report::Report, resolve_report::ResolveReport},
create_or_update::{note::CreateOrUpdateNote, page::CreateOrUpdatePage},
CreateOrUpdateType,
},
voting::send_like_activity,
};
use activitypub_federation::{
config::Data,
@@ -46,17 +44,21 @@ use lemmy_db_schema::{
},
traits::Crud,
};
use lemmy_db_views_post::PostView;
use lemmy_db_views_site::SiteView;
use lemmy_utils::error::{FederationError, LemmyError, LemmyResult};
use serde::Serialize;
use tracing::info;
use url::{ParseError, Url};
use uuid::Uuid;
pub mod activity_lists;
pub mod block;
pub mod community;
pub mod create_or_update;
pub mod deletion;
pub mod following;
pub mod protocol;
pub mod voting;
const MOD_ACTION_DEFAULT_REASON: &str = "No reason provided";
@@ -155,7 +157,7 @@ pub async fn match_outgoing_activities(
context: &Data<LemmyContext>,
) -> LemmyResult<()> {
let context = context.clone();
let fed_task = async {
Box::pin(async {
use SendActivityData::*;
match data {
CreatePost(post) => {
@@ -373,7 +375,30 @@ pub async fn match_outgoing_activities(
send_update_multi_community(multi, actor, context).await
}
}
};
fed_task.await?;
})
.await?;
Ok(())
}
pub(crate) async fn post_or_comment_community(
post_or_comment: &PostOrComment,
context: &Data<LemmyContext>,
) -> LemmyResult<Community> {
match post_or_comment {
PostOrComment::Left(p) => Community::read(&mut context.pool(), p.community_id).await,
PostOrComment::Right(c) => {
let site_view = SiteView::read_local(&mut context.pool()).await?;
Ok(
PostView::read(
&mut context.pool(),
c.post_id,
None,
site_view.instance.id,
false,
)
.await?
.community,
)
}
}
}

View File

@@ -1,4 +1,4 @@
use crate::activities::block::SiteOrCommunity;
use crate::block::SiteOrCommunity;
use activitypub_federation::{
config::Data,
fetch::object_id::ObjectId,

View File

@@ -0,0 +1,18 @@
pub mod block_user;
pub mod undo_block_user;
#[cfg(test)]
mod tests {
use crate::protocol::block::{block_user::BlockUser, undo_block_user::UndoBlockUser};
use lemmy_apub_objects::utils::test::test_parse_lemmy_item;
use lemmy_utils::error::LemmyResult;
#[test]
fn test_parse_lemmy_block() -> LemmyResult<()> {
test_parse_lemmy_item::<BlockUser>("../apub/assets/lemmy/activities/block/block_user.json")?;
test_parse_lemmy_item::<UndoBlockUser>(
"../apub/assets/lemmy/activities/block/undo_block_user.json",
)?;
Ok(())
}
}

View File

@@ -15,7 +15,7 @@ pub struct AnnounceActivity {
pub(crate) actor: ObjectId<ApubCommunity>,
#[serde(deserialize_with = "deserialize_one_or_many")]
pub(crate) to: Vec<Url>,
pub(crate) object: IdOrNestedObject<RawAnnouncableActivities>,
pub object: IdOrNestedObject<RawAnnouncableActivities>,
#[serde(deserialize_with = "deserialize_one_or_many")]
pub(crate) cc: Vec<Url>,
#[serde(rename = "type")]

View File

@@ -0,0 +1,68 @@
pub mod announce;
pub mod collection_add;
pub mod collection_remove;
pub mod lock;
pub mod report;
pub mod resolve_report;
pub mod update;
#[cfg(test)]
mod tests {
use super::resolve_report::ResolveReport;
use crate::protocol::community::{
announce::AnnounceActivity,
collection_add::CollectionAdd,
collection_remove::CollectionRemove,
lock::{LockPageOrNote, UndoLockPageOrNote},
report::Report,
update::Update,
};
use lemmy_apub_objects::utils::test::test_parse_lemmy_item;
use lemmy_utils::error::LemmyResult;
#[test]
fn test_parse_lemmy_community_activities() -> LemmyResult<()> {
test_parse_lemmy_item::<AnnounceActivity>(
"../apub/assets/lemmy/activities/community/announce_create_page.json",
)?;
test_parse_lemmy_item::<CollectionAdd>(
"../apub/assets/lemmy/activities/community/add_mod.json",
)?;
test_parse_lemmy_item::<CollectionRemove>(
"../apub/assets/lemmy/activities/community/remove_mod.json",
)?;
test_parse_lemmy_item::<CollectionAdd>(
"../apub/assets/lemmy/activities/community/add_featured_post.json",
)?;
test_parse_lemmy_item::<CollectionRemove>(
"../apub/assets/lemmy/activities/community/remove_featured_post.json",
)?;
test_parse_lemmy_item::<LockPageOrNote>(
"../apub/assets/lemmy/activities/community/lock_page.json",
)?;
test_parse_lemmy_item::<UndoLockPageOrNote>(
"../apub/assets/lemmy/activities/community/undo_lock_page.json",
)?;
test_parse_lemmy_item::<LockPageOrNote>(
"../apub/assets/lemmy/activities/community/lock_note.json",
)?;
test_parse_lemmy_item::<UndoLockPageOrNote>(
"../apub/assets/lemmy/activities/community/undo_lock_note.json",
)?;
test_parse_lemmy_item::<Update>(
"../apub/assets/lemmy/activities/community/update_community.json",
)?;
test_parse_lemmy_item::<Report>("../apub/assets/lemmy/activities/community/report_page.json")?;
test_parse_lemmy_item::<ResolveReport>(
"../apub/assets/lemmy/activities/community/resolve_report_page.json",
)?;
Ok(())
}
}

View File

@@ -6,7 +6,7 @@ pub mod private_message;
#[cfg(test)]
mod tests {
use super::note_wrapper::{CreateOrUpdateNoteWrapper, NoteWrapper};
use crate::protocol::activities::create_or_update::{
use crate::protocol::create_or_update::{
note::CreateOrUpdateNote,
page::CreateOrUpdatePage,
private_message::CreateOrUpdatePrivateMessage,
@@ -17,25 +17,25 @@ mod tests {
#[test]
fn test_parse_lemmy_create_or_update() -> LemmyResult<()> {
test_parse_lemmy_item::<CreateOrUpdatePage>(
"assets/lemmy/activities/create_or_update/create_page.json",
"../apub/assets/lemmy/activities/create_or_update/create_page.json",
)?;
test_parse_lemmy_item::<CreateOrUpdatePage>(
"assets/lemmy/activities/create_or_update/update_page.json",
"../apub/assets/lemmy/activities/create_or_update/update_page.json",
)?;
test_parse_lemmy_item::<CreateOrUpdateNote>(
"assets/lemmy/activities/create_or_update/create_comment.json",
"../apub/assets/lemmy/activities/create_or_update/create_comment.json",
)?;
test_parse_lemmy_item::<CreateOrUpdatePrivateMessage>(
"assets/lemmy/activities/create_or_update/create_private_message.json",
"../apub/assets/lemmy/activities/create_or_update/create_private_message.json",
)?;
test_parse_lemmy_item::<CreateOrUpdateNoteWrapper>(
"assets/lemmy/activities/create_or_update/create_comment.json",
"../apub/assets/lemmy/activities/create_or_update/create_comment.json",
)?;
test_parse_lemmy_item::<CreateOrUpdateNoteWrapper>(
"assets/lemmy/activities/create_or_update/create_private_message.json",
"../apub/assets/lemmy/activities/create_or_update/create_private_message.json",
)?;
test_parse_lemmy_item::<NoteWrapper>("assets/lemmy/objects/comment.json")?;
test_parse_lemmy_item::<NoteWrapper>("assets/lemmy/objects/private_message.json")?;
test_parse_lemmy_item::<NoteWrapper>("../apub/assets/lemmy/objects/comment.json")?;
test_parse_lemmy_item::<NoteWrapper>("../apub/assets/lemmy/objects/private_message.json")?;
Ok(())
}
}

View File

@@ -1,4 +1,4 @@
use crate::protocol::activities::CreateOrUpdateType;
use crate::protocol::CreateOrUpdateType;
use activitypub_federation::{
config::Data,
fetch::object_id::ObjectId,

View File

@@ -1,4 +1,4 @@
use crate::protocol::activities::CreateOrUpdateType;
use crate::protocol::CreateOrUpdateType;
use activitypub_federation::{
config::Data,
fetch::object_id::ObjectId,

View File

@@ -1,4 +1,4 @@
use crate::protocol::activities::CreateOrUpdateType;
use crate::protocol::CreateOrUpdateType;
use activitypub_federation::{fetch::object_id::ObjectId, protocol::helpers::deserialize_one};
use lemmy_apub_objects::{objects::person::ApubPerson, protocol::private_message::PrivateMessage};
use serde::{Deserialize, Serialize};

View File

@@ -1,4 +1,4 @@
use crate::{activities::deletion::DeletableObjects, protocol::IdOrNestedObject};
use crate::{deletion::DeletableObjects, protocol::IdOrNestedObject};
use activitypub_federation::{
config::Data,
fetch::object_id::ObjectId,

View File

@@ -0,0 +1,38 @@
pub mod delete;
pub mod delete_user;
pub mod undo_delete;
#[cfg(test)]
mod tests {
use crate::protocol::deletion::{
delete::Delete,
delete_user::DeleteUser,
undo_delete::UndoDelete,
};
use lemmy_apub_objects::utils::test::test_parse_lemmy_item;
use lemmy_utils::error::LemmyResult;
#[test]
fn test_parse_lemmy_deletion() -> LemmyResult<()> {
test_parse_lemmy_item::<Delete>("../apub/assets/lemmy/activities/deletion/remove_note.json")?;
test_parse_lemmy_item::<Delete>("../apub/assets/lemmy/activities/deletion/delete_page.json")?;
test_parse_lemmy_item::<UndoDelete>(
"../apub/assets/lemmy/activities/deletion/undo_remove_note.json",
)?;
test_parse_lemmy_item::<UndoDelete>(
"../apub/assets/lemmy/activities/deletion/undo_delete_page.json",
)?;
test_parse_lemmy_item::<Delete>(
"../apub/assets/lemmy/activities/deletion/delete_private_message.json",
)?;
test_parse_lemmy_item::<UndoDelete>(
"../apub/assets/lemmy/activities/deletion/undo_delete_private_message.json",
)?;
test_parse_lemmy_item::<DeleteUser>(
"../apub/assets/lemmy/activities/deletion/delete_user.json",
)?;
Ok(())
}
}

View File

@@ -1,4 +1,4 @@
use crate::protocol::activities::following::follow::Follow;
use crate::protocol::following::follow::Follow;
use activitypub_federation::{
fetch::object_id::ObjectId,
kinds::activity::AcceptType,

View File

@@ -0,0 +1,21 @@
pub(crate) mod accept;
pub mod follow;
pub(crate) mod reject;
pub mod undo_follow;
#[cfg(test)]
mod tests {
use crate::protocol::following::{accept::AcceptFollow, follow::Follow, undo_follow::UndoFollow};
use lemmy_apub_objects::utils::test::test_parse_lemmy_item;
use lemmy_utils::error::LemmyResult;
#[test]
fn test_parse_lemmy_accept_follow() -> LemmyResult<()> {
test_parse_lemmy_item::<Follow>("../apub/assets/lemmy/activities/following/follow.json")?;
test_parse_lemmy_item::<AcceptFollow>("../apub/assets/lemmy/activities/following/accept.json")?;
test_parse_lemmy_item::<UndoFollow>(
"../apub/assets/lemmy/activities/following/undo_follow.json",
)?;
Ok(())
}
}

View File

@@ -1,4 +1,4 @@
use crate::protocol::activities::following::follow::Follow;
use crate::protocol::following::follow::Follow;
use activitypub_federation::{
fetch::object_id::ObjectId,
kinds::activity::RejectType,

View File

@@ -1,4 +1,4 @@
use crate::protocol::activities::following::follow::Follow;
use crate::protocol::following::follow::Follow;
use activitypub_federation::{
fetch::object_id::ObjectId,
kinds::activity::UndoType,

View File

@@ -0,0 +1,131 @@
use activitypub_federation::{config::Data, fetch::fetch_object_http};
use lemmy_api_utils::context::LemmyContext;
use lemmy_apub_objects::utils::protocol::Id;
use lemmy_utils::error::LemmyResult;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use strum::Display;
use url::Url;
pub mod block;
pub mod community;
pub mod create_or_update;
pub mod deletion;
pub mod following;
pub mod voting;
#[derive(Clone, Debug, Display, Deserialize, Serialize, PartialEq, Eq)]
pub enum CreateOrUpdateType {
Create,
Update,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum IdOrNestedObject<Kind: Id> {
Id(Url),
NestedObject(Kind),
}
impl<Kind: Id + DeserializeOwned + Send> IdOrNestedObject<Kind> {
pub(crate) fn id(&self) -> &Url {
match self {
IdOrNestedObject::Id(i) => i,
IdOrNestedObject::NestedObject(n) => n.id(),
}
}
pub async fn object(self, context: &Data<LemmyContext>) -> LemmyResult<Kind> {
match self {
// TODO: move IdOrNestedObject struct to library and make fetch_object_http private
IdOrNestedObject::Id(i) => Ok(fetch_object_http(&i, context).await?.object),
IdOrNestedObject::NestedObject(o) => Ok(o),
}
}
}
#[cfg(test)]
mod tests {
use crate::protocol::{
community::{announce::AnnounceActivity, report::Report},
create_or_update::{note::CreateOrUpdateNote, page::CreateOrUpdatePage},
deletion::delete::Delete,
following::{accept::AcceptFollow, follow::Follow, undo_follow::UndoFollow},
voting::{undo_vote::UndoVote, vote::Vote},
};
use lemmy_apub_objects::utils::test::test_json;
use lemmy_utils::error::LemmyResult;
#[test]
fn test_parse_smithereen_activities() -> LemmyResult<()> {
test_json::<CreateOrUpdateNote>("../apub/assets/smithereen/activities/create_note.json")?;
Ok(())
}
#[test]
fn test_parse_pleroma_activities() -> LemmyResult<()> {
test_json::<CreateOrUpdateNote>("../apub/assets/pleroma/activities/create_note.json")?;
test_json::<Delete>("../apub/assets/pleroma/activities/delete.json")?;
test_json::<Follow>("../apub/assets/pleroma/activities/follow.json")?;
Ok(())
}
#[test]
fn test_parse_mastodon_activities() -> LemmyResult<()> {
test_json::<CreateOrUpdateNote>("../apub/assets/mastodon/activities/create_note.json")?;
test_json::<Delete>("../apub/assets/mastodon/activities/delete.json")?;
test_json::<Follow>("../apub/assets/mastodon/activities/follow.json")?;
test_json::<UndoFollow>("../apub/assets/mastodon/activities/undo_follow.json")?;
test_json::<Vote>("../apub/assets/mastodon/activities/like_page.json")?;
test_json::<UndoVote>("../apub/assets/mastodon/activities/undo_like_page.json")?;
test_json::<Report>("../apub/assets/mastodon/activities/flag.json")?;
Ok(())
}
#[test]
fn test_parse_lotide_activities() -> LemmyResult<()> {
test_json::<Follow>("../apub/assets/lotide/activities/follow.json")?;
test_json::<CreateOrUpdatePage>("../apub/assets/lotide/activities/create_page.json")?;
test_json::<CreateOrUpdatePage>("../apub/assets/lotide/activities/create_page_image.json")?;
test_json::<CreateOrUpdateNote>("../apub/assets/lotide/activities/create_note_reply.json")?;
Ok(())
}
#[test]
fn test_parse_friendica_activities() -> LemmyResult<()> {
test_json::<CreateOrUpdatePage>("../apub/assets/friendica/activities/create_page_1.json")?;
test_json::<CreateOrUpdatePage>("../apub/assets/friendica/activities/create_page_2.json")?;
test_json::<CreateOrUpdateNote>("../apub/assets/friendica/activities/create_note.json")?;
test_json::<CreateOrUpdateNote>("../apub/assets/friendica/activities/update_note.json")?;
test_json::<Delete>("../apub/assets/friendica/activities/delete.json")?;
test_json::<Vote>("../apub/assets/friendica/activities/like_page.json")?;
test_json::<Vote>("../apub/assets/friendica/activities/dislike_page.json")?;
test_json::<UndoVote>("../apub/assets/friendica/activities/undo_dislike_page.json")?;
Ok(())
}
#[test]
fn test_parse_gnusocial_activities() -> LemmyResult<()> {
test_json::<CreateOrUpdatePage>("../apub/assets/gnusocial/activities/create_page.json")?;
test_json::<CreateOrUpdateNote>("../apub/assets/gnusocial/activities/create_note.json")?;
test_json::<Vote>("../apub/assets/gnusocial/activities/like_note.json")?;
Ok(())
}
#[test]
fn test_parse_peertube_activities() -> LemmyResult<()> {
test_json::<AnnounceActivity>("../apub/assets/peertube/activities/announce_video.json")?;
Ok(())
}
#[test]
fn test_parse_mbin_activities() -> LemmyResult<()> {
test_json::<AcceptFollow>("../apub/assets/mbin/activities/accept.json")?;
test_json::<Report>("../apub/assets/mbin/activities/flag.json")?;
Ok(())
}
#[test]
fn test_parse_wordpress_activities() -> LemmyResult<()> {
test_json::<AnnounceActivity>("../apub/assets/wordpress/activities/announce.json")?;
Ok(())
}
}

View File

@@ -0,0 +1,23 @@
pub mod undo_vote;
pub mod vote;
#[cfg(test)]
mod tests {
use crate::protocol::voting::{undo_vote::UndoVote, vote::Vote};
use lemmy_apub_objects::utils::test::test_parse_lemmy_item;
use lemmy_utils::error::LemmyResult;
#[test]
fn test_parse_lemmy_voting() -> LemmyResult<()> {
test_parse_lemmy_item::<Vote>("../apub/assets/lemmy/activities/voting/like_note.json")?;
test_parse_lemmy_item::<Vote>("../apub/assets/lemmy/activities/voting/dislike_page.json")?;
test_parse_lemmy_item::<UndoVote>(
"../apub/assets/lemmy/activities/voting/undo_like_note.json",
)?;
test_parse_lemmy_item::<UndoVote>(
"../apub/assets/lemmy/activities/voting/undo_dislike_page.json",
)?;
Ok(())
}
}

View File

@@ -1,7 +1,7 @@
use crate::{
activities::community::send_activity_in_community,
activity_lists::AnnouncableActivities,
protocol::activities::voting::{
community::send_activity_in_community,
protocol::voting::{
undo_vote::UndoVote,
vote::{Vote, VoteType},
},

View File

@@ -1,9 +1,7 @@
use crate::{
activities::{
generate_activity_id,
voting::{undo_vote_comment, undo_vote_post},
},
protocol::activities::voting::{undo_vote::UndoVote, vote::Vote},
generate_activity_id,
protocol::voting::{undo_vote::UndoVote, vote::Vote},
voting::{undo_vote_comment, undo_vote_post},
};
use activitypub_federation::{
config::Data,
@@ -20,7 +18,7 @@ use lemmy_utils::error::{LemmyError, LemmyResult};
use url::Url;
impl UndoVote {
pub(in crate::activities::voting) fn new(
pub(in crate::voting) fn new(
vote: Vote,
actor: &ApubPerson,
context: &Data<LemmyContext>,

View File

@@ -1,9 +1,7 @@
use crate::{
activities::{
generate_activity_id,
voting::{undo_vote_comment, undo_vote_post, vote_comment, vote_post},
},
protocol::activities::voting::vote::{Vote, VoteType},
generate_activity_id,
protocol::voting::vote::{Vote, VoteType},
voting::{undo_vote_comment, undo_vote_post, vote_comment, vote_post},
};
use activitypub_federation::{
config::Data,
@@ -21,7 +19,7 @@ use lemmy_utils::error::{LemmyError, LemmyResult};
use url::Url;
impl Vote {
pub(in crate::activities::voting) fn new(
pub(in crate::voting) fn new(
object_id: ObjectId<PostOrComment>,
actor: &ApubPerson,
kind: VoteType,

View File

@@ -0,0 +1,51 @@
[package]
name = "lemmy_apub"
publish = false
version.workspace = true
edition.workspace = true
description.workspace = true
license.workspace = true
homepage.workspace = true
documentation.workspace = true
repository.workspace = true
rust-version.workspace = true
[lib]
name = "lemmy_apub"
path = "src/lib.rs"
doctest = false
[features]
full = []
[lints]
workspace = true
[dependencies]
lemmy_db_views_community_moderator = { workspace = true, features = ["full"] }
lemmy_db_views_community_follower = { workspace = true, features = ["full"] }
lemmy_db_views_post = { workspace = true, features = ["full"] }
lemmy_utils = { workspace = true, features = ["full"] }
lemmy_db_schema = { workspace = true, features = ["full"] }
lemmy_api_utils = { workspace = true, features = ["full"] }
lemmy_apub_activities = { workspace = true }
lemmy_apub_objects = { workspace = true }
activitypub_federation = { workspace = true }
lemmy_db_schema_file = { workspace = true }
serde_json = { workspace = true }
serde = { workspace = true }
actix-web = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
url = { workspace = true }
futures = { workspace = true }
futures-util = { workspace = true }
async-trait = { workspace = true }
either = { workspace = true }
[dev-dependencies]
serial_test = { workspace = true }
pretty_assertions = { workspace = true }
[package.metadata.cargo-shear]
ignored = ["futures", "futures-util"]

Some files were not shown because too many files have changed in this diff Show More