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