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