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