]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/deletion/undo_delete.rs
Add docs for MediaType, PublicUrl values
[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::{values::PublicUrl, verify_urls_match, ActivityCommonFields, ActivityHandler};
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[0], context, request_counter)
58         .await?;
59       verify_urls_match(&self.common.actor, &self.object.common().actor)?;
60     }
61     Ok(())
62   }
63
64   async fn receive(
65     &self,
66     context: &LemmyContext,
67     request_counter: &mut i32,
68   ) -> Result<(), LemmyError> {
69     let object_community =
70       get_or_fetch_and_upsert_community(&self.object.object, context, request_counter).await;
71     // restoring a community
72     if let Ok(community) = object_community {
73       if community.local {
74         // repeat these checks just to be sure
75         verify_person_in_community(&self.common().actor, &self.cc[0], context, request_counter)
76           .await?;
77         verify_mod_action(&self.common.actor, self.object.object.clone(), context).await?;
78         let mod_ =
79           get_or_fetch_and_upsert_person(&self.common.actor, context, request_counter).await?;
80         community.send_undo_delete(mod_, context).await?;
81       }
82       let deleted_community = blocking(context.pool(), move |conn| {
83         Community::update_deleted(conn, community.id, false)
84       })
85       .await??;
86
87       send_community_message(
88         deleted_community.id,
89         UserOperationCrud::EditCommunity,
90         context,
91       )
92       .await
93     }
94     // restoring a post or comment
95     else {
96       match get_or_fetch_and_insert_post_or_comment(&self.object.object, context, request_counter)
97         .await?
98       {
99         PostOrComment::Post(post) => {
100           let deleted_post = blocking(context.pool(), move |conn| {
101             Post::update_deleted(conn, post.id, false)
102           })
103           .await??;
104           send_post_message(deleted_post.id, UserOperationCrud::EditPost, context).await
105         }
106         PostOrComment::Comment(comment) => {
107           let deleted_comment = blocking(context.pool(), move |conn| {
108             Comment::update_deleted(conn, comment.id, false)
109           })
110           .await??;
111           send_comment_message(
112             deleted_comment.id,
113             vec![],
114             UserOperationCrud::EditComment,
115             context,
116           )
117           .await
118         }
119       }
120     }
121   }
122
123   fn common(&self) -> &ActivityCommonFields {
124     &self.common
125   }
126 }