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