]> Untitled Git - lemmy.git/blob - crates/api_crud/src/comment/delete.rs
8f928096576bd9602d5123374f404fc213dbe845
[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};
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 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
59         .send_delete(&local_user_view.person, context)
60         .await?;
61     } else {
62       updated_comment
63         .send_undo_delete(&local_user_view.person, context)
64         .await?;
65     }
66
67     // Refetch it
68     let comment_id = data.comment_id;
69     let person_id = local_user_view.person.id;
70     let comment_view = blocking(context.pool(), move |conn| {
71       CommentView::read(conn, comment_id, Some(person_id))
72     })
73     .await??;
74
75     // Build the recipients
76     let comment_view_2 = comment_view.clone();
77     let mentions = vec![];
78     let recipient_ids = send_local_notifs(
79       mentions,
80       updated_comment,
81       local_user_view.person.clone(),
82       comment_view_2.post,
83       context.pool(),
84       false,
85     )
86     .await?;
87
88     let res = CommentResponse {
89       comment_view,
90       recipient_ids,
91       form_id: None, // TODO a comment delete might clear forms?
92     };
93
94     context.chat_server().do_send(SendComment {
95       op: UserOperationCrud::DeleteComment,
96       comment: res.clone(),
97       websocket_id,
98     });
99
100     Ok(res)
101   }
102 }
103
104 #[async_trait::async_trait(?Send)]
105 impl PerformCrud for RemoveComment {
106   type Response = CommentResponse;
107
108   async fn perform(
109     &self,
110     context: &Data<LemmyContext>,
111     websocket_id: Option<ConnectionId>,
112   ) -> Result<CommentResponse, LemmyError> {
113     let data: &RemoveComment = &self;
114     let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
115
116     let comment_id = data.comment_id;
117     let orig_comment = blocking(context.pool(), move |conn| {
118       CommentView::read(&conn, comment_id, None)
119     })
120     .await??;
121
122     check_community_ban(
123       local_user_view.person.id,
124       orig_comment.community.id,
125       context.pool(),
126     )
127     .await?;
128
129     // Verify that only a mod or admin can remove
130     is_mod_or_admin(
131       context.pool(),
132       local_user_view.person.id,
133       orig_comment.community.id,
134     )
135     .await?;
136
137     // Do the remove
138     let removed = data.removed;
139     let updated_comment = blocking(context.pool(), move |conn| {
140       Comment::update_removed(conn, comment_id, removed)
141     })
142     .await?
143     .map_err(|_| ApiError::err("couldnt_update_comment"))?;
144
145     // Mod tables
146     let form = ModRemoveCommentForm {
147       mod_person_id: local_user_view.person.id,
148       comment_id: data.comment_id,
149       removed: Some(removed),
150       reason: data.reason.to_owned(),
151     };
152     blocking(context.pool(), move |conn| {
153       ModRemoveComment::create(conn, &form)
154     })
155     .await??;
156
157     // Send the apub message
158     if removed {
159       updated_comment
160         .send_remove(&local_user_view.person, context)
161         .await?;
162     } else {
163       updated_comment
164         .send_undo_remove(&local_user_view.person, context)
165         .await?;
166     }
167
168     // Refetch it
169     let comment_id = data.comment_id;
170     let person_id = local_user_view.person.id;
171     let comment_view = blocking(context.pool(), move |conn| {
172       CommentView::read(conn, comment_id, Some(person_id))
173     })
174     .await??;
175
176     // Build the recipients
177     let comment_view_2 = comment_view.clone();
178
179     let mentions = vec![];
180     let recipient_ids = send_local_notifs(
181       mentions,
182       updated_comment,
183       local_user_view.person.clone(),
184       comment_view_2.post,
185       context.pool(),
186       false,
187     )
188     .await?;
189
190     let res = CommentResponse {
191       comment_view,
192       recipient_ids,
193       form_id: None, // TODO maybe this might clear other forms
194     };
195
196     context.chat_server().do_send(SendComment {
197       op: UserOperationCrud::RemoveComment,
198       comment: res.clone(),
199       websocket_id,
200     });
201
202     Ok(res)
203   }
204 }