]> Untitled Git - lemmy.git/blob - crates/api_crud/src/community/update.rs
Replace TypedBuilder with Default in update forms (#3814)
[lemmy.git] / crates / api_crud / src / community / update.rs
1 use activitypub_federation::config::Data;
2 use actix_web::web::Json;
3 use lemmy_api_common::{
4   build_response::build_community_response,
5   community::{CommunityResponse, EditCommunity},
6   context::LemmyContext,
7   send_activity::{ActivityChannel, SendActivityData},
8   utils::{local_site_to_slur_regex, local_user_view_from_jwt, sanitize_html_opt},
9 };
10 use lemmy_db_schema::{
11   newtypes::PersonId,
12   source::{
13     actor_language::{CommunityLanguage, SiteLanguage},
14     community::{Community, CommunityUpdateForm},
15     local_site::LocalSite,
16   },
17   traits::Crud,
18   utils::{diesel_option_overwrite, diesel_option_overwrite_to_url, naive_now},
19 };
20 use lemmy_db_views_actor::structs::CommunityModeratorView;
21 use lemmy_utils::{
22   error::{LemmyError, LemmyErrorExt, LemmyErrorType},
23   utils::{slurs::check_slurs_opt, validation::is_valid_body_field},
24 };
25
26 #[tracing::instrument(skip(context))]
27 pub async fn update_community(
28   data: Json<EditCommunity>,
29   context: Data<LemmyContext>,
30 ) -> Result<Json<CommunityResponse>, LemmyError> {
31   let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
32   let local_site = LocalSite::read(&mut context.pool()).await?;
33
34   let slur_regex = local_site_to_slur_regex(&local_site);
35   check_slurs_opt(&data.title, &slur_regex)?;
36   check_slurs_opt(&data.description, &slur_regex)?;
37   is_valid_body_field(&data.description, false)?;
38
39   let title = sanitize_html_opt(&data.title);
40   let description = sanitize_html_opt(&data.description);
41
42   let icon = diesel_option_overwrite_to_url(&data.icon)?;
43   let banner = diesel_option_overwrite_to_url(&data.banner)?;
44   let description = diesel_option_overwrite(description);
45
46   // Verify its a mod (only mods can edit it)
47   let community_id = data.community_id;
48   let mods: Vec<PersonId> =
49     CommunityModeratorView::for_community(&mut context.pool(), community_id)
50       .await
51       .map(|v| v.into_iter().map(|m| m.moderator.id).collect())?;
52   if !mods.contains(&local_user_view.person.id) {
53     return Err(LemmyErrorType::NotAModerator)?;
54   }
55
56   let community_id = data.community_id;
57   if let Some(languages) = data.discussion_languages.clone() {
58     let site_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
59     // check that community languages are a subset of site languages
60     // https://stackoverflow.com/a/64227550
61     let is_subset = languages.iter().all(|item| site_languages.contains(item));
62     if !is_subset {
63       return Err(LemmyErrorType::LanguageNotAllowed)?;
64     }
65     CommunityLanguage::update(&mut context.pool(), languages, community_id).await?;
66   }
67
68   let community_form = CommunityUpdateForm {
69     title,
70     description,
71     icon,
72     banner,
73     nsfw: data.nsfw,
74     posting_restricted_to_mods: data.posting_restricted_to_mods,
75     updated: Some(Some(naive_now())),
76     ..Default::default()
77   };
78
79   let community_id = data.community_id;
80   let community = Community::update(&mut context.pool(), community_id, &community_form)
81     .await
82     .with_lemmy_type(LemmyErrorType::CouldntUpdateCommunity)?;
83
84   ActivityChannel::submit_activity(
85     SendActivityData::UpdateCommunity(local_user_view.person.clone(), community),
86     &context,
87   )
88   .await?;
89
90   build_community_response(&context, local_user_view, community_id).await
91 }