]> Untitled Git - lemmy.git/blob - crates/api_crud/src/post/delete.rs
Merge different delete activities for better compatibility (fixes #2066) (#2073)
[lemmy.git] / crates / api_crud / src / post / delete.rs
1 use crate::PerformCrud;
2 use actix_web::web::Data;
3 use lemmy_api_common::{
4   blocking,
5   check_community_ban,
6   check_community_deleted_or_removed,
7   get_local_user_view_from_jwt,
8   is_mod_or_admin,
9   post::*,
10 };
11 use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
12 use lemmy_db_schema::{
13   source::{
14     community::Community,
15     moderator::{ModRemovePost, ModRemovePostForm},
16     post::Post,
17   },
18   traits::Crud,
19 };
20 use lemmy_utils::{ConnectionId, LemmyError};
21 use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
22
23 #[async_trait::async_trait(?Send)]
24 impl PerformCrud for DeletePost {
25   type Response = PostResponse;
26
27   #[tracing::instrument(skip(context, websocket_id))]
28   async fn perform(
29     &self,
30     context: &Data<LemmyContext>,
31     websocket_id: Option<ConnectionId>,
32   ) -> Result<PostResponse, LemmyError> {
33     let data: &DeletePost = self;
34     let local_user_view =
35       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
36
37     let post_id = data.post_id;
38     let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
39
40     // Dont delete it if its already been deleted.
41     if orig_post.deleted == data.deleted {
42       return Err(LemmyError::from_message("couldnt_update_post"));
43     }
44
45     check_community_ban(
46       local_user_view.person.id,
47       orig_post.community_id,
48       context.pool(),
49     )
50     .await?;
51     check_community_deleted_or_removed(orig_post.community_id, context.pool()).await?;
52
53     // Verify that only the creator can delete
54     if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
55       return Err(LemmyError::from_message("no_post_edit_allowed"));
56     }
57
58     // Update the post
59     let post_id = data.post_id;
60     let deleted = data.deleted;
61     let updated_post = blocking(context.pool(), move |conn| {
62       Post::update_deleted(conn, post_id, deleted)
63     })
64     .await??;
65
66     let res = send_post_ws_message(
67       data.post_id,
68       UserOperationCrud::DeletePost,
69       websocket_id,
70       Some(local_user_view.person.id),
71       context,
72     )
73     .await?;
74
75     // apub updates
76     let community = blocking(context.pool(), move |conn| {
77       Community::read(conn, orig_post.community_id)
78     })
79     .await??;
80     let deletable = DeletableObjects::Post(Box::new(updated_post.into()));
81     send_apub_delete_in_community(
82       local_user_view.person,
83       community,
84       deletable,
85       None,
86       deleted,
87       context,
88     )
89     .await?;
90     Ok(res)
91   }
92 }
93
94 #[async_trait::async_trait(?Send)]
95 impl PerformCrud for RemovePost {
96   type Response = PostResponse;
97
98   #[tracing::instrument(skip(context, websocket_id))]
99   async fn perform(
100     &self,
101     context: &Data<LemmyContext>,
102     websocket_id: Option<ConnectionId>,
103   ) -> Result<PostResponse, LemmyError> {
104     let data: &RemovePost = self;
105     let local_user_view =
106       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
107
108     let post_id = data.post_id;
109     let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
110
111     check_community_ban(
112       local_user_view.person.id,
113       orig_post.community_id,
114       context.pool(),
115     )
116     .await?;
117
118     // Verify that only the mods can remove
119     is_mod_or_admin(
120       context.pool(),
121       local_user_view.person.id,
122       orig_post.community_id,
123     )
124     .await?;
125
126     // Update the post
127     let post_id = data.post_id;
128     let removed = data.removed;
129     let updated_post = blocking(context.pool(), move |conn| {
130       Post::update_removed(conn, post_id, removed)
131     })
132     .await??;
133
134     // Mod tables
135     let form = ModRemovePostForm {
136       mod_person_id: local_user_view.person.id,
137       post_id: data.post_id,
138       removed: Some(removed),
139       reason: data.reason.to_owned(),
140     };
141     blocking(context.pool(), move |conn| {
142       ModRemovePost::create(conn, &form)
143     })
144     .await??;
145
146     let res = send_post_ws_message(
147       data.post_id,
148       UserOperationCrud::RemovePost,
149       websocket_id,
150       Some(local_user_view.person.id),
151       context,
152     )
153     .await?;
154
155     // apub updates
156     let community = blocking(context.pool(), move |conn| {
157       Community::read(conn, orig_post.community_id)
158     })
159     .await??;
160     let deletable = DeletableObjects::Post(Box::new(updated_post.into()));
161     send_apub_delete_in_community(
162       local_user_view.person,
163       community,
164       deletable,
165       data.reason.clone().or_else(|| Some("".to_string())),
166       removed,
167       context,
168     )
169     .await?;
170     Ok(res)
171   }
172 }