2 activities::receive::verify_activity_domains_valid,
3 check_is_apub_id_valid,
4 extensions::signatures::verify_signature,
5 fetcher::{get_or_fetch_and_upsert_actor, get_or_fetch_and_upsert_community},
6 inbox::{get_activity_id, is_activity_already_known},
11 use activitystreams::{
12 activity::{Accept, ActorAndObject, Create, Delete, Follow, Undo, Update},
17 use actix_web::{web, HttpRequest, HttpResponse};
18 use anyhow::{anyhow, Context};
20 community::{CommunityFollower, CommunityFollowerForm},
21 private_message::{PrivateMessage, PrivateMessageForm},
22 private_message_view::PrivateMessageView,
27 use lemmy_structs::{blocking, user::PrivateMessageResponse};
28 use lemmy_utils::{location_info, LemmyError};
29 use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation};
31 use serde::{Deserialize, Serialize};
34 /// Allowed activities for user inbox.
35 #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
36 #[serde(rename_all = "PascalCase")]
45 pub type AcceptedActivities = ActorAndObject<ValidTypes>;
47 /// Handler for all incoming activities to user inboxes.
48 pub async fn user_inbox(
50 input: web::Json<AcceptedActivities>,
51 path: web::Path<String>,
52 context: web::Data<LemmyContext>,
53 ) -> Result<HttpResponse, LemmyError> {
54 let activity = input.into_inner();
55 let username = path.into_inner();
56 let user = blocking(&context.pool(), move |conn| {
57 User_::read_from_name(&conn, &username)
63 .context(location_info!())?
65 .single_xsd_any_uri();
66 if Some(user.actor_id()?) != to {
67 return Err(anyhow!("Activity delivered to wrong user").into());
70 let actor_uri = activity
72 .as_single_xsd_any_uri()
73 .context(location_info!())?;
75 "User {} inbox received activity {:?} from {}",
77 &activity.id_unchecked(),
81 check_is_apub_id_valid(actor_uri)?;
83 let request_counter = &mut 0;
84 let actor = get_or_fetch_and_upsert_actor(actor_uri, &context, request_counter).await?;
85 verify_signature(&request, actor.as_ref())?;
87 let activity_id = get_activity_id(&activity, actor_uri)?;
88 if is_activity_already_known(context.pool(), &activity_id).await? {
89 return Ok(HttpResponse::Ok().finish());
92 let any_base = activity.clone().into_any_base()?;
93 let kind = activity.kind().context(location_info!())?;
94 let res = match kind {
95 ValidTypes::Accept => {
96 receive_accept(&context, any_base, actor.as_ref(), user, request_counter).await
98 ValidTypes::Create => {
99 receive_create_private_message(&context, any_base, actor.as_ref(), request_counter).await
101 ValidTypes::Update => {
102 receive_update_private_message(&context, any_base, actor.as_ref(), request_counter).await
104 ValidTypes::Delete => receive_delete_private_message(&context, any_base, actor.as_ref()).await,
105 ValidTypes::Undo => {
106 receive_undo_delete_private_message(&context, any_base, actor.as_ref()).await
121 /// Handle accepted follows.
122 async fn receive_accept(
123 context: &LemmyContext,
125 actor: &dyn ActorType,
127 request_counter: &mut i32,
128 ) -> Result<HttpResponse, LemmyError> {
129 let accept = Accept::from_any_base(activity)?.context(location_info!())?;
130 verify_activity_domains_valid(&accept, actor.actor_id()?, false)?;
132 // TODO: we should check that we actually sent this activity, because the remote instance
133 // could just put a fake Follow
134 let object = accept.object().to_owned().one().context(location_info!())?;
135 let follow = Follow::from_any_base(object)?.context(location_info!())?;
136 verify_activity_domains_valid(&follow, user.actor_id()?, false)?;
138 let community_uri = accept
141 .single_xsd_any_uri()
142 .context(location_info!())?;
145 get_or_fetch_and_upsert_community(&community_uri, context, request_counter).await?;
147 // Now you need to add this to the community follower
148 let community_follower_form = CommunityFollowerForm {
149 community_id: community.id,
153 // This will fail if they're already a follower
154 blocking(&context.pool(), move |conn| {
155 CommunityFollower::follow(conn, &community_follower_form).ok()
159 Ok(HttpResponse::Ok().finish())
162 async fn receive_create_private_message(
163 context: &LemmyContext,
165 actor: &dyn ActorType,
166 request_counter: &mut i32,
167 ) -> Result<HttpResponse, LemmyError> {
168 let create = Create::from_any_base(activity)?.context(location_info!())?;
169 verify_activity_domains_valid(&create, actor.actor_id()?, true)?;
171 let note = Note::from_any_base(
175 .context(location_info!())?
178 .context(location_info!())?;
180 let private_message =
181 PrivateMessageForm::from_apub(¬e, context, Some(actor.actor_id()?), request_counter).await?;
183 let inserted_private_message = blocking(&context.pool(), move |conn| {
184 PrivateMessage::create(conn, &private_message)
188 let message = blocking(&context.pool(), move |conn| {
189 PrivateMessageView::read(conn, inserted_private_message.id)
193 let res = PrivateMessageResponse { message };
195 let recipient_id = res.message.recipient_id;
197 context.chat_server().do_send(SendUserRoomMessage {
198 op: UserOperation::CreatePrivateMessage,
204 Ok(HttpResponse::Ok().finish())
207 async fn receive_update_private_message(
208 context: &LemmyContext,
210 actor: &dyn ActorType,
211 request_counter: &mut i32,
212 ) -> Result<HttpResponse, LemmyError> {
213 let update = Update::from_any_base(activity)?.context(location_info!())?;
214 verify_activity_domains_valid(&update, actor.actor_id()?, true)?;
219 .context(location_info!())?
221 let note = Note::from_any_base(object)?.context(location_info!())?;
223 let private_message_form =
224 PrivateMessageForm::from_apub(¬e, context, Some(actor.actor_id()?), request_counter).await?;
226 let private_message_ap_id = private_message_form
229 .context(location_info!())?
231 let private_message = blocking(&context.pool(), move |conn| {
232 PrivateMessage::read_from_apub_id(conn, &private_message_ap_id)
236 let private_message_id = private_message.id;
237 blocking(&context.pool(), move |conn| {
238 PrivateMessage::update(conn, private_message_id, &private_message_form)
242 let private_message_id = private_message.id;
243 let message = blocking(&context.pool(), move |conn| {
244 PrivateMessageView::read(conn, private_message_id)
248 let res = PrivateMessageResponse { message };
250 let recipient_id = res.message.recipient_id;
252 context.chat_server().do_send(SendUserRoomMessage {
253 op: UserOperation::EditPrivateMessage,
259 Ok(HttpResponse::Ok().finish())
262 async fn receive_delete_private_message(
263 context: &LemmyContext,
265 actor: &dyn ActorType,
266 ) -> Result<HttpResponse, LemmyError> {
267 let delete = Delete::from_any_base(activity)?.context(location_info!())?;
268 verify_activity_domains_valid(&delete, actor.actor_id()?, true)?;
270 let private_message_id = delete
273 .single_xsd_any_uri()
274 .context(location_info!())?;
275 let private_message = blocking(context.pool(), move |conn| {
276 PrivateMessage::read_from_apub_id(conn, private_message_id.as_str())
279 let deleted_private_message = blocking(context.pool(), move |conn| {
280 PrivateMessage::update_deleted(conn, private_message.id, true)
284 let message = blocking(&context.pool(), move |conn| {
285 PrivateMessageView::read(&conn, deleted_private_message.id)
289 let res = PrivateMessageResponse { message };
290 let recipient_id = res.message.recipient_id;
291 context.chat_server().do_send(SendUserRoomMessage {
292 op: UserOperation::EditPrivateMessage,
298 Ok(HttpResponse::Ok().finish())
301 async fn receive_undo_delete_private_message(
302 context: &LemmyContext,
304 actor: &dyn ActorType,
305 ) -> Result<HttpResponse, LemmyError> {
306 let undo = Undo::from_any_base(activity)?.context(location_info!())?;
307 verify_activity_domains_valid(&undo, actor.actor_id()?, true)?;
308 let object = undo.object().to_owned().one().context(location_info!())?;
309 let delete = Delete::from_any_base(object)?.context(location_info!())?;
310 verify_activity_domains_valid(&delete, actor.actor_id()?, true)?;
312 let private_message_id = delete
315 .single_xsd_any_uri()
316 .context(location_info!())?;
317 let private_message = blocking(context.pool(), move |conn| {
318 PrivateMessage::read_from_apub_id(conn, private_message_id.as_str())
321 let deleted_private_message = blocking(context.pool(), move |conn| {
322 PrivateMessage::update_deleted(conn, private_message.id, false)
326 let message = blocking(&context.pool(), move |conn| {
327 PrivateMessageView::read(&conn, deleted_private_message.id)
331 let res = PrivateMessageResponse { message };
332 let recipient_id = res.message.recipient_id;
333 context.chat_server().do_send(SendUserRoomMessage {
334 op: UserOperation::EditPrivateMessage,
340 Ok(HttpResponse::Ok().finish())