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