diff --git a/server/src/apub/community.rs b/server/src/apub/community.rs index 8c0fb1606..31bf146af 100644 --- a/server/src/apub/community.rs +++ b/server/src/apub/community.rs @@ -1,4 +1,4 @@ -use crate::apub::{create_apub_response, make_apub_endpoint}; +use crate::apub::{create_apub_response, make_apub_endpoint, EndpointType}; use crate::convert_datetime; use crate::db::community::Community; use crate::db::community_view::CommunityFollowerView; @@ -28,7 +28,7 @@ pub async fn get_apub_community( db: web::Data>>, ) -> Result, Error> { let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?; - let base_url = make_apub_endpoint("c", &community.name); + let base_url = make_apub_endpoint(EndpointType::Community, &community.name); let mut group = Group::default(); let oprops: &mut ObjectProperties = group.as_mut(); @@ -38,7 +38,10 @@ pub async fn get_apub_community( .set_id(base_url.to_owned())? .set_name_xsd_string(community.title.to_owned())? .set_published(convert_datetime(community.published))? - .set_attributed_to_xsd_any_uri(make_apub_endpoint("u", &community.creator_id))?; + .set_attributed_to_xsd_any_uri(make_apub_endpoint( + EndpointType::User, + &community.creator_id.to_string(), + ))?; if let Some(u) = community.updated.to_owned() { oprops.set_updated(convert_datetime(u))?; @@ -61,7 +64,7 @@ pub async fn get_apub_community_followers( db: web::Data>>, ) -> Result, Error> { let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?; - let base_url = make_apub_endpoint("c", &community.name); + let base_url = make_apub_endpoint(EndpointType::Community, &community.name); let connection = establish_unpooled_connection(); //As we are an object, we validated that the community id was valid @@ -84,7 +87,7 @@ pub async fn get_apub_community_outbox( db: web::Data>>, ) -> Result, Error> { let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?; - let base_url = make_apub_endpoint("c", &community.name); + let base_url = make_apub_endpoint(EndpointType::Community, &community.name); let connection = establish_unpooled_connection(); //As we are an object, we validated that the community id was valid diff --git a/server/src/apub/mod.rs b/server/src/apub/mod.rs index d648e902c..c0e881af4 100644 --- a/server/src/apub/mod.rs +++ b/server/src/apub/mod.rs @@ -6,7 +6,6 @@ use crate::Settings; use actix_web::body::Body; use actix_web::HttpResponse; -use std::fmt::Display; use url::Url; fn create_apub_response(json_data: String) -> HttpResponse { @@ -15,15 +14,25 @@ fn create_apub_response(json_data: String) -> HttpResponse { .body(json_data) } -// TODO: this should take an enum community/user/post for `point` -// TODO: also not sure what exactly `value` should be (numeric id, name string, ...) -fn make_apub_endpoint(point: S, value: T) -> Url { +enum EndpointType { + Community, + User, + Post, +} + +fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url { + let point = match endpoint_type { + EndpointType::Community => "c", + EndpointType::User => "u", + EndpointType::Post => "p", + }; + Url::parse(&format!( "{}://{}/federation/{}/{}", get_apub_protocol_string(), Settings::get().hostname, point, - value + name )) .unwrap() } diff --git a/server/src/apub/post.rs b/server/src/apub/post.rs index 61b5a78da..06340396e 100644 --- a/server/src/apub/post.rs +++ b/server/src/apub/post.rs @@ -1,12 +1,35 @@ -use crate::apub::make_apub_endpoint; +use crate::apub::{create_apub_response, make_apub_endpoint, EndpointType}; use crate::convert_datetime; use crate::db::post_view::PostView; use activitystreams::{object::apub::Page, object::properties::ObjectProperties}; +use actix_web::body::Body; +use actix_web::web::Path; +use actix_web::{web, HttpResponse}; +use diesel::r2d2::{ConnectionManager, Pool}; +use diesel::PgConnection; use failure::Error; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct PostQuery { + post_id: String, +} + +pub async fn get_apub_post( + info: Path, + db: web::Data>>, +) -> Result, Error> { + let id = info.post_id.parse::()?; + // TODO: shows error: missing field `user_name` + let post = PostView::read(&&db.get()?, id, None)?; + Ok(create_apub_response(serde_json::to_string( + &post.as_page()?, + )?)) +} impl PostView { pub fn as_page(&self) -> Result { - let base_url = make_apub_endpoint("post", self.id); + let base_url = make_apub_endpoint(EndpointType::Post, &self.id.to_string()); let mut page = Page::default(); let oprops: &mut ObjectProperties = page.as_mut(); @@ -16,16 +39,20 @@ impl PostView { .set_id(base_url)? .set_name_xsd_string(self.name.to_owned())? .set_published(convert_datetime(self.published))? - .set_attributed_to_xsd_any_uri(make_apub_endpoint("u", &self.creator_id))?; + .set_attributed_to_xsd_any_uri(make_apub_endpoint( + EndpointType::User, + &self.creator_id.to_string(), + ))?; if let Some(body) = &self.body { oprops.set_content_xsd_string(body.to_owned())?; } // TODO: hacky code because we get self.url == Some("") - let url = self.url.as_ref(); - if url.is_some() && !url.unwrap().is_empty() { - oprops.set_url_xsd_any_uri(url.unwrap().to_owned())?; + // https://github.com/dessalines/lemmy/issues/602 + let url = self.url.as_ref().filter(|u| !u.is_empty()); + if let Some(u) = url { + oprops.set_url_xsd_any_uri(u.to_owned())?; } if let Some(u) = self.updated { @@ -35,5 +62,3 @@ impl PostView { Ok(page) } } - -// TODO: need to serve this via actix diff --git a/server/src/apub/user.rs b/server/src/apub/user.rs index 005ca9de7..0bc90b0cc 100644 --- a/server/src/apub/user.rs +++ b/server/src/apub/user.rs @@ -1,15 +1,15 @@ -use crate::apub::{make_apub_endpoint, create_apub_response}; +use crate::apub::{create_apub_response, make_apub_endpoint, EndpointType}; use crate::convert_datetime; use crate::db::user::User_; use activitystreams::{actor::apub::Person, context, object::properties::ObjectProperties}; use actix_web::body::Body; use actix_web::web::Path; use actix_web::HttpResponse; -use failure::Error; -use serde::Deserialize; +use actix_web::{web, Result}; use diesel::r2d2::{ConnectionManager, Pool}; use diesel::PgConnection; -use actix_web::{web, Result}; +use failure::Error; +use serde::Deserialize; #[derive(Deserialize)] pub struct UserQuery { @@ -18,16 +18,17 @@ pub struct UserQuery { pub async fn get_apub_user( info: Path, - db: web::Data>>,) -> Result, Error> { + db: web::Data>>, +) -> Result, Error> { let user = User_::find_by_email_or_username(&&db.get()?, &info.user_name)?; - let base_url = make_apub_endpoint("u", &user.name); + let base_url = make_apub_endpoint(EndpointType::User, &user.name); let mut person = Person::default(); let oprops: &mut ObjectProperties = person.as_mut(); oprops - .set_context_xsd_any_uri(context())? - .set_id(base_url.to_string())? - .set_published(convert_datetime(user.published))?; + .set_context_xsd_any_uri(context())? + .set_id(base_url.to_string())? + .set_published(convert_datetime(user.published))?; if let Some(u) = user.updated { oprops.set_updated(convert_datetime(u))?; @@ -38,11 +39,11 @@ pub async fn get_apub_user( } person - .ap_actor_props - .set_inbox(format!("{}/inbox", &base_url))? - .set_outbox(format!("{}/outbox", &base_url))? - .set_following(format!("{}/following", &base_url))? - .set_liked(format!("{}/liked", &base_url))?; + .ap_actor_props + .set_inbox(format!("{}/inbox", &base_url))? + .set_outbox(format!("{}/outbox", &base_url))? + .set_following(format!("{}/following", &base_url))? + .set_liked(format!("{}/liked", &base_url))?; Ok(create_apub_response(serde_json::to_string(&person)?)) } diff --git a/server/src/routes/federation.rs b/server/src/routes/federation.rs index 99b4d2c0b..fbe8d795a 100644 --- a/server/src/routes/federation.rs +++ b/server/src/routes/federation.rs @@ -28,6 +28,10 @@ pub fn config(cfg: &mut web::ServiceConfig) { "/federation/u/{user_name}", web::get().to(apub::user::get_apub_user), ) + .route( + "/federation/p/{post_id}", + web::get().to(apub::user::get_apub_user), + ) // TODO: we should be able to remove this but somehow that breaks the remote community list .route( "/api/v1/communities/list",