2 check_is_apub_id_valid,
3 extensions::signatures::verify,
4 fetcher::{get_or_fetch_and_upsert_actor, get_or_fetch_and_upsert_community},
9 activity::{Accept, ActorAndObject, Create, Delete, Undo, Update},
14 use actix_web::{web, HttpRequest, HttpResponse};
17 community::{CommunityFollower, CommunityFollowerForm},
19 private_message::{PrivateMessage, PrivateMessageForm},
20 private_message_view::PrivateMessageView,
25 use lemmy_structs::{blocking, user::PrivateMessageResponse};
26 use lemmy_utils::{location_info, LemmyError};
27 use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation};
29 use serde::{Deserialize, Serialize};
32 #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
33 #[serde(rename_all = "PascalCase")]
42 pub type AcceptedActivities = ActorAndObject<ValidTypes>;
44 /// Handler for all incoming activities to user inboxes.
45 pub async fn user_inbox(
47 input: web::Json<AcceptedActivities>,
48 path: web::Path<String>,
49 context: web::Data<LemmyContext>,
50 ) -> Result<HttpResponse, LemmyError> {
51 let activity = input.into_inner();
52 let username = path.into_inner();
53 debug!("User {} received activity: {:?}", &username, &activity);
55 let actor_uri = activity
57 .as_single_xsd_any_uri()
58 .context(location_info!())?;
60 check_is_apub_id_valid(actor_uri)?;
62 let actor = get_or_fetch_and_upsert_actor(actor_uri, &context).await?;
63 verify(&request, actor.as_ref())?;
65 let any_base = activity.clone().into_any_base()?;
66 let kind = activity.kind().context(location_info!())?;
67 let res = match kind {
68 ValidTypes::Accept => receive_accept(any_base, username, &context).await,
69 ValidTypes::Create => receive_create_private_message(any_base, &context).await,
70 ValidTypes::Update => receive_update_private_message(any_base, &context).await,
71 ValidTypes::Delete => receive_delete_private_message(any_base, &context).await,
72 ValidTypes::Undo => receive_undo_delete_private_message(any_base, &context).await,
75 insert_activity(actor.user_id(), activity.clone(), false, context.pool()).await?;
79 /// Handle accepted follows.
80 async fn receive_accept(
83 context: &LemmyContext,
84 ) -> Result<HttpResponse, LemmyError> {
85 let accept = Accept::from_any_base(activity)?.context(location_info!())?;
86 let community_uri = accept
90 .context(location_info!())?;
92 let community = get_or_fetch_and_upsert_community(&community_uri, context).await?;
94 let user = blocking(&context.pool(), move |conn| {
95 User_::read_from_name(conn, &username)
99 // Now you need to add this to the community follower
100 let community_follower_form = CommunityFollowerForm {
101 community_id: community.id,
105 // This will fail if they're already a follower
106 blocking(&context.pool(), move |conn| {
107 CommunityFollower::follow(conn, &community_follower_form).ok()
111 // TODO: make sure that we actually requested a follow
112 Ok(HttpResponse::Ok().finish())
115 async fn receive_create_private_message(
117 context: &LemmyContext,
118 ) -> Result<HttpResponse, LemmyError> {
119 let create = Create::from_any_base(activity)?.context(location_info!())?;
120 let note = Note::from_any_base(
124 .context(location_info!())?
127 .context(location_info!())?;
129 let domain = Some(create.id_unchecked().context(location_info!())?.to_owned());
130 let private_message = PrivateMessageForm::from_apub(¬e, context, domain).await?;
132 let inserted_private_message = blocking(&context.pool(), move |conn| {
133 PrivateMessage::create(conn, &private_message)
137 let message = blocking(&context.pool(), move |conn| {
138 PrivateMessageView::read(conn, inserted_private_message.id)
142 let res = PrivateMessageResponse { message };
144 let recipient_id = res.message.recipient_id;
146 context.chat_server().do_send(SendUserRoomMessage {
147 op: UserOperation::CreatePrivateMessage,
153 Ok(HttpResponse::Ok().finish())
156 async fn receive_update_private_message(
158 context: &LemmyContext,
159 ) -> Result<HttpResponse, LemmyError> {
160 let update = Update::from_any_base(activity)?.context(location_info!())?;
161 let note = Note::from_any_base(
165 .context(location_info!())?
168 .context(location_info!())?;
170 let domain = Some(update.id_unchecked().context(location_info!())?.to_owned());
171 let private_message_form = PrivateMessageForm::from_apub(¬e, context, domain).await?;
173 let private_message_ap_id = private_message_form
176 .context(location_info!())?
178 let private_message = blocking(&context.pool(), move |conn| {
179 PrivateMessage::read_from_apub_id(conn, &private_message_ap_id)
183 let private_message_id = private_message.id;
184 blocking(&context.pool(), move |conn| {
185 PrivateMessage::update(conn, private_message_id, &private_message_form)
189 let private_message_id = private_message.id;
190 let message = blocking(&context.pool(), move |conn| {
191 PrivateMessageView::read(conn, private_message_id)
195 let res = PrivateMessageResponse { message };
197 let recipient_id = res.message.recipient_id;
199 context.chat_server().do_send(SendUserRoomMessage {
200 op: UserOperation::EditPrivateMessage,
206 Ok(HttpResponse::Ok().finish())
209 async fn receive_delete_private_message(
211 context: &LemmyContext,
212 ) -> Result<HttpResponse, LemmyError> {
213 let delete = Delete::from_any_base(activity)?.context(location_info!())?;
214 let note = Note::from_any_base(
218 .context(location_info!())?
221 .context(location_info!())?;
223 let domain = Some(delete.id_unchecked().context(location_info!())?.to_owned());
224 let private_message_form = PrivateMessageForm::from_apub(¬e, context, domain).await?;
226 let private_message_ap_id = private_message_form.ap_id.context(location_info!())?;
227 let private_message = blocking(&context.pool(), move |conn| {
228 PrivateMessage::read_from_apub_id(conn, &private_message_ap_id)
232 let private_message_form = PrivateMessageForm {
233 content: private_message_form.content,
234 recipient_id: private_message.recipient_id,
235 creator_id: private_message.creator_id,
238 ap_id: Some(private_message.ap_id),
239 local: private_message.local,
241 updated: Some(naive_now()),
244 let private_message_id = private_message.id;
245 blocking(&context.pool(), move |conn| {
246 PrivateMessage::update(conn, private_message_id, &private_message_form)
250 let private_message_id = private_message.id;
251 let message = blocking(&context.pool(), move |conn| {
252 PrivateMessageView::read(&conn, private_message_id)
256 let res = PrivateMessageResponse { message };
258 let recipient_id = res.message.recipient_id;
260 context.chat_server().do_send(SendUserRoomMessage {
261 op: UserOperation::EditPrivateMessage,
267 Ok(HttpResponse::Ok().finish())
270 async fn receive_undo_delete_private_message(
272 context: &LemmyContext,
273 ) -> Result<HttpResponse, LemmyError> {
274 let undo = Undo::from_any_base(activity)?.context(location_info!())?;
275 let delete = Delete::from_any_base(undo.object().as_one().context(location_info!())?.to_owned())?
276 .context(location_info!())?;
277 let note = Note::from_any_base(
281 .context(location_info!())?
284 .context(location_info!())?;
286 let domain = Some(undo.id_unchecked().context(location_info!())?.to_owned());
287 let private_message = PrivateMessageForm::from_apub(¬e, context, domain).await?;
289 let private_message_ap_id = private_message
292 .context(location_info!())?
294 let private_message_id = blocking(&context.pool(), move |conn| {
295 PrivateMessage::read_from_apub_id(conn, &private_message_ap_id).map(|pm| pm.id)
299 let private_message_form = PrivateMessageForm {
300 content: private_message.content,
301 recipient_id: private_message.recipient_id,
302 creator_id: private_message.creator_id,
303 deleted: Some(false),
305 ap_id: private_message.ap_id,
306 local: private_message.local,
308 updated: Some(naive_now()),
311 blocking(&context.pool(), move |conn| {
312 PrivateMessage::update(conn, private_message_id, &private_message_form)
316 let message = blocking(&context.pool(), move |conn| {
317 PrivateMessageView::read(&conn, private_message_id)
321 let res = PrivateMessageResponse { message };
323 let recipient_id = res.message.recipient_id;
325 context.chat_server().do_send(SendUserRoomMessage {
326 op: UserOperation::EditPrivateMessage,
332 Ok(HttpResponse::Ok().finish())