]> Untitled Git - lemmy.git/blob - crates/api_crud/src/comment/delete.rs
85917846e40f6c3192979c9e4eb6631135a6eb41
[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_queries::{source::comment::Comment_, Crud};
13 use lemmy_db_schema::source::{comment::*, community::Community, moderator::*, post::Post};
14 use lemmy_db_views::comment_view::CommentView;
15 use lemmy_utils::{ApiError, ConnectionId, LemmyError};
16 use lemmy_websocket::{send::send_comment_ws_message, 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     let community = blocking(context.pool(), move |conn| {
58       Community::read(conn, orig_comment.post.community_id)
59     })
60     .await??;
61     send_apub_delete(
62       &local_user_view.person,
63       &community,
64       updated_comment.ap_id.clone().into(),
65       deleted,
66       context,
67     )
68     .await?;
69
70     let post_id = updated_comment.post_id;
71     let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
72     let recipient_ids = send_local_notifs(
73       vec![],
74       updated_comment,
75       local_user_view.person.clone(),
76       post,
77       context.pool(),
78       false,
79     )
80     .await?;
81
82     send_comment_ws_message(
83       data.comment_id,
84       UserOperationCrud::DeleteComment,
85       websocket_id,
86       None, // TODO a comment delete might clear forms?
87       Some(local_user_view.person.id),
88       recipient_ids,
89       context,
90     )
91     .await
92   }
93 }
94
95 #[async_trait::async_trait(?Send)]
96 impl PerformCrud for RemoveComment {
97   type Response = CommentResponse;
98
99   async fn perform(
100     &self,
101     context: &Data<LemmyContext>,
102     websocket_id: Option<ConnectionId>,
103   ) -> Result<CommentResponse, LemmyError> {
104     let data: &RemoveComment = self;
105     let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
106
107     let comment_id = data.comment_id;
108     let orig_comment = blocking(context.pool(), move |conn| {
109       CommentView::read(conn, comment_id, None)
110     })
111     .await??;
112
113     check_community_ban(
114       local_user_view.person.id,
115       orig_comment.community.id,
116       context.pool(),
117     )
118     .await?;
119
120     // Verify that only a mod or admin can remove
121     is_mod_or_admin(
122       context.pool(),
123       local_user_view.person.id,
124       orig_comment.community.id,
125     )
126     .await?;
127
128     // Do the remove
129     let removed = data.removed;
130     let updated_comment = blocking(context.pool(), move |conn| {
131       Comment::update_removed(conn, comment_id, removed)
132     })
133     .await?
134     .map_err(|_| ApiError::err("couldnt_update_comment"))?;
135
136     // Mod tables
137     let form = ModRemoveCommentForm {
138       mod_person_id: local_user_view.person.id,
139       comment_id: data.comment_id,
140       removed: Some(removed),
141       reason: data.reason.to_owned(),
142     };
143     blocking(context.pool(), move |conn| {
144       ModRemoveComment::create(conn, &form)
145     })
146     .await??;
147
148     // Send the apub message
149     let community = blocking(context.pool(), move |conn| {
150       Community::read(conn, orig_comment.post.community_id)
151     })
152     .await??;
153     send_apub_remove(
154       &local_user_view.person,
155       &community,
156       updated_comment.ap_id.clone().into(),
157       data.reason.clone().unwrap_or_else(|| "".to_string()),
158       removed,
159       context,
160     )
161     .await?;
162
163     let post_id = updated_comment.post_id;
164     let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
165     let recipient_ids = send_local_notifs(
166       vec![],
167       updated_comment,
168       local_user_view.person.clone(),
169       post,
170       context.pool(),
171       false,
172     )
173     .await?;
174
175     send_comment_ws_message(
176       data.comment_id,
177       UserOperationCrud::RemoveComment,
178       websocket_id,
179       None, // TODO maybe this might clear other forms
180       Some(local_user_view.person.id),
181       recipient_ids,
182       context,
183     )
184     .await
185   }
186 }