]> Untitled Git - lemmy.git/blob - crates/apub/src/http/person.rs
Implement instance actor (#1798)
[lemmy.git] / crates / apub / src / http / person.rs
1 use crate::{
2   activity_lists::PersonInboxActivities,
3   context::WithContext,
4   generate_outbox_url,
5   http::{
6     create_apub_response,
7     create_apub_tombstone_response,
8     payload_to_string,
9     receive_activity,
10     ActivityCommonFields,
11   },
12   objects::person::ApubPerson,
13   protocol::collections::empty_outbox::EmptyOutbox,
14 };
15 use actix_web::{web, web::Payload, HttpRequest, HttpResponse};
16 use lemmy_api_common::blocking;
17 use lemmy_apub_lib::traits::ApubObject;
18 use lemmy_db_schema::{source::person::Person, traits::ApubActor};
19 use lemmy_utils::LemmyError;
20 use lemmy_websocket::LemmyContext;
21 use serde::Deserialize;
22 use tracing::info;
23
24 #[derive(Deserialize)]
25 pub struct PersonQuery {
26   user_name: String,
27 }
28
29 /// Return the ActivityPub json representation of a local person over HTTP.
30 #[tracing::instrument(skip_all)]
31 pub(crate) async fn get_apub_person_http(
32   info: web::Path<PersonQuery>,
33   context: web::Data<LemmyContext>,
34 ) -> Result<HttpResponse, LemmyError> {
35   let user_name = info.into_inner().user_name;
36   // TODO: this needs to be able to read deleted persons, so that it can send tombstones
37   let person: ApubPerson = blocking(context.pool(), move |conn| {
38     Person::read_from_name(conn, &user_name)
39   })
40   .await??
41   .into();
42
43   if !person.deleted {
44     let apub = person.into_apub(&context).await?;
45
46     Ok(create_apub_response(&apub))
47   } else {
48     Ok(create_apub_tombstone_response(&person.to_tombstone()?))
49   }
50 }
51
52 #[tracing::instrument(skip_all)]
53 pub async fn person_inbox(
54   request: HttpRequest,
55   payload: Payload,
56   _path: web::Path<String>,
57   context: web::Data<LemmyContext>,
58 ) -> Result<HttpResponse, LemmyError> {
59   let unparsed = payload_to_string(payload).await?;
60   info!("Received person inbox activity {}", unparsed);
61   let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?;
62   let activity = serde_json::from_str::<WithContext<PersonInboxActivities>>(&unparsed)?;
63   receive_person_inbox(activity.inner(), activity_data, request, &context).await
64 }
65
66 pub(in crate::http) async fn receive_person_inbox(
67   activity: PersonInboxActivities,
68   activity_data: ActivityCommonFields,
69   request: HttpRequest,
70   context: &LemmyContext,
71 ) -> Result<HttpResponse, LemmyError> {
72   receive_activity(request, activity, activity_data, context).await
73 }
74
75 #[tracing::instrument(skip_all)]
76 pub(crate) async fn get_apub_person_outbox(
77   info: web::Path<PersonQuery>,
78   context: web::Data<LemmyContext>,
79 ) -> Result<HttpResponse, LemmyError> {
80   let person = blocking(context.pool(), move |conn| {
81     Person::read_from_name(conn, &info.user_name)
82   })
83   .await??;
84   let outbox_id = generate_outbox_url(&person.actor_id)?.into();
85   let outbox = EmptyOutbox::new(outbox_id).await?;
86   Ok(create_apub_response(&outbox))
87 }