]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/create_or_update/private_message.rs
Split activity table into sent and received parts (fixes #3103) (#3583)
[lemmy.git] / crates / apub / src / activities / create_or_update / private_message.rs
1 use crate::{
2   activities::{generate_activity_id, send_lemmy_activity, verify_person},
3   insert_received_activity,
4   objects::{person::ApubPerson, private_message::ApubPrivateMessage},
5   protocol::activities::{
6     create_or_update::chat_message::CreateOrUpdateChatMessage,
7     CreateOrUpdateType,
8   },
9   SendActivity,
10 };
11 use activitypub_federation::{
12   config::Data,
13   protocol::verification::verify_domains_match,
14   traits::{ActivityHandler, Actor, Object},
15 };
16 use lemmy_api_common::{
17   context::LemmyContext,
18   private_message::{CreatePrivateMessage, EditPrivateMessage, PrivateMessageResponse},
19 };
20 use lemmy_db_schema::{
21   newtypes::PersonId,
22   source::{person::Person, private_message::PrivateMessage},
23   traits::Crud,
24 };
25 use lemmy_utils::error::LemmyError;
26 use url::Url;
27
28 #[async_trait::async_trait]
29 impl SendActivity for CreatePrivateMessage {
30   type Response = PrivateMessageResponse;
31
32   async fn send_activity(
33     _request: &Self,
34     response: &Self::Response,
35     context: &Data<LemmyContext>,
36   ) -> Result<(), LemmyError> {
37     CreateOrUpdateChatMessage::send(
38       &response.private_message_view.private_message,
39       response.private_message_view.creator.id,
40       CreateOrUpdateType::Create,
41       context,
42     )
43     .await
44   }
45 }
46 #[async_trait::async_trait]
47 impl SendActivity for EditPrivateMessage {
48   type Response = PrivateMessageResponse;
49
50   async fn send_activity(
51     _request: &Self,
52     response: &Self::Response,
53     context: &Data<LemmyContext>,
54   ) -> Result<(), LemmyError> {
55     CreateOrUpdateChatMessage::send(
56       &response.private_message_view.private_message,
57       response.private_message_view.creator.id,
58       CreateOrUpdateType::Update,
59       context,
60     )
61     .await
62   }
63 }
64
65 impl CreateOrUpdateChatMessage {
66   #[tracing::instrument(skip_all)]
67   async fn send(
68     private_message: &PrivateMessage,
69     sender_id: PersonId,
70     kind: CreateOrUpdateType,
71     context: &Data<LemmyContext>,
72   ) -> Result<(), LemmyError> {
73     let recipient_id = private_message.recipient_id;
74     let sender: ApubPerson = Person::read(&mut context.pool(), sender_id).await?.into();
75     let recipient: ApubPerson = Person::read(&mut context.pool(), recipient_id)
76       .await?
77       .into();
78
79     let id = generate_activity_id(
80       kind.clone(),
81       &context.settings().get_protocol_and_hostname(),
82     )?;
83     let create_or_update = CreateOrUpdateChatMessage {
84       id: id.clone(),
85       actor: sender.id().into(),
86       to: [recipient.id().into()],
87       object: ApubPrivateMessage(private_message.clone())
88         .into_json(context)
89         .await?,
90       kind,
91     };
92     let inbox = vec![recipient.shared_inbox_or_inbox()];
93     send_lemmy_activity(context, create_or_update, &sender, inbox, true).await
94   }
95 }
96
97 #[async_trait::async_trait]
98 impl ActivityHandler for CreateOrUpdateChatMessage {
99   type DataType = LemmyContext;
100   type Error = LemmyError;
101
102   fn id(&self) -> &Url {
103     &self.id
104   }
105
106   fn actor(&self) -> &Url {
107     self.actor.inner()
108   }
109
110   #[tracing::instrument(skip_all)]
111   async fn verify(&self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
112     insert_received_activity(&self.id, context).await?;
113     verify_person(&self.actor, context).await?;
114     verify_domains_match(self.actor.inner(), self.object.id.inner())?;
115     verify_domains_match(self.to[0].inner(), self.object.to[0].inner())?;
116     ApubPrivateMessage::verify(&self.object, self.actor.inner(), context).await?;
117     Ok(())
118   }
119
120   #[tracing::instrument(skip_all)]
121   async fn receive(self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
122     ApubPrivateMessage::from_json(self.object, context).await?;
123     Ok(())
124   }
125 }