]> Untitled Git - lemmy.git/blob - crates/api_crud/src/comment/update.rs
7d6f78109cc27cb21cd214e8d8e69abfa46c1cfb
[lemmy.git] / crates / api_crud / src / comment / update.rs
1 use actix_web::web::Data;
2 use lemmy_api_common::{
3   comment::{CommentResponse, EditComment},
4   utils::{
5     blocking,
6     check_community_ban,
7     check_community_deleted_or_removed,
8     check_post_deleted_or_removed,
9     get_local_user_view_from_jwt,
10     is_mod_or_admin,
11   },
12 };
13 use lemmy_apub::protocol::activities::{
14   create_or_update::comment::CreateOrUpdateComment,
15   CreateOrUpdateType,
16 };
17 use lemmy_db_schema::{
18   source::comment::{Comment, CommentForm},
19   traits::Crud,
20 };
21 use lemmy_db_views::structs::CommentView;
22 use lemmy_utils::{
23   error::LemmyError,
24   utils::{remove_slurs, scrape_text_for_mentions},
25   ConnectionId,
26 };
27 use lemmy_websocket::{
28   send::{send_comment_ws_message, send_local_notifs},
29   LemmyContext,
30   UserOperationCrud,
31 };
32
33 use crate::PerformCrud;
34
35 #[async_trait::async_trait(?Send)]
36 impl PerformCrud for EditComment {
37   type Response = CommentResponse;
38
39   #[tracing::instrument(skip(context, websocket_id))]
40   async fn perform(
41     &self,
42     context: &Data<LemmyContext>,
43     websocket_id: Option<ConnectionId>,
44   ) -> Result<CommentResponse, LemmyError> {
45     let data: &EditComment = self;
46     let local_user_view =
47       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
48
49     let comment_id = data.comment_id;
50     let orig_comment = blocking(context.pool(), move |conn| {
51       CommentView::read(conn, comment_id, None)
52     })
53     .await??;
54
55     // TODO is this necessary? It should really only need to check on create
56     check_community_ban(
57       local_user_view.person.id,
58       orig_comment.community.id,
59       context.pool(),
60     )
61     .await?;
62     check_community_deleted_or_removed(orig_comment.community.id, context.pool()).await?;
63     check_post_deleted_or_removed(&orig_comment.post)?;
64
65     // Verify that only the creator can edit
66     if local_user_view.person.id != orig_comment.creator.id {
67       return Err(LemmyError::from_message("no_comment_edit_allowed"));
68     }
69
70     if data.distinguished.is_some() {
71       // Verify that only a mod or admin can distinguish a comment
72       is_mod_or_admin(
73         context.pool(),
74         local_user_view.person.id,
75         orig_comment.community.id,
76       )
77       .await?;
78     }
79
80     // Update the Content
81     let content_slurs_removed = data
82       .content
83       .as_ref()
84       .map(|c| remove_slurs(c, &context.settings().slur_regex()));
85     let comment_id = data.comment_id;
86     let form = CommentForm {
87       creator_id: orig_comment.comment.creator_id,
88       post_id: orig_comment.comment.post_id,
89       content: content_slurs_removed.unwrap_or(orig_comment.comment.content),
90       distinguished: data.distinguished,
91       language_id: data.language_id,
92       ..Default::default()
93     };
94     let updated_comment = blocking(context.pool(), move |conn| {
95       Comment::update(conn, comment_id, &form)
96     })
97     .await?
98     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
99
100     // Do the mentions / recipients
101     let updated_comment_content = updated_comment.content.to_owned();
102     let mentions = scrape_text_for_mentions(&updated_comment_content);
103     let recipient_ids = send_local_notifs(
104       mentions,
105       &updated_comment,
106       &local_user_view.person,
107       &orig_comment.post,
108       false,
109       context,
110     )
111     .await?;
112
113     // Send the apub update
114     CreateOrUpdateComment::send(
115       updated_comment.into(),
116       &local_user_view.person.into(),
117       CreateOrUpdateType::Update,
118       context,
119       &mut 0,
120     )
121     .await?;
122
123     send_comment_ws_message(
124       data.comment_id,
125       UserOperationCrud::EditComment,
126       websocket_id,
127       data.form_id.to_owned(),
128       None,
129       recipient_ids,
130       context,
131     )
132     .await
133   }
134 }