]> Untitled Git - lemmy.git/blob - crates/api_crud/src/comment/update.rs
Sanitize html (#3708)
[lemmy.git] / crates / api_crud / src / comment / update.rs
1 use crate::PerformCrud;
2 use actix_web::web::Data;
3 use lemmy_api_common::{
4   build_response::{build_comment_response, send_local_notifs},
5   comment::{CommentResponse, EditComment},
6   context::LemmyContext,
7   utils::{
8     check_community_ban,
9     local_site_to_slur_regex,
10     local_user_view_from_jwt,
11     sanitize_html_opt,
12   },
13 };
14 use lemmy_db_schema::{
15   source::{
16     actor_language::CommunityLanguage,
17     comment::{Comment, CommentUpdateForm},
18     local_site::LocalSite,
19   },
20   traits::Crud,
21   utils::naive_now,
22 };
23 use lemmy_db_views::structs::CommentView;
24 use lemmy_utils::{
25   error::{LemmyError, LemmyErrorExt, LemmyErrorType},
26   utils::{
27     mention::scrape_text_for_mentions,
28     slurs::remove_slurs,
29     validation::is_valid_body_field,
30   },
31 };
32
33 #[async_trait::async_trait(?Send)]
34 impl PerformCrud for EditComment {
35   type Response = CommentResponse;
36
37   #[tracing::instrument(skip(context))]
38   async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommentResponse, LemmyError> {
39     let data: &EditComment = self;
40     let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
41     let local_site = LocalSite::read(&mut context.pool()).await?;
42
43     let comment_id = data.comment_id;
44     let orig_comment = CommentView::read(&mut context.pool(), comment_id, None).await?;
45
46     check_community_ban(
47       local_user_view.person.id,
48       orig_comment.community.id,
49       &mut context.pool(),
50     )
51     .await?;
52
53     // Verify that only the creator can edit
54     if local_user_view.person.id != orig_comment.creator.id {
55       return Err(LemmyErrorType::NoCommentEditAllowed)?;
56     }
57
58     let language_id = self.language_id;
59     CommunityLanguage::is_allowed_community_language(
60       &mut context.pool(),
61       language_id,
62       orig_comment.community.id,
63     )
64     .await?;
65
66     // Update the Content
67     let content = data
68       .content
69       .as_ref()
70       .map(|c| remove_slurs(c, &local_site_to_slur_regex(&local_site)));
71     is_valid_body_field(&content, false)?;
72     let content = sanitize_html_opt(&content);
73
74     let comment_id = data.comment_id;
75     let form = CommentUpdateForm::builder()
76       .content(content)
77       .language_id(data.language_id)
78       .updated(Some(Some(naive_now())))
79       .build();
80     let updated_comment = Comment::update(&mut context.pool(), comment_id, &form)
81       .await
82       .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?;
83
84     // Do the mentions / recipients
85     let updated_comment_content = updated_comment.content.clone();
86     let mentions = scrape_text_for_mentions(&updated_comment_content);
87     let recipient_ids = send_local_notifs(
88       mentions,
89       &updated_comment,
90       &local_user_view.person,
91       &orig_comment.post,
92       false,
93       context,
94     )
95     .await?;
96
97     build_comment_response(
98       context,
99       updated_comment.id,
100       Some(local_user_view),
101       self.form_id.clone(),
102       recipient_ids,
103     )
104     .await
105   }
106 }