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