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