]> Untitled Git - lemmy.git/blob - crates/apub_receive/src/activities/post/update.rs
Apub inbox rewrite (#1652)
[lemmy.git] / crates / apub_receive / src / activities / post / update.rs
1 use crate::activities::{
2   post::send_websocket_message,
3   verify_activity,
4   verify_mod_action,
5   verify_person_in_community,
6 };
7 use activitystreams::{activity::kind::UpdateType, base::BaseExt};
8 use anyhow::Context;
9 use lemmy_api_common::blocking;
10 use lemmy_apub::{
11   objects::{FromApub, FromApubToForm},
12   ActorType,
13   PageExt,
14 };
15 use lemmy_apub_lib::{verify_domains_match_opt, ActivityCommonFields, ActivityHandler, PublicUrl};
16 use lemmy_db_queries::ApubObject;
17 use lemmy_db_schema::{
18   source::post::{Post, PostForm},
19   DbUrl,
20 };
21 use lemmy_utils::{location_info, LemmyError};
22 use lemmy_websocket::{LemmyContext, UserOperationCrud};
23 use url::Url;
24
25 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
26 #[serde(rename_all = "camelCase")]
27 pub struct UpdatePost {
28   to: PublicUrl,
29   object: PageExt,
30   cc: Vec<Url>,
31   #[serde(rename = "type")]
32   kind: UpdateType,
33   #[serde(flatten)]
34   common: ActivityCommonFields,
35 }
36
37 #[async_trait::async_trait(?Send)]
38 impl ActivityHandler for UpdatePost {
39   async fn verify(
40     &self,
41     context: &LemmyContext,
42     request_counter: &mut i32,
43   ) -> Result<(), LemmyError> {
44     verify_activity(self.common())?;
45     let community =
46       verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
47
48     let temp_post = PostForm::from_apub(
49       &self.object,
50       context,
51       self.common.actor.clone(),
52       request_counter,
53       true,
54     )
55     .await?;
56     let post_id: DbUrl = temp_post.ap_id.context(location_info!())?;
57     let old_post = blocking(context.pool(), move |conn| {
58       Post::read_from_apub_id(conn, &post_id)
59     })
60     .await??;
61     let stickied = temp_post.stickied.context(location_info!())?;
62     let locked = temp_post.locked.context(location_info!())?;
63     // community mod changed locked/sticky status
64     if (stickied != old_post.stickied) || (locked != old_post.locked) {
65       verify_mod_action(&self.common.actor, community.actor_id(), context).await?;
66     }
67     // user edited their own post
68     else {
69       verify_domains_match_opt(&self.common.actor, self.object.id_unchecked())?;
70     }
71
72     Ok(())
73   }
74
75   async fn receive(
76     &self,
77     context: &LemmyContext,
78     request_counter: &mut i32,
79   ) -> Result<(), LemmyError> {
80     let post = Post::from_apub(
81       &self.object,
82       context,
83       self.common.actor.clone(),
84       request_counter,
85       // TODO: we already check here if the mod action is valid, can remove that check param
86       true,
87     )
88     .await?;
89
90     send_websocket_message(post.id, UserOperationCrud::EditPost, context).await
91   }
92
93   fn common(&self) -> &ActivityCommonFields {
94     &self.common
95   }
96 }