]> Untitled Git - lemmy.git/blobdiff - crates/apub/src/http/mod.rs
Split activity table into sent and received parts (fixes #3103) (#3583)
[lemmy.git] / crates / apub / src / http / mod.rs
index 6bf4bbde6a3c6e8a6c9d87340d9b99296e00be08..c261d9e4929c363385e10756d491967a25f29148 100644 (file)
@@ -1,52 +1,86 @@
-use crate::APUB_JSON_CONTENT_TYPE;
-use actix_web::{body::Body, web, HttpResponse};
+use crate::{
+  activity_lists::SharedInboxActivities,
+  fetcher::user_or_community::UserOrCommunity,
+  protocol::objects::tombstone::Tombstone,
+  CONTEXT,
+};
+use activitypub_federation::{
+  actix_web::inbox::receive_activity,
+  config::Data,
+  protocol::context::WithContext,
+  FEDERATION_CONTENT_TYPE,
+};
+use actix_web::{web, web::Bytes, HttpRequest, HttpResponse};
 use http::StatusCode;
-use lemmy_api_structs::blocking;
-use lemmy_db_queries::source::activity::Activity_;
-use lemmy_db_schema::source::activity::Activity;
-use lemmy_utils::{settings::structs::Settings, LemmyError};
-use lemmy_websocket::LemmyContext;
+use lemmy_api_common::context::LemmyContext;
+use lemmy_db_schema::source::activity::SentActivity;
+use lemmy_utils::error::{LemmyError, LemmyErrorType, LemmyResult};
 use serde::{Deserialize, Serialize};
+use std::ops::Deref;
 use url::Url;
 
-pub mod comment;
-pub mod community;
-pub mod post;
-pub mod user;
+mod comment;
+mod community;
+mod person;
+mod post;
+pub mod routes;
+pub mod site;
+
+pub async fn shared_inbox(
+  request: HttpRequest,
+  body: Bytes,
+  data: Data<LemmyContext>,
+) -> LemmyResult<HttpResponse> {
+  receive_activity::<SharedInboxActivities, UserOrCommunity, LemmyContext>(request, body, &data)
+    .await
+}
 
 /// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
 /// headers.
-fn create_apub_response<T>(data: &T) -> HttpResponse<Body>
+///
+/// actix-web doesn't allow pretty-print for json so we need to do this manually.
+fn create_apub_response<T>(data: &T) -> LemmyResult<HttpResponse>
 where
   T: Serialize,
 {
-  HttpResponse::Ok()
-    .content_type(APUB_JSON_CONTENT_TYPE)
-    .json(data)
+  let json = serde_json::to_string_pretty(&WithContext::new(data, CONTEXT.clone()))?;
+
+  Ok(
+    HttpResponse::Ok()
+      .content_type(FEDERATION_CONTENT_TYPE)
+      .body(json),
+  )
 }
 
-fn create_apub_tombstone_response<T>(data: &T) -> HttpResponse<Body>
-where
-  T: Serialize,
-{
-  HttpResponse::Gone()
-    .content_type(APUB_JSON_CONTENT_TYPE)
-    .status(StatusCode::GONE)
-    .json(data)
+fn create_apub_tombstone_response<T: Into<Url>>(id: T) -> LemmyResult<HttpResponse> {
+  let tombstone = Tombstone::new(id.into());
+  let json = serde_json::to_string_pretty(&WithContext::new(tombstone, CONTEXT.deref().clone()))?;
+
+  Ok(
+    HttpResponse::Gone()
+      .content_type(FEDERATION_CONTENT_TYPE)
+      .status(StatusCode::GONE)
+      .body(json),
+  )
+}
+
+fn err_object_not_local() -> LemmyError {
+  LemmyErrorType::ObjectNotLocal.into()
 }
 
 #[derive(Deserialize)]
-pub struct CommunityQuery {
+pub struct ActivityQuery {
   type_: String,
   id: String,
 }
 
-/// Return the ActivityPub json representation of a local community over HTTP.
-pub async fn get_activity(
-  info: web::Path<CommunityQuery>,
+/// Return the ActivityPub json representation of a local activity over HTTP.
+#[tracing::instrument(skip_all)]
+pub(crate) async fn get_activity(
+  info: web::Path<ActivityQuery>,
   context: web::Data<LemmyContext>,
-) -> Result<HttpResponse<Body>, LemmyError> {
-  let settings = Settings::get();
+) -> Result<HttpResponse, LemmyError> {
+  let settings = context.settings();
   let activity_id = Url::parse(&format!(
     "{}/activities/{}/{}",
     settings.get_protocol_and_hostname(),
@@ -54,15 +88,12 @@ pub async fn get_activity(
     info.id
   ))?
   .into();
-  let activity = blocking(context.pool(), move |conn| {
-    Activity::read_from_apub_id(&conn, &activity_id)
-  })
-  .await??;
+  let activity = SentActivity::read_from_apub_id(&mut context.pool(), &activity_id).await?;
 
-  let sensitive = activity.sensitive.unwrap_or(true);
-  if !activity.local || sensitive {
-    Ok(HttpResponse::NotFound().finish())
+  let sensitive = activity.sensitive;
+  if sensitive {
+    Ok(HttpResponse::Forbidden().finish())
   } else {
-    Ok(create_apub_response(&activity.data))
+    create_apub_response(&activity.data)
   }
 }