]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/deletion/undo_delete.rs
Fix changelog links
[lemmy.git] / crates / apub / src / activities / deletion / undo_delete.rs
1 use crate::{
2   activities::{
3     comment::send_websocket_message as send_comment_message,
4     community::send_websocket_message as send_community_message,
5     deletion::delete::DeletePostCommentOrCommunity,
6     post::send_websocket_message as send_post_message,
7     verify_activity,
8     verify_mod_action,
9     verify_person_in_community,
10   },
11   fetcher::{
12     community::get_or_fetch_and_upsert_community,
13     objects::get_or_fetch_and_insert_post_or_comment,
14     person::get_or_fetch_and_upsert_person,
15   },
16   CommunityType,
17   PostOrComment,
18 };
19 use activitystreams::activity::kind::UndoType;
20 use lemmy_api_common::blocking;
21 use lemmy_apub_lib::{verify_urls_match, ActivityCommonFields, ActivityHandler, PublicUrl};
22 use lemmy_db_queries::source::{comment::Comment_, community::Community_, post::Post_};
23 use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
24 use lemmy_utils::LemmyError;
25 use lemmy_websocket::{LemmyContext, UserOperationCrud};
26 use url::Url;
27
28 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
29 #[serde(rename_all = "camelCase")]
30 pub struct UndoDeletePostCommentOrCommunity {
31   to: PublicUrl,
32   object: DeletePostCommentOrCommunity,
33   cc: [Url; 1],
34   #[serde(rename = "type")]
35   kind: UndoType,
36   #[serde(flatten)]
37   common: ActivityCommonFields,
38 }
39
40 #[async_trait::async_trait(?Send)]
41 impl ActivityHandler for UndoDeletePostCommentOrCommunity {
42   async fn verify(
43     &self,
44     context: &LemmyContext,
45     request_counter: &mut i32,
46   ) -> Result<(), LemmyError> {
47     verify_activity(self.common())?;
48     self.object.verify(context, request_counter).await?;
49     let object_community =
50       get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
51     // restoring a community
52     if object_community.is_ok() {
53       verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?;
54     }
55     // restoring a post or comment
56     else {
57       verify_person_in_community(&self.common().actor, &self.cc, context, request_counter).await?;
58       verify_urls_match(&self.common.actor, &self.object.common().actor)?;
59     }
60     Ok(())
61   }
62
63   async fn receive(
64     &self,
65     context: &LemmyContext,
66     request_counter: &mut i32,
67   ) -> Result<(), LemmyError> {
68     let object_community =
69       get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
70     // restoring a community
71     if let Ok(community) = object_community {
72       if community.local {
73         // repeat these checks just to be sure
74         verify_person_in_community(&self.common().actor, &self.cc, context, request_counter)
75           .await?;
76         verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?;
77         let mod_ =
78           get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
79         community.send_undo_delete(mod_, context).await?;
80       }
81       let deleted_community = blocking(context.pool(), move |conn| {
82         Community::update_deleted(conn, community.id, false)
83       })
84       .await??;
85
86       send_community_message(
87         deleted_community.id,
88         UserOperationCrud::EditCommunity,
89         context,
90       )
91       .await
92     }
93     // restoring a post or comment
94     else {
95       match get_or_fetch_and_insert_post_or_comment(&self.object.object, context, request_counter)
96         .await?
97       {
98         PostOrComment::Post(post) => {
99           let deleted_post = blocking(context.pool(), move |conn| {
100             Post::update_deleted(conn, post.id, false)
101           })
102           .await??;
103           send_post_message(deleted_post.id, UserOperationCrud::EditPost, context).await
104         }
105         PostOrComment::Comment(comment) => {
106           let deleted_comment = blocking(context.pool(), move |conn| {
107             Comment::update_deleted(conn, comment.id, false)
108           })
109           .await??;
110           send_comment_message(
111             deleted_comment.id,
112             vec![],
113             UserOperationCrud::EditComment,
114             context,
115           )
116           .await
117         }
118       }
119     }
120   }
121
122   fn common(&self) -> &ActivityCommonFields {
123     &self.common
124   }
125 }