]> Untitled Git - lemmy.git/blob - crates/api_crud/src/comment/delete.rs
Merge crates db_schema and db_queries
[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::activities::deletion::{send_apub_delete, send_apub_remove};
12 use lemmy_db_schema::{
13   source::{
14     comment::Comment,
15     community::Community,
16     moderator::{ModRemoveComment, ModRemoveCommentForm},
17     post::Post,
18   },
19   traits::Crud,
20 };
21 use lemmy_db_views::comment_view::CommentView;
22 use lemmy_utils::{ApiError, ConnectionId, LemmyError};
23 use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
24
25 #[async_trait::async_trait(?Send)]
26 impl PerformCrud for DeleteComment {
27   type Response = CommentResponse;
28
29   async fn perform(
30     &self,
31     context: &Data<LemmyContext>,
32     websocket_id: Option<ConnectionId>,
33   ) -> Result<CommentResponse, LemmyError> {
34     let data: &DeleteComment = self;
35     let local_user_view =
36       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
37
38     let comment_id = data.comment_id;
39     let orig_comment = blocking(context.pool(), move |conn| {
40       CommentView::read(conn, comment_id, None)
41     })
42     .await??;
43
44     check_community_ban(
45       local_user_view.person.id,
46       orig_comment.community.id,
47       context.pool(),
48     )
49     .await?;
50
51     // Verify that only the creator can delete
52     if local_user_view.person.id != orig_comment.creator.id {
53       return Err(ApiError::err_plain("no_comment_edit_allowed").into());
54     }
55
56     // Do the delete
57     let deleted = data.deleted;
58     let updated_comment = blocking(context.pool(), move |conn| {
59       Comment::update_deleted(conn, comment_id, deleted)
60     })
61     .await?
62     .map_err(|e| ApiError::err("couldnt_update_comment", e))?;
63
64     // Send the apub message
65     let community = blocking(context.pool(), move |conn| {
66       Community::read(conn, orig_comment.post.community_id)
67     })
68     .await??;
69     send_apub_delete(
70       &local_user_view.person,
71       &community,
72       updated_comment.ap_id.clone().into(),
73       deleted,
74       context,
75     )
76     .await?;
77
78     let post_id = updated_comment.post_id;
79     let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
80     let recipient_ids = send_local_notifs(
81       vec![],
82       updated_comment,
83       local_user_view.person.clone(),
84       post,
85       context.pool(),
86       false,
87       &context.settings(),
88     )
89     .await?;
90
91     send_comment_ws_message(
92       data.comment_id,
93       UserOperationCrud::DeleteComment,
94       websocket_id,
95       None, // TODO a comment delete might clear forms?
96       Some(local_user_view.person.id),
97       recipient_ids,
98       context,
99     )
100     .await
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 =
115       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
116
117     let comment_id = data.comment_id;
118     let orig_comment = blocking(context.pool(), move |conn| {
119       CommentView::read(conn, comment_id, None)
120     })
121     .await??;
122
123     check_community_ban(
124       local_user_view.person.id,
125       orig_comment.community.id,
126       context.pool(),
127     )
128     .await?;
129
130     // Verify that only a mod or admin can remove
131     is_mod_or_admin(
132       context.pool(),
133       local_user_view.person.id,
134       orig_comment.community.id,
135     )
136     .await?;
137
138     // Do the remove
139     let removed = data.removed;
140     let updated_comment = blocking(context.pool(), move |conn| {
141       Comment::update_removed(conn, comment_id, removed)
142     })
143     .await?
144     .map_err(|e| ApiError::err("couldnt_update_comment", e))?;
145
146     // Mod tables
147     let form = ModRemoveCommentForm {
148       mod_person_id: local_user_view.person.id,
149       comment_id: data.comment_id,
150       removed: Some(removed),
151       reason: data.reason.to_owned(),
152     };
153     blocking(context.pool(), move |conn| {
154       ModRemoveComment::create(conn, &form)
155     })
156     .await??;
157
158     // Send the apub message
159     let community = blocking(context.pool(), move |conn| {
160       Community::read(conn, orig_comment.post.community_id)
161     })
162     .await??;
163     send_apub_remove(
164       &local_user_view.person,
165       &community,
166       updated_comment.ap_id.clone().into(),
167       data.reason.clone().unwrap_or_else(|| "".to_string()),
168       removed,
169       context,
170     )
171     .await?;
172
173     let post_id = updated_comment.post_id;
174     let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
175     let recipient_ids = send_local_notifs(
176       vec![],
177       updated_comment,
178       local_user_view.person.clone(),
179       post,
180       context.pool(),
181       false,
182       &context.settings(),
183     )
184     .await?;
185
186     send_comment_ws_message(
187       data.comment_id,
188       UserOperationCrud::RemoveComment,
189       websocket_id,
190       None, // TODO maybe this might clear other forms
191       Some(local_user_view.person.id),
192       recipient_ids,
193       context,
194     )
195     .await
196   }
197 }