diff --git a/Cargo.lock b/Cargo.lock index 9931aef13..0b8f6413a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1728,6 +1728,7 @@ dependencies = [ "lazy_static", "lemmy_api_common", "lemmy_apub", + "lemmy_apub_lib", "lemmy_db_schema", "lemmy_db_views", "lemmy_db_views_actor", diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index 57a9406fb..39be5b5ad 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -14,6 +14,7 @@ doctest = false [dependencies] lemmy_apub = { version = "=0.13.5-rc.7", path = "../apub" } +lemmy_apub_lib = { version = "=0.13.5-rc.7", path = "../apub_lib" } lemmy_utils = { version = "=0.13.5-rc.7", path = "../utils" } lemmy_db_schema = { version = "=0.13.5-rc.7", path = "../db_schema" } lemmy_db_views = { version = "=0.13.5-rc.7", path = "../db_views" } diff --git a/crates/api/src/site.rs b/crates/api/src/site.rs index 2797955a5..8d89d5db6 100644 --- a/crates/api/src/site.rs +++ b/crates/api/src/site.rs @@ -11,10 +11,10 @@ use lemmy_api_common::{ site::*, }; use lemmy_apub::{ - build_actor_id_from_shortname, fetcher::search::{search_by_apub_id, SearchableObjects}, - EndpointType, + get_actor_id_from_name, }; +use lemmy_apub_lib::webfinger::WebfingerType; use lemmy_db_schema::{ from_opt_str_to_opt_enum, newtypes::PersonId, @@ -174,11 +174,13 @@ impl Perform for Search { let listing_type: Option = from_opt_str_to_opt_enum(&data.listing_type); let search_type: SearchType = from_opt_str_to_opt_enum(&data.type_).unwrap_or(SearchType::All); let community_id = data.community_id; - let community_actor_id = data - .community_name - .as_ref() - .map(|t| build_actor_id_from_shortname(EndpointType::Community, t, &context.settings()).ok()) - .unwrap_or(None); + let community_actor_id = if let Some(name) = &data.community_name { + get_actor_id_from_name(WebfingerType::Group, name, context) + .await + .ok() + } else { + None + }; let creator_id = data.creator_id; match search_type { SearchType::Posts => { diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 690a50820..6c90e94e1 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -17,7 +17,7 @@ use lemmy_apub::{ CreateOrUpdateType, }, fetcher::post_or_comment::PostOrComment, - generate_apub_endpoint, + generate_local_apub_endpoint, EndpointType, }; use lemmy_db_schema::{ @@ -109,7 +109,7 @@ impl PerformCrud for CreateComment { let updated_comment: Comment = blocking(context.pool(), move |conn| -> Result { - let apub_id = generate_apub_endpoint( + let apub_id = generate_local_apub_endpoint( EndpointType::Comment, &inserted_comment_id.to_string(), &protocol_and_hostname, diff --git a/crates/api_crud/src/comment/read.rs b/crates/api_crud/src/comment/read.rs index 490c9670f..05f9f90fb 100644 --- a/crates/api_crud/src/comment/read.rs +++ b/crates/api_crud/src/comment/read.rs @@ -1,7 +1,8 @@ use crate::PerformCrud; use actix_web::web::Data; use lemmy_api_common::{blocking, comment::*, get_local_user_view_from_jwt_opt}; -use lemmy_apub::{build_actor_id_from_shortname, EndpointType}; +use lemmy_apub::get_actor_id_from_name; +use lemmy_apub_lib::webfinger::WebfingerType; use lemmy_db_schema::{ from_opt_str_to_opt_enum, traits::DeleteableOrRemoveable, @@ -34,11 +35,13 @@ impl PerformCrud for GetComments { let listing_type: Option = from_opt_str_to_opt_enum(&data.type_); let community_id = data.community_id; - let community_actor_id = data - .community_name - .as_ref() - .map(|t| build_actor_id_from_shortname(EndpointType::Community, t, &context.settings()).ok()) - .unwrap_or(None); + let community_actor_id = if let Some(name) = &data.community_name { + get_actor_id_from_name(WebfingerType::Group, name, context) + .await + .ok() + } else { + None + }; let saved_only = data.saved_only; let page = data.page; let limit = data.limit; diff --git a/crates/api_crud/src/community/create.rs b/crates/api_crud/src/community/create.rs index 8b7daeb7b..523ccf00d 100644 --- a/crates/api_crud/src/community/create.rs +++ b/crates/api_crud/src/community/create.rs @@ -8,9 +8,9 @@ use lemmy_api_common::{ }; use lemmy_apub::{ fetcher::object_id::ObjectId, - generate_apub_endpoint, generate_followers_url, generate_inbox_url, + generate_local_apub_endpoint, generate_shared_inbox_url, objects::community::ApubCommunity, EndpointType, @@ -67,7 +67,7 @@ impl PerformCrud for CreateCommunity { } // Double check for duplicate community actor_ids - let community_actor_id = generate_apub_endpoint( + let community_actor_id = generate_local_apub_endpoint( EndpointType::Community, &data.name, &context.settings().get_protocol_and_hostname(), diff --git a/crates/api_crud/src/community/read.rs b/crates/api_crud/src/community/read.rs index 91effae87..feaf110fb 100644 --- a/crates/api_crud/src/community/read.rs +++ b/crates/api_crud/src/community/read.rs @@ -2,11 +2,11 @@ use crate::PerformCrud; use actix_web::web::Data; use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt_opt}; use lemmy_apub::{ - build_actor_id_from_shortname, fetcher::object_id::ObjectId, + get_actor_id_from_name, objects::community::ApubCommunity, - EndpointType, }; +use lemmy_apub_lib::webfinger::WebfingerType; use lemmy_db_schema::{ from_opt_str_to_opt_enum, traits::DeleteableOrRemoveable, @@ -39,7 +39,7 @@ impl PerformCrud for GetCommunity { None => { let name = data.name.to_owned().unwrap_or_else(|| "main".to_string()); let community_actor_id = - build_actor_id_from_shortname(EndpointType::Community, &name, &context.settings())?; + get_actor_id_from_name(WebfingerType::Group, &name, context).await?; ObjectId::::new(community_actor_id) .dereference(context, &mut 0) diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 3e5fb41e1..a66410341 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -16,7 +16,7 @@ use lemmy_apub::{ CreateOrUpdateType, }, fetcher::post_or_comment::PostOrComment, - generate_apub_endpoint, + generate_local_apub_endpoint, EndpointType, }; use lemmy_db_schema::{ @@ -98,7 +98,7 @@ impl PerformCrud for CreatePost { let inserted_post_id = inserted_post.id; let protocol_and_hostname = context.settings().get_protocol_and_hostname(); let updated_post = blocking(context.pool(), move |conn| -> Result { - let apub_id = generate_apub_endpoint( + let apub_id = generate_local_apub_endpoint( EndpointType::Post, &inserted_post_id.to_string(), &protocol_and_hostname, diff --git a/crates/api_crud/src/post/read.rs b/crates/api_crud/src/post/read.rs index 901d1e935..d2a46f53e 100644 --- a/crates/api_crud/src/post/read.rs +++ b/crates/api_crud/src/post/read.rs @@ -1,7 +1,8 @@ use crate::PerformCrud; use actix_web::web::Data; use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, mark_post_as_read, post::*}; -use lemmy_apub::{build_actor_id_from_shortname, EndpointType}; +use lemmy_apub::get_actor_id_from_name; +use lemmy_apub_lib::webfinger::WebfingerType; use lemmy_db_schema::{ from_opt_str_to_opt_enum, traits::DeleteableOrRemoveable, @@ -136,11 +137,13 @@ impl PerformCrud for GetPosts { let page = data.page; let limit = data.limit; let community_id = data.community_id; - let community_actor_id = data - .community_name - .as_ref() - .map(|t| build_actor_id_from_shortname(EndpointType::Community, t, &context.settings()).ok()) - .unwrap_or(None); + let community_actor_id = if let Some(name) = &data.community_name { + get_actor_id_from_name(WebfingerType::Group, name, context) + .await + .ok() + } else { + None + }; let saved_only = data.saved_only; let mut posts = blocking(context.pool(), move |conn| { diff --git a/crates/api_crud/src/private_message/create.rs b/crates/api_crud/src/private_message/create.rs index d6560be25..c7bca4e02 100644 --- a/crates/api_crud/src/private_message/create.rs +++ b/crates/api_crud/src/private_message/create.rs @@ -11,7 +11,7 @@ use lemmy_apub::{ private_message::create_or_update::CreateOrUpdatePrivateMessage, CreateOrUpdateType, }, - generate_apub_endpoint, + generate_local_apub_endpoint, EndpointType, }; use lemmy_db_schema::{ @@ -67,7 +67,7 @@ impl PerformCrud for CreatePrivateMessage { let updated_private_message = blocking( context.pool(), move |conn| -> Result { - let apub_id = generate_apub_endpoint( + let apub_id = generate_local_apub_endpoint( EndpointType::PrivateMessage, &inserted_private_message_id.to_string(), &protocol_and_hostname, diff --git a/crates/api_crud/src/user/create.rs b/crates/api_crud/src/user/create.rs index ce37cd6a0..78b204ff9 100644 --- a/crates/api_crud/src/user/create.rs +++ b/crates/api_crud/src/user/create.rs @@ -2,9 +2,9 @@ use crate::PerformCrud; use actix_web::web::Data; use lemmy_api_common::{blocking, honeypot_check, password_length_check, person::*}; use lemmy_apub::{ - generate_apub_endpoint, generate_followers_url, generate_inbox_url, + generate_local_apub_endpoint, generate_shared_inbox_url, EndpointType, }; @@ -96,7 +96,7 @@ impl PerformCrud for Register { if !is_valid_actor_name(&data.username, context.settings().actor_name_max_length) { return Err(ApiError::err_plain("invalid_username").into()); } - let actor_id = generate_apub_endpoint( + let actor_id = generate_local_apub_endpoint( EndpointType::Person, &data.username, &context.settings().get_protocol_and_hostname(), @@ -179,7 +179,7 @@ impl PerformCrud for Register { Ok(c) => c, Err(_e) => { let default_community_name = "main"; - let actor_id = generate_apub_endpoint( + let actor_id = generate_local_apub_endpoint( EndpointType::Community, default_community_name, &protocol_and_hostname, diff --git a/crates/api_crud/src/user/read.rs b/crates/api_crud/src/user/read.rs index a5b69ba45..b649c8fbb 100644 --- a/crates/api_crud/src/user/read.rs +++ b/crates/api_crud/src/user/read.rs @@ -2,11 +2,11 @@ use crate::PerformCrud; use actix_web::web::Data; use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, person::*}; use lemmy_apub::{ - build_actor_id_from_shortname, fetcher::object_id::ObjectId, + get_actor_id_from_name, objects::person::ApubPerson, - EndpointType, }; +use lemmy_apub_lib::webfinger::WebfingerType; use lemmy_db_schema::{from_opt_str_to_opt_enum, SortType}; use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder}; use lemmy_db_views_actor::{ @@ -46,8 +46,7 @@ impl PerformCrud for GetPersonDetails { .username .to_owned() .unwrap_or_else(|| "admin".to_string()); - let actor_id = - build_actor_id_from_shortname(EndpointType::Person, &name, &context.settings())?; + let actor_id = get_actor_id_from_name(WebfingerType::Person, &name, context).await?; let person = ObjectId::::new(actor_id) .dereference(context, &mut 0) diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs index 675798b6f..a900ad3d1 100644 --- a/crates/apub/src/lib.rs +++ b/crates/apub/src/lib.rs @@ -12,7 +12,11 @@ extern crate lazy_static; use crate::fetcher::post_or_comment::PostOrComment; use anyhow::{anyhow, Context}; use lemmy_api_common::blocking; -use lemmy_apub_lib::{activity_queue::send_activity, traits::ActorType}; +use lemmy_apub_lib::{ + activity_queue::send_activity, + traits::ActorType, + webfinger::{webfinger_resolve_actor, WebfingerType}, +}; use lemmy_db_schema::{ newtypes::{CommunityId, DbUrl}, source::{activity::Activity, person::Person}, @@ -111,7 +115,7 @@ pub enum EndpointType { } /// Generates an apub endpoint for a given domain, IE xyz.tld -fn generate_apub_endpoint_for_domain( +pub fn generate_local_apub_endpoint( endpoint_type: EndpointType, name: &str, domain: &str, @@ -127,15 +131,6 @@ fn generate_apub_endpoint_for_domain( Ok(Url::parse(&format!("{}/{}/{}", domain, point, name))?.into()) } -/// Generates the ActivityPub ID for a given object type and ID. -pub fn generate_apub_endpoint( - endpoint_type: EndpointType, - name: &str, - protocol_and_hostname: &str, -) -> Result { - generate_apub_endpoint_for_domain(endpoint_type, name, protocol_and_hostname) -} - pub fn generate_followers_url(actor_id: &DbUrl) -> Result { Ok(Url::parse(&format!("{}/followers", actor_id))?.into()) } @@ -169,23 +164,31 @@ fn generate_moderators_url(community_id: &DbUrl) -> Result { /// Takes in a shortname of the type dessalines@xyz.tld or dessalines (assumed to be local), and outputs the actor id. /// Used in the API for communities and users. -pub fn build_actor_id_from_shortname( - endpoint_type: EndpointType, +pub async fn get_actor_id_from_name( + webfinger_type: WebfingerType, short_name: &str, - settings: &Settings, -) -> Result { + context: &LemmyContext, +) -> Result { let split = short_name.split('@').collect::>(); let name = split[0]; // If there's no @, its local - let domain = if split.len() == 1 { - settings.get_protocol_and_hostname() + if split.len() == 1 { + let domain = context.settings().get_protocol_and_hostname(); + let endpoint_type = match webfinger_type { + WebfingerType::Person => EndpointType::Person, + WebfingerType::Group => EndpointType::Community, + }; + Ok(generate_local_apub_endpoint(endpoint_type, name, &domain)?) } else { - format!("{}://{}", settings.get_protocol_string(), split[1]) - }; - - generate_apub_endpoint_for_domain(endpoint_type, name, &domain) + let protocol = context.settings().get_protocol_string(); + Ok( + webfinger_resolve_actor(name, split[1], webfinger_type, context.client(), protocol) + .await? + .into(), + ) + } } /// Store a sent or received activity in the database, for logging purposes. These records are not diff --git a/src/code_migrations.rs b/src/code_migrations.rs index 8910733a5..2feefbdfb 100644 --- a/src/code_migrations.rs +++ b/src/code_migrations.rs @@ -4,9 +4,9 @@ use diesel::{ *, }; use lemmy_apub::{ - generate_apub_endpoint, generate_followers_url, generate_inbox_url, + generate_local_apub_endpoint, generate_shared_inbox_url, EndpointType, }; @@ -58,7 +58,7 @@ fn user_updates_2020_04_02( let form = PersonForm { name: cperson.name.to_owned(), - actor_id: Some(generate_apub_endpoint( + actor_id: Some(generate_local_apub_endpoint( EndpointType::Person, &cperson.name, protocol_and_hostname, @@ -93,7 +93,7 @@ fn community_updates_2020_04_02( for ccommunity in &incorrect_communities { let keypair = generate_actor_keypair()?; - let community_actor_id = generate_apub_endpoint( + let community_actor_id = generate_local_apub_endpoint( EndpointType::Community, &ccommunity.name, protocol_and_hostname, @@ -143,7 +143,7 @@ fn post_updates_2020_04_03( .load::(conn)?; for cpost in &incorrect_posts { - let apub_id = generate_apub_endpoint( + let apub_id = generate_local_apub_endpoint( EndpointType::Post, &cpost.id.to_string(), protocol_and_hostname, @@ -171,7 +171,7 @@ fn comment_updates_2020_04_03( .load::(conn)?; for ccomment in &incorrect_comments { - let apub_id = generate_apub_endpoint( + let apub_id = generate_local_apub_endpoint( EndpointType::Comment, &ccomment.id.to_string(), protocol_and_hostname, @@ -199,7 +199,7 @@ fn private_message_updates_2020_05_05( .load::(conn)?; for cpm in &incorrect_pms { - let apub_id = generate_apub_endpoint( + let apub_id = generate_local_apub_endpoint( EndpointType::PrivateMessage, &cpm.id.to_string(), protocol_and_hostname,