]> Untitled Git - lemmy.git/blob - crates/api_crud/src/comment/delete.rs
e2ec3080ea87e5900dd1a675716383e8bc946b71
[lemmy.git] / crates / api_crud / src / comment / delete.rs
1 use crate::PerformCrud;
2 use actix_web::web::Data;
3 use lemmy_api_common::{
4   blocking,
5   check_community_ban,
6   comment::*,
7   get_local_user_view_from_jwt,
8   is_mod_or_admin,
9   send_local_notifs,
10 };
11 use lemmy_apub::ApubObjectType;
12 use lemmy_db_queries::{source::comment::Comment_, Crud, DeleteableOrRemoveable};
13 use lemmy_db_schema::source::{comment::*, moderator::*};
14 use lemmy_db_views::comment_view::CommentView;
15 use lemmy_utils::{ApiError, ConnectionId, LemmyError};
16 use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperationCrud};
17
18 #[async_trait::async_trait(?Send)]
19 impl PerformCrud for DeleteComment {
20   type Response = CommentResponse;
21
22   async fn perform(
23     &self,
24     context: &Data<LemmyContext>,
25     websocket_id: Option<ConnectionId>,
26   ) -> Result<CommentResponse, LemmyError> {
27     let data: &DeleteComment = self;
28     let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
29
30     let comment_id = data.comment_id;
31     let orig_comment = blocking(context.pool(), move |conn| {
32       CommentView::read(conn, comment_id, None)
33     })
34     .await??;
35
36     check_community_ban(
37       local_user_view.person.id,
38       orig_comment.community.id,
39       context.pool(),
40     )
41     .await?;
42
43     // Verify that only the creator can delete
44     if local_user_view.person.id != orig_comment.creator.id {
45       return Err(ApiError::err("no_comment_edit_allowed").into());
46     }
47
48     // Do the delete
49     let deleted = data.deleted;
50     let mut updated_comment = blocking(context.pool(), move |conn| {
51       Comment::update_deleted(conn, comment_id, deleted)
52     })
53     .await?
54     .map_err(|_| ApiError::err("couldnt_update_comment"))?;
55
56     // Send the apub message
57     if deleted {
58       updated_comment = updated_comment.blank_out_deleted_or_removed_info();
59       updated_comment
60         .send_delete(&local_user_view.person, context)
61         .await?;
62     } else {
63       updated_comment
64         .send_undo_delete(&local_user_view.person, context)
65         .await?;
66     }
67
68     // Refetch it
69     let comment_id = data.comment_id;
70     let person_id = local_user_view.person.id;
71     let mut comment_view = blocking(context.pool(), move |conn| {
72       CommentView::read(conn, comment_id, Some(person_id))
73     })
74     .await??;
75
76     // Blank out deleted or removed info
77     if deleted {
78       comment_view.comment = comment_view.comment.blank_out_deleted_or_removed_info();
79     }
80
81     // Build the recipients
82     let comment_view_2 = comment_view.clone();
83     let mentions = vec![];
84     let recipient_ids = send_local_notifs(
85       mentions,
86       updated_comment,
87       local_user_view.person.clone(),
88       comment_view_2.post,
89       context.pool(),
90       false,
91     )
92     .await?;
93
94     let res = CommentResponse {
95       comment_view,
96       recipient_ids,
97       form_id: None, // TODO a comment delete might clear forms?
98     };
99
100     context.chat_server().do_send(SendComment {
101       op: UserOperationCrud::DeleteComment,
102       comment: res.clone(),
103       websocket_id,
104     });
105
106     Ok(res)
107   }
108 }
109
110 #[async_trait::async_trait(?Send)]
111 impl PerformCrud for RemoveComment {
112   type Response = CommentResponse;
113
114   async fn perform(
115     &self,
116     context: &Data<LemmyContext>,
117     websocket_id: Option<ConnectionId>,
118   ) -> Result<CommentResponse, LemmyError> {
119     let data: &RemoveComment = self;
120     let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
121
122     let comment_id = data.comment_id;
123     let orig_comment = blocking(context.pool(), move |conn| {
124       CommentView::read(conn, comment_id, None)
125     })
126     .await??;
127
128     check_community_ban(
129       local_user_view.person.id,
130       orig_comment.community.id,
131       context.pool(),
132     )
133     .await?;
134
135     // Verify that only a mod or admin can remove
136     is_mod_or_admin(
137       context.pool(),
138       local_user_view.person.id,
139       orig_comment.community.id,
140     )
141     .await?;
142
143     // Do the remove
144     let removed = data.removed;
145     let mut updated_comment = blocking(context.pool(), move |conn| {
146       Comment::update_removed(conn, comment_id, removed)
147     })
148     .await?
149     .map_err(|_| ApiError::err("couldnt_update_comment"))?;
150
151     // Mod tables
152     let form = ModRemoveCommentForm {
153       mod_person_id: local_user_view.person.id,
154       comment_id: data.comment_id,
155       removed: Some(removed),
156       reason: data.reason.to_owned(),
157     };
158     blocking(context.pool(), move |conn| {
159       ModRemoveComment::create(conn, &form)
160     })
161     .await??;
162
163     // Send the apub message
164     if removed {
165       updated_comment = updated_comment.blank_out_deleted_or_removed_info();
166       updated_comment
167         .send_remove(&local_user_view.person, context)
168         .await?;
169     } else {
170       updated_comment
171         .send_undo_remove(&local_user_view.person, context)
172         .await?;
173     }
174
175     // Refetch it
176     let comment_id = data.comment_id;
177     let person_id = local_user_view.person.id;
178     let mut comment_view = blocking(context.pool(), move |conn| {
179       CommentView::read(conn, comment_id, Some(person_id))
180     })
181     .await??;
182
183     // Blank out deleted or removed info
184     if removed {
185       comment_view.comment = comment_view.comment.blank_out_deleted_or_removed_info();
186     }
187
188     // Build the recipients
189     let comment_view_2 = comment_view.clone();
190
191     let mentions = vec![];
192     let recipient_ids = send_local_notifs(
193       mentions,
194       updated_comment,
195       local_user_view.person.clone(),
196       comment_view_2.post,
197       context.pool(),
198       false,
199     )
200     .await?;
201
202     let res = CommentResponse {
203       comment_view,
204       recipient_ids,
205       form_id: None, // TODO maybe this might clear other forms
206     };
207
208     context.chat_server().do_send(SendComment {
209       op: UserOperationCrud::RemoveComment,
210       comment: res.clone(),
211       websocket_id,
212     });
213
214     Ok(res)
215   }
216 }