]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/post/update.rs
Merge pull request #1660 from LemmyNet/merge-apub-crates
[lemmy.git] / crates / apub / src / activities / post / update.rs
1 use crate::{
2   activities::{
3     post::send_websocket_message,
4     verify_activity,
5     verify_mod_action,
6     verify_person_in_community,
7   },
8   objects::{FromApub, FromApubToForm},
9   ActorType,
10   PageExt,
11 };
12 use activitystreams::{activity::kind::UpdateType, base::BaseExt};
13 use anyhow::Context;
14 use lemmy_api_common::blocking;
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 }