]> Untitled Git - lemmy.git/blob - crates/api/src/community/ban.rs
Merge websocket crate into api_common
[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   utils::{get_local_user_view_from_jwt, is_mod_or_admin, remove_user_data_in_community},
6   websocket::{messages::SendCommunityRoomMessage, UserOperation},
7   LemmyContext,
8 };
9 use lemmy_apub::{
10   activities::block::SiteOrCommunity,
11   objects::{community::ApubCommunity, person::ApubPerson},
12   protocol::activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
13 };
14 use lemmy_db_schema::{
15   source::{
16     community::{
17       Community,
18       CommunityFollower,
19       CommunityFollowerForm,
20       CommunityPersonBan,
21       CommunityPersonBanForm,
22     },
23     moderator::{ModBanFromCommunity, ModBanFromCommunityForm},
24     person::Person,
25   },
26   traits::{Bannable, Crud, Followable},
27 };
28 use lemmy_db_views_actor::structs::PersonViewSafe;
29 use lemmy_utils::{error::LemmyError, utils::naive_from_unix, ConnectionId};
30
31 #[async_trait::async_trait(?Send)]
32 impl Perform for BanFromCommunity {
33   type Response = BanFromCommunityResponse;
34
35   #[tracing::instrument(skip(context, websocket_id))]
36   async fn perform(
37     &self,
38     context: &Data<LemmyContext>,
39     websocket_id: Option<ConnectionId>,
40   ) -> Result<BanFromCommunityResponse, LemmyError> {
41     let data: &BanFromCommunity = self;
42     let local_user_view =
43       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
44
45     let community_id = data.community_id;
46     let banned_person_id = data.person_id;
47     let remove_data = data.remove_data.unwrap_or(false);
48     let expires = data.expires.map(naive_from_unix);
49
50     // Verify that only mods or admins can ban
51     is_mod_or_admin(context.pool(), local_user_view.person.id, community_id).await?;
52
53     let community_user_ban_form = CommunityPersonBanForm {
54       community_id: data.community_id,
55       person_id: data.person_id,
56       expires: Some(expires),
57     };
58
59     let community: ApubCommunity = Community::read(context.pool(), community_id).await?.into();
60     let banned_person: ApubPerson = Person::read(context.pool(), banned_person_id).await?.into();
61
62     if data.ban {
63       CommunityPersonBan::ban(context.pool(), &community_user_ban_form)
64         .await
65         .map_err(|e| LemmyError::from_error_message(e, "community_user_already_banned"))?;
66
67       // Also unsubscribe them from the community, if they are subscribed
68       let community_follower_form = CommunityFollowerForm {
69         community_id: data.community_id,
70         person_id: banned_person_id,
71         pending: false,
72       };
73
74       CommunityFollower::unfollow(context.pool(), &community_follower_form)
75         .await
76         .ok();
77
78       BlockUser::send(
79         &SiteOrCommunity::Community(community),
80         &banned_person,
81         &local_user_view.person.clone().into(),
82         remove_data,
83         data.reason.clone(),
84         expires,
85         context,
86       )
87       .await?;
88     } else {
89       CommunityPersonBan::unban(context.pool(), &community_user_ban_form)
90         .await
91         .map_err(|e| LemmyError::from_error_message(e, "community_user_already_banned"))?;
92       UndoBlockUser::send(
93         &SiteOrCommunity::Community(community),
94         &banned_person,
95         &local_user_view.person.clone().into(),
96         data.reason.clone(),
97         context,
98       )
99       .await?;
100     }
101
102     // Remove/Restore their data if that's desired
103     if remove_data {
104       remove_user_data_in_community(community_id, banned_person_id, context.pool()).await?;
105     }
106
107     // Mod tables
108     let form = ModBanFromCommunityForm {
109       mod_person_id: local_user_view.person.id,
110       other_person_id: data.person_id,
111       community_id: data.community_id,
112       reason: data.reason.clone(),
113       banned: Some(data.ban),
114       expires,
115     };
116
117     ModBanFromCommunity::create(context.pool(), &form).await?;
118
119     let person_id = data.person_id;
120     let person_view = PersonViewSafe::read(context.pool(), person_id).await?;
121
122     let res = BanFromCommunityResponse {
123       person_view,
124       banned: data.ban,
125     };
126
127     context.chat_server().do_send(SendCommunityRoomMessage {
128       op: UserOperation::BanFromCommunity,
129       response: res.clone(),
130       community_id,
131       websocket_id,
132     });
133
134     Ok(res)
135   }
136 }