]> Untitled Git - lemmy.git/blob - crates/api_crud/src/post/delete.rs
Support mastodon deletes
[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, send_apub_remove, 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::{ApiError, 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   async fn perform(
28     &self,
29     context: &Data<LemmyContext>,
30     websocket_id: Option<ConnectionId>,
31   ) -> Result<PostResponse, LemmyError> {
32     let data: &DeletePost = self;
33     let local_user_view =
34       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
35
36     let post_id = data.post_id;
37     let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
38
39     // Dont delete it if its already been deleted.
40     if orig_post.deleted == data.deleted {
41       return Err(ApiError::err_plain("couldnt_update_post").into());
42     }
43
44     check_community_ban(
45       local_user_view.person.id,
46       orig_post.community_id,
47       context.pool(),
48     )
49     .await?;
50     check_community_deleted_or_removed(orig_post.community_id, context.pool()).await?;
51
52     // Verify that only the creator can delete
53     if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
54       return Err(ApiError::err_plain("no_post_edit_allowed").into());
55     }
56
57     // Update the post
58     let post_id = data.post_id;
59     let deleted = data.deleted;
60     let updated_post = blocking(context.pool(), move |conn| {
61       Post::update_deleted(conn, post_id, deleted)
62     })
63     .await??;
64
65     // apub updates
66     let community = blocking(context.pool(), move |conn| {
67       Community::read(conn, orig_post.community_id)
68     })
69     .await??;
70     send_apub_delete(
71       &local_user_view.person.clone().into(),
72       &community.into(),
73       DeletableObjects::Post(Box::new(updated_post.into())),
74       deleted,
75       context,
76     )
77     .await?;
78
79     send_post_ws_message(
80       data.post_id,
81       UserOperationCrud::DeletePost,
82       websocket_id,
83       Some(local_user_view.person.id),
84       context,
85     )
86     .await
87   }
88 }
89
90 #[async_trait::async_trait(?Send)]
91 impl PerformCrud for RemovePost {
92   type Response = PostResponse;
93
94   async fn perform(
95     &self,
96     context: &Data<LemmyContext>,
97     websocket_id: Option<ConnectionId>,
98   ) -> Result<PostResponse, LemmyError> {
99     let data: &RemovePost = self;
100     let local_user_view =
101       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
102
103     let post_id = data.post_id;
104     let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
105
106     check_community_ban(
107       local_user_view.person.id,
108       orig_post.community_id,
109       context.pool(),
110     )
111     .await?;
112
113     // Verify that only the mods can remove
114     is_mod_or_admin(
115       context.pool(),
116       local_user_view.person.id,
117       orig_post.community_id,
118     )
119     .await?;
120
121     // Update the post
122     let post_id = data.post_id;
123     let removed = data.removed;
124     let updated_post = blocking(context.pool(), move |conn| {
125       Post::update_removed(conn, post_id, removed)
126     })
127     .await??;
128
129     // Mod tables
130     let form = ModRemovePostForm {
131       mod_person_id: local_user_view.person.id,
132       post_id: data.post_id,
133       removed: Some(removed),
134       reason: data.reason.to_owned(),
135     };
136     blocking(context.pool(), move |conn| {
137       ModRemovePost::create(conn, &form)
138     })
139     .await??;
140
141     // apub updates
142     let community = blocking(context.pool(), move |conn| {
143       Community::read(conn, orig_post.community_id)
144     })
145     .await??;
146     send_apub_remove(
147       &local_user_view.person.clone().into(),
148       &community.into(),
149       DeletableObjects::Post(Box::new(updated_post.into())),
150       data.reason.clone().unwrap_or_else(|| "".to_string()),
151       removed,
152       context,
153     )
154     .await?;
155
156     send_post_ws_message(
157       data.post_id,
158       UserOperationCrud::RemovePost,
159       websocket_id,
160       Some(local_user_view.person.id),
161       context,
162     )
163     .await
164   }
165 }