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