]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/block_user.rs
f5a6f02cebfdf54ce5653a72ec4b1b674c7cb5df
[lemmy.git] / crates / apub / src / activities / community / block_user.rs
1 use crate::{
2   activities::{
3     community::{announce::GetCommunity, send_activity_in_community},
4     generate_activity_id,
5     verify_activity,
6     verify_is_public,
7     verify_mod_action,
8     verify_person_in_community,
9   },
10   activity_lists::AnnouncableActivities,
11   objects::{community::ApubCommunity, person::ApubPerson},
12   protocol::activities::community::block_user::BlockUserFromCommunity,
13 };
14 use activitystreams_kinds::{activity::BlockType, public};
15 use chrono::NaiveDateTime;
16 use lemmy_api_common::blocking;
17 use lemmy_apub_lib::{
18   data::Data,
19   object_id::ObjectId,
20   traits::{ActivityHandler, ActorType},
21 };
22 use lemmy_db_schema::{
23   source::community::{
24     CommunityFollower,
25     CommunityFollowerForm,
26     CommunityPersonBan,
27     CommunityPersonBanForm,
28   },
29   traits::{Bannable, Followable},
30 };
31 use lemmy_utils::{utils::convert_datetime, LemmyError};
32 use lemmy_websocket::LemmyContext;
33
34 impl BlockUserFromCommunity {
35   pub(in crate::activities::community) fn new(
36     community: &ApubCommunity,
37     target: &ApubPerson,
38     actor: &ApubPerson,
39     expires: Option<NaiveDateTime>,
40     context: &LemmyContext,
41   ) -> Result<BlockUserFromCommunity, LemmyError> {
42     Ok(BlockUserFromCommunity {
43       actor: ObjectId::new(actor.actor_id()),
44       to: vec![public()],
45       object: ObjectId::new(target.actor_id()),
46       cc: vec![community.actor_id()],
47       target: ObjectId::new(community.actor_id()),
48       kind: BlockType::Block,
49       id: generate_activity_id(
50         BlockType::Block,
51         &context.settings().get_protocol_and_hostname(),
52       )?,
53       expires: expires.map(convert_datetime),
54       unparsed: Default::default(),
55     })
56   }
57
58   #[tracing::instrument(skip_all)]
59   pub async fn send(
60     community: &ApubCommunity,
61     target: &ApubPerson,
62     actor: &ApubPerson,
63     expires: Option<NaiveDateTime>,
64     context: &LemmyContext,
65   ) -> Result<(), LemmyError> {
66     let block = BlockUserFromCommunity::new(community, target, actor, expires, context)?;
67     let block_id = block.id.clone();
68
69     let activity = AnnouncableActivities::BlockUserFromCommunity(block);
70     let inboxes = vec![target.shared_inbox_or_inbox_url()];
71     send_activity_in_community(activity, &block_id, actor, community, inboxes, context).await
72   }
73 }
74
75 #[async_trait::async_trait(?Send)]
76 impl ActivityHandler for BlockUserFromCommunity {
77   type DataType = LemmyContext;
78
79   #[tracing::instrument(skip_all)]
80   async fn verify(
81     &self,
82     context: &Data<LemmyContext>,
83     request_counter: &mut i32,
84   ) -> Result<(), LemmyError> {
85     verify_is_public(&self.to, &self.cc)?;
86     verify_activity(&self.id, self.actor.inner(), &context.settings())?;
87     let community = self.get_community(context, request_counter).await?;
88     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
89     verify_mod_action(&self.actor, &community, context, request_counter).await?;
90     Ok(())
91   }
92
93   #[tracing::instrument(skip_all)]
94   async fn receive(
95     self,
96     context: &Data<LemmyContext>,
97     request_counter: &mut i32,
98   ) -> Result<(), LemmyError> {
99     let community = self.get_community(context, request_counter).await?;
100     let blocked_user = self
101       .object
102       .dereference(context, context.client(), request_counter)
103       .await?;
104
105     let community_user_ban_form = CommunityPersonBanForm {
106       community_id: community.id,
107       person_id: blocked_user.id,
108       expires: Some(self.expires.map(|u| u.naive_local())),
109     };
110
111     blocking(context.pool(), move |conn: &'_ _| {
112       CommunityPersonBan::ban(conn, &community_user_ban_form)
113     })
114     .await??;
115
116     // Also unsubscribe them from the community, if they are subscribed
117     let community_follower_form = CommunityFollowerForm {
118       community_id: community.id,
119       person_id: blocked_user.id,
120       pending: false,
121     };
122     blocking(context.pool(), move |conn: &'_ _| {
123       CommunityFollower::unfollow(conn, &community_follower_form)
124     })
125     .await?
126     .ok();
127
128     Ok(())
129   }
130 }
131
132 #[async_trait::async_trait(?Send)]
133 impl GetCommunity for BlockUserFromCommunity {
134   #[tracing::instrument(skip_all)]
135   async fn get_community(
136     &self,
137     context: &LemmyContext,
138     request_counter: &mut i32,
139   ) -> Result<ApubCommunity, LemmyError> {
140     self
141       .target
142       .dereference(context, context.client(), request_counter)
143       .await
144   }
145 }