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