]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/block_user.rs
Move code to apub library (#1795)
[lemmy.git] / crates / apub / src / activities / community / block_user.rs
1 use crate::{
2   activities::{
3     community::{announce::AnnouncableActivities, send_to_community},
4     generate_activity_id,
5     verify_activity,
6     verify_mod_action,
7     verify_person_in_community,
8   },
9   context::lemmy_context,
10   fetcher::object_id::ObjectId,
11 };
12 use activitystreams::{
13   activity::kind::BlockType,
14   base::AnyBase,
15   primitives::OneOrMany,
16   unparsed::Unparsed,
17 };
18 use lemmy_api_common::blocking;
19 use lemmy_apub_lib::{
20   data::Data,
21   traits::{ActivityFields, ActivityHandler, ActorType},
22   values::PublicUrl,
23 };
24 use lemmy_db_queries::{Bannable, Followable};
25 use lemmy_db_schema::source::{
26   community::{
27     Community,
28     CommunityFollower,
29     CommunityFollowerForm,
30     CommunityPersonBan,
31     CommunityPersonBanForm,
32   },
33   person::Person,
34 };
35 use lemmy_utils::LemmyError;
36 use lemmy_websocket::LemmyContext;
37 use serde::{Deserialize, Serialize};
38 use url::Url;
39
40 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
41 #[serde(rename_all = "camelCase")]
42 pub struct BlockUserFromCommunity {
43   actor: ObjectId<Person>,
44   to: [PublicUrl; 1],
45   pub(in crate::activities::community) object: ObjectId<Person>,
46   cc: [ObjectId<Community>; 1],
47   #[serde(rename = "type")]
48   kind: BlockType,
49   id: Url,
50   #[serde(rename = "@context")]
51   context: OneOrMany<AnyBase>,
52   #[serde(flatten)]
53   unparsed: Unparsed,
54 }
55
56 impl BlockUserFromCommunity {
57   pub(in crate::activities::community) fn new(
58     community: &Community,
59     target: &Person,
60     actor: &Person,
61     context: &LemmyContext,
62   ) -> Result<BlockUserFromCommunity, LemmyError> {
63     Ok(BlockUserFromCommunity {
64       actor: ObjectId::new(actor.actor_id()),
65       to: [PublicUrl::Public],
66       object: ObjectId::new(target.actor_id()),
67       cc: [ObjectId::new(community.actor_id())],
68       kind: BlockType::Block,
69       id: generate_activity_id(
70         BlockType::Block,
71         &context.settings().get_protocol_and_hostname(),
72       )?,
73       context: lemmy_context(),
74       unparsed: Default::default(),
75     })
76   }
77
78   pub async fn send(
79     community: &Community,
80     target: &Person,
81     actor: &Person,
82     context: &LemmyContext,
83   ) -> Result<(), LemmyError> {
84     let block = BlockUserFromCommunity::new(community, target, actor, context)?;
85     let block_id = block.id.clone();
86
87     let activity = AnnouncableActivities::BlockUserFromCommunity(block);
88     let inboxes = vec![target.shared_inbox_or_inbox_url()];
89     send_to_community(activity, &block_id, actor, community, inboxes, context).await
90   }
91 }
92
93 #[async_trait::async_trait(?Send)]
94 impl ActivityHandler for BlockUserFromCommunity {
95   type DataType = LemmyContext;
96   async fn verify(
97     &self,
98     context: &Data<LemmyContext>,
99     request_counter: &mut i32,
100   ) -> Result<(), LemmyError> {
101     verify_activity(self, &context.settings())?;
102     verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
103     verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
104     Ok(())
105   }
106
107   async fn receive(
108     self,
109     context: &Data<LemmyContext>,
110     request_counter: &mut i32,
111   ) -> Result<(), LemmyError> {
112     let community = self.cc[0].dereference(context, request_counter).await?;
113     let blocked_user = self.object.dereference(context, request_counter).await?;
114
115     let community_user_ban_form = CommunityPersonBanForm {
116       community_id: community.id,
117       person_id: blocked_user.id,
118     };
119
120     blocking(context.pool(), move |conn: &'_ _| {
121       CommunityPersonBan::ban(conn, &community_user_ban_form)
122     })
123     .await??;
124
125     // Also unsubscribe them from the community, if they are subscribed
126     let community_follower_form = CommunityFollowerForm {
127       community_id: community.id,
128       person_id: blocked_user.id,
129       pending: false,
130     };
131     blocking(context.pool(), move |conn: &'_ _| {
132       CommunityFollower::unfollow(conn, &community_follower_form)
133     })
134     .await?
135     .ok();
136
137     Ok(())
138   }
139 }