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