]> Untitled Git - lemmy.git/blob - crates/apub/src/http/person.rs
Rewrite community followers and user outbox to use our own structs
[lemmy.git] / crates / apub / src / http / person.rs
1 use crate::{
2   activities::{
3     community::announce::{AnnouncableActivities, AnnounceActivity},
4     following::accept::AcceptFollowCommunity,
5     private_message::{
6       create_or_update::CreateOrUpdatePrivateMessage,
7       delete::DeletePrivateMessage,
8       undo_delete::UndoDeletePrivateMessage,
9     },
10   },
11   collections::user_outbox::UserOutbox,
12   context::WithContext,
13   http::{
14     create_apub_response,
15     create_apub_tombstone_response,
16     payload_to_string,
17     receive_activity,
18   },
19   objects::person::ApubPerson,
20 };
21 use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
22 use lemmy_api_common::blocking;
23 use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler, ApubObject};
24 use lemmy_db_schema::source::person::Person;
25 use lemmy_utils::LemmyError;
26 use lemmy_websocket::LemmyContext;
27 use log::info;
28 use serde::{Deserialize, Serialize};
29
30 #[derive(Deserialize)]
31 pub struct PersonQuery {
32   user_name: String,
33 }
34
35 /// Return the ActivityPub json representation of a local person over HTTP.
36 pub(crate) async fn get_apub_person_http(
37   info: web::Path<PersonQuery>,
38   context: web::Data<LemmyContext>,
39 ) -> Result<HttpResponse<Body>, LemmyError> {
40   let user_name = info.into_inner().user_name;
41   // TODO: this needs to be able to read deleted persons, so that it can send tombstones
42   let person: ApubPerson = blocking(context.pool(), move |conn| {
43     Person::find_by_name(conn, &user_name)
44   })
45   .await??
46   .into();
47
48   if !person.deleted {
49     let apub = person.to_apub(&context).await?;
50
51     Ok(create_apub_response(&apub))
52   } else {
53     Ok(create_apub_tombstone_response(&person.to_tombstone()?))
54   }
55 }
56
57 #[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
58 #[serde(untagged)]
59 #[activity_handler(LemmyContext)]
60 pub enum PersonInboxActivities {
61   AcceptFollowCommunity(AcceptFollowCommunity),
62   /// Some activities can also be sent from user to user, eg a comment with mentions
63   AnnouncableActivities(AnnouncableActivities),
64   CreateOrUpdatePrivateMessage(CreateOrUpdatePrivateMessage),
65   DeletePrivateMessage(DeletePrivateMessage),
66   UndoDeletePrivateMessage(UndoDeletePrivateMessage),
67   AnnounceActivity(Box<AnnounceActivity>),
68 }
69
70 pub async fn person_inbox(
71   request: HttpRequest,
72   payload: Payload,
73   _path: web::Path<String>,
74   context: web::Data<LemmyContext>,
75 ) -> Result<HttpResponse, LemmyError> {
76   let unparsed = payload_to_string(payload).await?;
77   info!("Received person inbox activity {}", unparsed);
78   let activity = serde_json::from_str::<WithContext<PersonInboxActivities>>(&unparsed)?;
79   receive_person_inbox(activity.inner(), request, &context).await
80 }
81
82 pub(in crate::http) async fn receive_person_inbox(
83   activity: PersonInboxActivities,
84   request: HttpRequest,
85   context: &LemmyContext,
86 ) -> Result<HttpResponse, LemmyError> {
87   receive_activity(request, activity, context).await
88 }
89
90 pub(crate) async fn get_apub_person_outbox(
91   info: web::Path<PersonQuery>,
92   context: web::Data<LemmyContext>,
93 ) -> Result<HttpResponse<Body>, LemmyError> {
94   let person = blocking(context.pool(), move |conn| {
95     Person::find_by_name(conn, &info.user_name)
96   })
97   .await??;
98   let outbox = UserOutbox::new(person).await?;
99   Ok(create_apub_response(&outbox))
100 }