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