]> Untitled Git - lemmy.git/blob - crates/api/src/community/ban.rs
add enable_federated_downvotes site option
[lemmy.git] / crates / api / src / community / ban.rs
1 use activitypub_federation::config::Data;
2 use actix_web::web::Json;
3 use lemmy_api_common::{
4   community::{BanFromCommunity, BanFromCommunityResponse},
5   context::LemmyContext,
6   send_activity::{ActivityChannel, SendActivityData},
7   utils::{
8     is_mod_or_admin,
9     local_user_view_from_jwt,
10     remove_user_data_in_community,
11     sanitize_html_opt,
12   },
13 };
14 use lemmy_db_schema::{
15   source::{
16     community::{
17       CommunityFollower,
18       CommunityFollowerForm,
19       CommunityPersonBan,
20       CommunityPersonBanForm,
21     },
22     moderator::{ModBanFromCommunity, ModBanFromCommunityForm},
23   },
24   traits::{Bannable, Crud, Followable},
25 };
26 use lemmy_db_views_actor::structs::PersonView;
27 use lemmy_utils::{
28   error::{LemmyError, LemmyErrorExt, LemmyErrorType},
29   utils::{time::naive_from_unix, validation::is_valid_body_field},
30 };
31
32 #[tracing::instrument(skip(context))]
33 pub async fn ban_from_community(
34   data: Json<BanFromCommunity>,
35   context: Data<LemmyContext>,
36 ) -> Result<Json<BanFromCommunityResponse>, LemmyError> {
37   let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
38
39   let banned_person_id = data.person_id;
40   let remove_data = data.remove_data.unwrap_or(false);
41   let expires = data.expires.map(naive_from_unix);
42
43   // Verify that only mods or admins can ban
44   is_mod_or_admin(
45     &mut context.pool(),
46     local_user_view.person.id,
47     data.community_id,
48   )
49   .await?;
50   is_valid_body_field(&data.reason, false)?;
51
52   let community_user_ban_form = CommunityPersonBanForm {
53     community_id: data.community_id,
54     person_id: data.person_id,
55     expires: Some(expires),
56   };
57
58   if data.ban {
59     CommunityPersonBan::ban(&mut context.pool(), &community_user_ban_form)
60       .await
61       .with_lemmy_type(LemmyErrorType::CommunityUserAlreadyBanned)?;
62
63     // Also unsubscribe them from the community, if they are subscribed
64     let community_follower_form = CommunityFollowerForm {
65       community_id: data.community_id,
66       person_id: banned_person_id,
67       pending: false,
68     };
69
70     CommunityFollower::unfollow(&mut context.pool(), &community_follower_form)
71       .await
72       .ok();
73   } else {
74     CommunityPersonBan::unban(&mut context.pool(), &community_user_ban_form)
75       .await
76       .with_lemmy_type(LemmyErrorType::CommunityUserAlreadyBanned)?;
77   }
78
79   // Remove/Restore their data if that's desired
80   if remove_data {
81     remove_user_data_in_community(data.community_id, banned_person_id, &mut context.pool()).await?;
82   }
83
84   // Mod tables
85   let form = ModBanFromCommunityForm {
86     mod_person_id: local_user_view.person.id,
87     other_person_id: data.person_id,
88     community_id: data.community_id,
89     reason: sanitize_html_opt(&data.reason),
90     banned: Some(data.ban),
91     expires,
92   };
93
94   ModBanFromCommunity::create(&mut context.pool(), &form).await?;
95
96   let person_view = PersonView::read(&mut context.pool(), data.person_id).await?;
97
98   ActivityChannel::submit_activity(
99     SendActivityData::BanFromCommunity(
100       local_user_view.person,
101       data.community_id,
102       person_view.person.clone(),
103       data.0.clone(),
104     ),
105     &context,
106   )
107   .await?;
108
109   Ok(Json(BanFromCommunityResponse {
110     person_view,
111     banned: data.ban,
112   }))
113 }