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