]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/receive/private_message.rs
Split api crate into api_structs and api
[lemmy.git] / crates / apub / src / activities / receive / private_message.rs
1 use crate::{
2   activities::receive::verify_activity_domains_valid,
3   check_is_apub_id_valid,
4   fetcher::person::get_or_fetch_and_upsert_person,
5   inbox::get_activity_to_and_cc,
6   objects::FromApub,
7   NoteExt,
8 };
9 use activitystreams::{
10   activity::{ActorAndObjectRefExt, Create, Delete, Undo, Update},
11   base::{AsBase, ExtendsExt},
12   object::AsObject,
13   public,
14 };
15 use anyhow::{anyhow, Context};
16 use lemmy_api_common::{blocking, person::PrivateMessageResponse};
17 use lemmy_db_queries::source::private_message::PrivateMessage_;
18 use lemmy_db_schema::source::private_message::PrivateMessage;
19 use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView};
20 use lemmy_utils::{location_info, LemmyError};
21 use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation};
22 use url::Url;
23
24 pub(crate) async fn receive_create_private_message(
25   context: &LemmyContext,
26   create: Create,
27   expected_domain: Url,
28   request_counter: &mut i32,
29 ) -> Result<(), LemmyError> {
30   check_private_message_activity_valid(&create, context, request_counter).await?;
31
32   let note = NoteExt::from_any_base(
33     create
34       .object()
35       .as_one()
36       .context(location_info!())?
37       .to_owned(),
38   )?
39   .context(location_info!())?;
40
41   let private_message =
42     PrivateMessage::from_apub(&note, context, expected_domain, request_counter, false).await?;
43
44   let message = blocking(&context.pool(), move |conn| {
45     PrivateMessageView::read(conn, private_message.id)
46   })
47   .await??;
48
49   let res = PrivateMessageResponse {
50     private_message_view: message,
51   };
52
53   // Send notifications to the local recipient, if one exists
54   let recipient_id = res.private_message_view.recipient.id;
55   let local_recipient_id = blocking(context.pool(), move |conn| {
56     LocalUserView::read_person(conn, recipient_id)
57   })
58   .await??
59   .local_user
60   .id;
61
62   context.chat_server().do_send(SendUserRoomMessage {
63     op: UserOperation::CreatePrivateMessage,
64     response: res,
65     local_recipient_id,
66     websocket_id: None,
67   });
68
69   Ok(())
70 }
71
72 pub(crate) async fn receive_update_private_message(
73   context: &LemmyContext,
74   update: Update,
75   expected_domain: Url,
76   request_counter: &mut i32,
77 ) -> Result<(), LemmyError> {
78   check_private_message_activity_valid(&update, context, request_counter).await?;
79
80   let object = update
81     .object()
82     .as_one()
83     .context(location_info!())?
84     .to_owned();
85   let note = NoteExt::from_any_base(object)?.context(location_info!())?;
86
87   let private_message =
88     PrivateMessage::from_apub(&note, context, expected_domain, request_counter, false).await?;
89
90   let private_message_id = private_message.id;
91   let message = blocking(&context.pool(), move |conn| {
92     PrivateMessageView::read(conn, private_message_id)
93   })
94   .await??;
95
96   let res = PrivateMessageResponse {
97     private_message_view: message,
98   };
99
100   let recipient_id = res.private_message_view.recipient.id;
101   let local_recipient_id = blocking(context.pool(), move |conn| {
102     LocalUserView::read_person(conn, recipient_id)
103   })
104   .await??
105   .local_user
106   .id;
107
108   context.chat_server().do_send(SendUserRoomMessage {
109     op: UserOperation::EditPrivateMessage,
110     response: res,
111     local_recipient_id,
112     websocket_id: None,
113   });
114
115   Ok(())
116 }
117
118 pub(crate) async fn receive_delete_private_message(
119   context: &LemmyContext,
120   delete: Delete,
121   private_message: PrivateMessage,
122   request_counter: &mut i32,
123 ) -> Result<(), LemmyError> {
124   check_private_message_activity_valid(&delete, context, request_counter).await?;
125
126   let deleted_private_message = blocking(context.pool(), move |conn| {
127     PrivateMessage::update_deleted(conn, private_message.id, true)
128   })
129   .await??;
130
131   let message = blocking(&context.pool(), move |conn| {
132     PrivateMessageView::read(&conn, deleted_private_message.id)
133   })
134   .await??;
135
136   let res = PrivateMessageResponse {
137     private_message_view: message,
138   };
139
140   let recipient_id = res.private_message_view.recipient.id;
141   let local_recipient_id = blocking(context.pool(), move |conn| {
142     LocalUserView::read_person(conn, recipient_id)
143   })
144   .await??
145   .local_user
146   .id;
147
148   context.chat_server().do_send(SendUserRoomMessage {
149     op: UserOperation::EditPrivateMessage,
150     response: res,
151     local_recipient_id,
152     websocket_id: None,
153   });
154
155   Ok(())
156 }
157
158 pub(crate) async fn receive_undo_delete_private_message(
159   context: &LemmyContext,
160   undo: Undo,
161   expected_domain: &Url,
162   private_message: PrivateMessage,
163   request_counter: &mut i32,
164 ) -> Result<(), LemmyError> {
165   check_private_message_activity_valid(&undo, context, request_counter).await?;
166   let object = undo.object().to_owned().one().context(location_info!())?;
167   let delete = Delete::from_any_base(object)?.context(location_info!())?;
168   verify_activity_domains_valid(&delete, expected_domain, true)?;
169   check_private_message_activity_valid(&delete, context, request_counter).await?;
170
171   let deleted_private_message = blocking(context.pool(), move |conn| {
172     PrivateMessage::update_deleted(conn, private_message.id, false)
173   })
174   .await??;
175
176   let message = blocking(&context.pool(), move |conn| {
177     PrivateMessageView::read(&conn, deleted_private_message.id)
178   })
179   .await??;
180
181   let res = PrivateMessageResponse {
182     private_message_view: message,
183   };
184
185   let recipient_id = res.private_message_view.recipient.id;
186   let local_recipient_id = blocking(context.pool(), move |conn| {
187     LocalUserView::read_person(conn, recipient_id)
188   })
189   .await??
190   .local_user
191   .id;
192
193   context.chat_server().do_send(SendUserRoomMessage {
194     op: UserOperation::EditPrivateMessage,
195     response: res,
196     local_recipient_id,
197     websocket_id: None,
198   });
199
200   Ok(())
201 }
202
203 async fn check_private_message_activity_valid<T, Kind>(
204   activity: &T,
205   context: &LemmyContext,
206   request_counter: &mut i32,
207 ) -> Result<(), LemmyError>
208 where
209   T: AsBase<Kind> + AsObject<Kind> + ActorAndObjectRefExt,
210 {
211   let to_and_cc = get_activity_to_and_cc(activity);
212   if to_and_cc.len() != 1 {
213     return Err(anyhow!("Private message can only be addressed to one person").into());
214   }
215   if to_and_cc.contains(&public()) {
216     return Err(anyhow!("Private message cant be public").into());
217   }
218   let person_id = activity
219     .actor()?
220     .to_owned()
221     .single_xsd_any_uri()
222     .context(location_info!())?;
223   check_is_apub_id_valid(&person_id)?;
224   // check that the sender is a person, not a community
225   get_or_fetch_and_upsert_person(&person_id, &context, request_counter).await?;
226
227   Ok(())
228 }