]> Untitled Git - lemmy.git/blob - crates/apub/src/http/person.rs
Rewrite remaining activities (#1712)
[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   extensions::context::lemmy_context,
12   http::{
13     create_apub_response,
14     create_apub_tombstone_response,
15     payload_to_string,
16     receive_activity,
17   },
18   objects::ToApub,
19   ActorType,
20 };
21 use activitystreams::{
22   base::BaseExt,
23   collection::{CollectionExt, OrderedCollection},
24 };
25 use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
26 use lemmy_api_common::blocking;
27 use lemmy_apub_lib::{ActivityFields, ActivityHandler};
28 use lemmy_db_queries::source::person::Person_;
29 use lemmy_db_schema::source::person::Person;
30 use lemmy_utils::LemmyError;
31 use lemmy_websocket::LemmyContext;
32 use log::trace;
33 use serde::{Deserialize, Serialize};
34 use url::Url;
35
36 #[derive(Deserialize)]
37 pub struct PersonQuery {
38   user_name: String,
39 }
40
41 /// Return the ActivityPub json representation of a local person over HTTP.
42 pub(crate) async fn get_apub_person_http(
43   info: web::Path<PersonQuery>,
44   context: web::Data<LemmyContext>,
45 ) -> Result<HttpResponse<Body>, LemmyError> {
46   let user_name = info.into_inner().user_name;
47   // TODO: this needs to be able to read deleted persons, so that it can send tombstones
48   let person = blocking(context.pool(), move |conn| {
49     Person::find_by_name(conn, &user_name)
50   })
51   .await??;
52
53   if !person.deleted {
54     let apub = person.to_apub(context.pool()).await?;
55
56     Ok(create_apub_response(&apub))
57   } else {
58     Ok(create_apub_tombstone_response(&person.to_tombstone()?))
59   }
60 }
61
62 #[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
63 #[serde(untagged)]
64 pub enum PersonInboxActivities {
65   AcceptFollowCommunity(AcceptFollowCommunity),
66   /// Some activities can also be sent from user to user, eg a comment with mentions
67   AnnouncableActivities(AnnouncableActivities),
68   CreateOrUpdatePrivateMessage(CreateOrUpdatePrivateMessage),
69   DeletePrivateMessage(DeletePrivateMessage),
70   UndoDeletePrivateMessage(UndoDeletePrivateMessage),
71   AnnounceActivity(Box<AnnounceActivity>),
72 }
73
74 pub async fn person_inbox(
75   request: HttpRequest,
76   payload: Payload,
77   _path: web::Path<String>,
78   context: web::Data<LemmyContext>,
79 ) -> Result<HttpResponse, LemmyError> {
80   let unparsed = payload_to_string(payload).await?;
81   trace!("Received person inbox activity {}", unparsed);
82   let activity = serde_json::from_str::<PersonInboxActivities>(&unparsed)?;
83   receive_person_inbox(activity, request, &context).await
84 }
85
86 pub(in crate::http) async fn receive_person_inbox(
87   activity: PersonInboxActivities,
88   request: HttpRequest,
89   context: &LemmyContext,
90 ) -> Result<HttpResponse, LemmyError> {
91   receive_activity(request, activity, context).await
92 }
93
94 pub(crate) async fn get_apub_person_outbox(
95   info: web::Path<PersonQuery>,
96   context: web::Data<LemmyContext>,
97 ) -> Result<HttpResponse<Body>, LemmyError> {
98   let person = blocking(context.pool(), move |conn| {
99     Person::find_by_name(conn, &info.user_name)
100   })
101   .await??;
102   // TODO: populate the person outbox
103   let mut collection = OrderedCollection::new();
104   collection
105     .set_many_items(Vec::<Url>::new())
106     .set_many_contexts(lemmy_context())
107     .set_id(person.get_outbox_url()?)
108     .set_total_items(0_u64);
109   Ok(create_apub_response(&collection))
110 }
111
112 pub(crate) async fn get_apub_person_inbox(
113   info: web::Path<PersonQuery>,
114   context: web::Data<LemmyContext>,
115 ) -> Result<HttpResponse<Body>, LemmyError> {
116   let person = blocking(context.pool(), move |conn| {
117     Person::find_by_name(conn, &info.user_name)
118   })
119   .await??;
120
121   let mut collection = OrderedCollection::new();
122   collection
123     .set_id(person.inbox_url.into())
124     .set_many_contexts(lemmy_context());
125   Ok(create_apub_response(&collection))
126 }