]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/block/undo_block_user.rs
Add cargo feature for building lemmy_api_common with mininum deps (#2243)
[lemmy.git] / crates / apub / src / activities / block / undo_block_user.rs
1 use crate::{
2   activities::{
3     block::{generate_cc, generate_instance_inboxes, SiteOrCommunity},
4     community::{announce::GetCommunity, send_activity_in_community},
5     generate_activity_id,
6     send_lemmy_activity,
7     verify_activity,
8     verify_is_public,
9   },
10   activity_lists::AnnouncableActivities,
11   objects::{community::ApubCommunity, person::ApubPerson},
12   protocol::activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
13 };
14 use activitystreams_kinds::{activity::UndoType, public};
15 use lemmy_api_common::utils::blocking;
16 use lemmy_apub_lib::{
17   data::Data,
18   object_id::ObjectId,
19   traits::{ActivityHandler, ActorType},
20   verify::verify_domains_match,
21 };
22 use lemmy_db_schema::{
23   source::{
24     community::{CommunityPersonBan, CommunityPersonBanForm},
25     moderator::{ModBan, ModBanForm, ModBanFromCommunity, ModBanFromCommunityForm},
26     person::Person,
27   },
28   traits::{Bannable, Crud},
29 };
30 use lemmy_utils::LemmyError;
31 use lemmy_websocket::LemmyContext;
32
33 impl UndoBlockUser {
34   #[tracing::instrument(skip_all)]
35   pub async fn send(
36     target: &SiteOrCommunity,
37     user: &ApubPerson,
38     mod_: &ApubPerson,
39     reason: Option<String>,
40     context: &LemmyContext,
41   ) -> Result<(), LemmyError> {
42     let block = BlockUser::new(target, user, mod_, None, reason, None, context).await?;
43
44     let id = generate_activity_id(
45       UndoType::Undo,
46       &context.settings().get_protocol_and_hostname(),
47     )?;
48     let undo = UndoBlockUser {
49       actor: ObjectId::new(mod_.actor_id()),
50       to: vec![public()],
51       object: block,
52       cc: generate_cc(target, context.pool()).await?,
53       kind: UndoType::Undo,
54       id: id.clone(),
55       unparsed: Default::default(),
56     };
57
58     let inboxes = vec![user.shared_inbox_or_inbox_url()];
59     match target {
60       SiteOrCommunity::Site(_) => {
61         let inboxes = generate_instance_inboxes(user, context.pool()).await?;
62         send_lemmy_activity(context, &undo, &id, mod_, inboxes, false).await
63       }
64       SiteOrCommunity::Community(c) => {
65         let activity = AnnouncableActivities::UndoBlockUser(undo);
66         send_activity_in_community(activity, &id, mod_, c, inboxes, context).await
67       }
68     }
69   }
70 }
71
72 #[async_trait::async_trait(?Send)]
73 impl ActivityHandler for UndoBlockUser {
74   type DataType = LemmyContext;
75
76   #[tracing::instrument(skip_all)]
77   async fn verify(
78     &self,
79     context: &Data<LemmyContext>,
80     request_counter: &mut i32,
81   ) -> Result<(), LemmyError> {
82     verify_is_public(&self.to, &self.cc)?;
83     verify_activity(&self.id, self.actor.inner(), &context.settings())?;
84     verify_domains_match(self.actor.inner(), self.object.actor.inner())?;
85     self.object.verify(context, request_counter).await?;
86     Ok(())
87   }
88
89   #[tracing::instrument(skip_all)]
90   async fn receive(
91     self,
92     context: &Data<LemmyContext>,
93     request_counter: &mut i32,
94   ) -> Result<(), LemmyError> {
95     let expires = self.object.expires.map(|u| u.naive_local());
96     let mod_person = self
97       .actor
98       .dereference(context, context.client(), request_counter)
99       .await?;
100     let blocked_person = self
101       .object
102       .object
103       .dereference(context, context.client(), request_counter)
104       .await?;
105     match self
106       .object
107       .target
108       .dereference(context, context.client(), request_counter)
109       .await?
110     {
111       SiteOrCommunity::Site(_site) => {
112         let blocked_person = blocking(context.pool(), move |conn| {
113           Person::ban_person(conn, blocked_person.id, false, expires)
114         })
115         .await??;
116
117         // write mod log
118         let form = ModBanForm {
119           mod_person_id: mod_person.id,
120           other_person_id: blocked_person.id,
121           reason: self.object.summary,
122           banned: Some(false),
123           expires,
124         };
125         blocking(context.pool(), move |conn| ModBan::create(conn, &form)).await??;
126       }
127       SiteOrCommunity::Community(community) => {
128         let community_user_ban_form = CommunityPersonBanForm {
129           community_id: community.id,
130           person_id: blocked_person.id,
131           expires: None,
132         };
133         blocking(context.pool(), move |conn: &'_ _| {
134           CommunityPersonBan::unban(conn, &community_user_ban_form)
135         })
136         .await??;
137
138         // write to mod log
139         let form = ModBanFromCommunityForm {
140           mod_person_id: mod_person.id,
141           other_person_id: blocked_person.id,
142           community_id: community.id,
143           reason: self.object.summary,
144           banned: Some(false),
145           expires,
146         };
147         blocking(context.pool(), move |conn| {
148           ModBanFromCommunity::create(conn, &form)
149         })
150         .await??;
151       }
152     }
153
154     Ok(())
155   }
156 }
157
158 #[async_trait::async_trait(?Send)]
159 impl GetCommunity for UndoBlockUser {
160   #[tracing::instrument(skip_all)]
161   async fn get_community(
162     &self,
163     context: &LemmyContext,
164     request_counter: &mut i32,
165   ) -> Result<ApubCommunity, LemmyError> {
166     self.object.get_community(context, request_counter).await
167   }
168 }