]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/removal/remove.rs
Rewrite delete activities (#1699)
[lemmy.git] / crates / apub / src / activities / removal / remove.rs
1 use crate::{
2   activities::{
3     deletion::{delete::receive_remove_action, verify_delete_activity},
4     verify_activity,
5     verify_add_remove_moderator_target,
6     verify_mod_action,
7     verify_person_in_community,
8   },
9   fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
10   CommunityType,
11 };
12 use activitystreams::{activity::kind::RemoveType, base::AnyBase};
13 use lemmy_api_common::blocking;
14 use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler};
15 use lemmy_db_queries::Joinable;
16 use lemmy_db_schema::source::community::{CommunityModerator, CommunityModeratorForm};
17 use lemmy_utils::LemmyError;
18 use lemmy_websocket::LemmyContext;
19 use url::Url;
20
21 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
22 #[serde(rename_all = "camelCase")]
23 pub struct RemoveMod {
24   to: PublicUrl,
25   pub(in crate::activities::removal) object: Url,
26   cc: [Url; 1],
27   #[serde(rename = "type")]
28   kind: RemoveType,
29   // if target is set, this is means remove mod from community
30   pub(in crate::activities::removal) target: Option<Url>,
31   #[serde(flatten)]
32   common: ActivityCommonFields,
33 }
34
35 #[async_trait::async_trait(?Send)]
36 impl ActivityHandler for RemoveMod {
37   async fn verify(
38     &self,
39     context: &LemmyContext,
40     request_counter: &mut i32,
41   ) -> Result<(), LemmyError> {
42     verify_activity(self.common())?;
43     if let Some(target) = &self.target {
44       verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
45       verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
46       verify_add_remove_moderator_target(target, self.cc[0].clone())?;
47     } else {
48       verify_delete_activity(
49         &self.object,
50         &self.cc[0],
51         self.common(),
52         true,
53         context,
54         request_counter,
55       )
56       .await?;
57     }
58     Ok(())
59   }
60
61   async fn receive(
62     self,
63     context: &LemmyContext,
64     request_counter: &mut i32,
65   ) -> Result<(), LemmyError> {
66     if self.target.is_some() {
67       let community =
68         get_or_fetch_and_upsert_community(&self.cc[0], context, request_counter).await?;
69       let remove_mod =
70         get_or_fetch_and_upsert_person(&self.object, context, request_counter).await?;
71
72       let form = CommunityModeratorForm {
73         community_id: community.id,
74         person_id: remove_mod.id,
75       };
76       blocking(context.pool(), move |conn| {
77         CommunityModerator::leave(conn, &form)
78       })
79       .await??;
80       let anybase = AnyBase::from_arbitrary_json(serde_json::to_string(&self)?)?;
81       community
82         .send_announce(anybase, Some(self.object.clone()), context)
83         .await?;
84       // TODO: send websocket notification about removed mod
85       Ok(())
86     } else {
87       receive_remove_action(
88         &self.common.actor,
89         &self.object,
90         None,
91         context,
92         request_counter,
93       )
94       .await
95     }
96   }
97
98   fn common(&self) -> &ActivityCommonFields {
99     &self.common
100   }
101 }