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