]> Untitled Git - lemmy.git/blob - crates/api/src/community/ban.rs
Get rid of Safe Views, use serde_skip (#2767)
[lemmy.git] / crates / api / src / community / ban.rs
1 use crate::Perform;
2 use actix_web::web::Data;
3 use lemmy_api_common::{
4   community::{BanFromCommunity, BanFromCommunityResponse},
5   context::LemmyContext,
6   utils::{get_local_user_view_from_jwt, is_mod_or_admin, remove_user_data_in_community},
7   websocket::UserOperation,
8 };
9 use lemmy_db_schema::{
10   source::{
11     community::{
12       CommunityFollower,
13       CommunityFollowerForm,
14       CommunityPersonBan,
15       CommunityPersonBanForm,
16     },
17     moderator::{ModBanFromCommunity, ModBanFromCommunityForm},
18   },
19   traits::{Bannable, Crud, Followable},
20 };
21 use lemmy_db_views_actor::structs::PersonView;
22 use lemmy_utils::{error::LemmyError, utils::time::naive_from_unix, ConnectionId};
23
24 #[async_trait::async_trait(?Send)]
25 impl Perform for BanFromCommunity {
26   type Response = BanFromCommunityResponse;
27
28   #[tracing::instrument(skip(context, websocket_id))]
29   async fn perform(
30     &self,
31     context: &Data<LemmyContext>,
32     websocket_id: Option<ConnectionId>,
33   ) -> Result<BanFromCommunityResponse, LemmyError> {
34     let data: &BanFromCommunity = self;
35     let local_user_view =
36       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
37
38     let community_id = data.community_id;
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(context.pool(), local_user_view.person.id, community_id).await?;
45
46     let community_user_ban_form = CommunityPersonBanForm {
47       community_id: data.community_id,
48       person_id: data.person_id,
49       expires: Some(expires),
50     };
51
52     if data.ban {
53       CommunityPersonBan::ban(context.pool(), &community_user_ban_form)
54         .await
55         .map_err(|e| LemmyError::from_error_message(e, "community_user_already_banned"))?;
56
57       // Also unsubscribe them from the community, if they are subscribed
58       let community_follower_form = CommunityFollowerForm {
59         community_id: data.community_id,
60         person_id: banned_person_id,
61         pending: false,
62       };
63
64       CommunityFollower::unfollow(context.pool(), &community_follower_form)
65         .await
66         .ok();
67     } else {
68       CommunityPersonBan::unban(context.pool(), &community_user_ban_form)
69         .await
70         .map_err(|e| LemmyError::from_error_message(e, "community_user_already_banned"))?;
71     }
72
73     // Remove/Restore their data if that's desired
74     if remove_data {
75       remove_user_data_in_community(community_id, banned_person_id, context.pool()).await?;
76     }
77
78     // Mod tables
79     let form = ModBanFromCommunityForm {
80       mod_person_id: local_user_view.person.id,
81       other_person_id: data.person_id,
82       community_id: data.community_id,
83       reason: data.reason.clone(),
84       banned: Some(data.ban),
85       expires,
86     };
87
88     ModBanFromCommunity::create(context.pool(), &form).await?;
89
90     let person_id = data.person_id;
91     let person_view = PersonView::read(context.pool(), person_id).await?;
92
93     let res = BanFromCommunityResponse {
94       person_view,
95       banned: data.ban,
96     };
97
98     context
99       .chat_server()
100       .send_community_room_message(
101         &UserOperation::BanFromCommunity,
102         &res,
103         community_id,
104         websocket_id,
105       )
106       .await?;
107
108     Ok(res)
109   }
110 }