]> Untitled Git - lemmy.git/blob - crates/api_crud/src/post/update.rs
Replace TypedBuilder with Default in update forms (#3814)
[lemmy.git] / crates / api_crud / src / post / update.rs
1 use activitypub_federation::config::Data;
2 use actix_web::web::Json;
3 use lemmy_api_common::{
4   build_response::build_post_response,
5   context::LemmyContext,
6   post::{EditPost, PostResponse},
7   request::fetch_site_data,
8   send_activity::{ActivityChannel, SendActivityData},
9   utils::{
10     check_community_ban,
11     local_site_to_slur_regex,
12     local_user_view_from_jwt,
13     sanitize_html_opt,
14   },
15 };
16 use lemmy_db_schema::{
17   source::{
18     actor_language::CommunityLanguage,
19     local_site::LocalSite,
20     post::{Post, PostUpdateForm},
21   },
22   traits::Crud,
23   utils::{diesel_option_overwrite, naive_now},
24 };
25 use lemmy_utils::{
26   error::{LemmyError, LemmyErrorExt, LemmyErrorType},
27   utils::{
28     slurs::check_slurs_opt,
29     validation::{check_url_scheme, clean_url_params, is_valid_body_field, is_valid_post_title},
30   },
31 };
32 use std::ops::Deref;
33
34 #[tracing::instrument(skip(context))]
35 pub async fn update_post(
36   data: Json<EditPost>,
37   context: Data<LemmyContext>,
38 ) -> Result<Json<PostResponse>, LemmyError> {
39   let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
40   let local_site = LocalSite::read(&mut context.pool()).await?;
41
42   let data_url = data.url.as_ref();
43
44   // TODO No good way to handle a clear.
45   // Issue link: https://github.com/LemmyNet/lemmy/issues/2287
46   let url = Some(data_url.map(clean_url_params).map(Into::into));
47
48   let slur_regex = local_site_to_slur_regex(&local_site);
49   check_slurs_opt(&data.name, &slur_regex)?;
50   check_slurs_opt(&data.body, &slur_regex)?;
51
52   if let Some(name) = &data.name {
53     is_valid_post_title(name)?;
54   }
55
56   is_valid_body_field(&data.body, true)?;
57   check_url_scheme(&data.url)?;
58
59   let post_id = data.post_id;
60   let orig_post = Post::read(&mut context.pool(), post_id).await?;
61
62   check_community_ban(
63     local_user_view.person.id,
64     orig_post.community_id,
65     &mut context.pool(),
66   )
67   .await?;
68
69   // Verify that only the creator can edit
70   if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
71     return Err(LemmyErrorType::NoPostEditAllowed)?;
72   }
73
74   // Fetch post links and Pictrs cached image
75   let data_url = data.url.as_ref();
76   let (metadata_res, thumbnail_url) =
77     fetch_site_data(context.client(), context.settings(), data_url, true).await;
78   let (embed_title, embed_description, embed_video_url) = metadata_res
79     .map(|u| (Some(u.title), Some(u.description), Some(u.embed_video_url)))
80     .unwrap_or_default();
81
82   let name = sanitize_html_opt(&data.name);
83   let body = sanitize_html_opt(&data.body);
84   let body = diesel_option_overwrite(body);
85   let embed_title = embed_title.map(|e| sanitize_html_opt(&e));
86   let embed_description = embed_description.map(|e| sanitize_html_opt(&e));
87
88   let language_id = data.language_id;
89   CommunityLanguage::is_allowed_community_language(
90     &mut context.pool(),
91     language_id,
92     orig_post.community_id,
93   )
94   .await?;
95
96   let post_form = PostUpdateForm {
97     name,
98     url,
99     body,
100     nsfw: data.nsfw,
101     embed_title,
102     embed_description,
103     embed_video_url,
104     language_id: data.language_id,
105     thumbnail_url: Some(thumbnail_url),
106     updated: Some(Some(naive_now())),
107     ..Default::default()
108   };
109
110   let post_id = data.post_id;
111   let updated_post = Post::update(&mut context.pool(), post_id, &post_form)
112     .await
113     .with_lemmy_type(LemmyErrorType::CouldntUpdatePost)?;
114
115   ActivityChannel::submit_activity(SendActivityData::UpdatePost(updated_post), &context).await?;
116
117   build_post_response(
118     context.deref(),
119     orig_post.community_id,
120     local_user_view.person.id,
121     post_id,
122   )
123   .await
124 }