]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/remove_mod.rs
Moving settings and secrets to context.
[lemmy.git] / crates / apub / src / activities / community / remove_mod.rs
1 use crate::{
2   activities::{
3     community::announce::AnnouncableActivities,
4     deletion::{delete::receive_remove_action, verify_delete_activity},
5     generate_activity_id,
6     verify_activity,
7     verify_add_remove_moderator_target,
8     verify_mod_action,
9     verify_person_in_community,
10   },
11   activity_queue::send_to_community_new,
12   extensions::context::lemmy_context,
13   fetcher::object_id::ObjectId,
14   generate_moderators_url,
15   ActorType,
16 };
17 use activitystreams::{
18   activity::kind::RemoveType,
19   base::AnyBase,
20   primitives::OneOrMany,
21   unparsed::Unparsed,
22 };
23 use lemmy_api_common::blocking;
24 use lemmy_apub_lib::{values::PublicUrl, ActivityFields, ActivityHandler};
25 use lemmy_db_queries::Joinable;
26 use lemmy_db_schema::source::{
27   community::{Community, CommunityModerator, CommunityModeratorForm},
28   person::Person,
29 };
30 use lemmy_utils::LemmyError;
31 use lemmy_websocket::LemmyContext;
32 use serde::{Deserialize, Serialize};
33 use url::Url;
34
35 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
36 #[serde(rename_all = "camelCase")]
37 pub struct RemoveMod {
38   actor: ObjectId<Person>,
39   to: [PublicUrl; 1],
40   pub(in crate::activities) object: ObjectId<Person>,
41   cc: [ObjectId<Community>; 1],
42   #[serde(rename = "type")]
43   kind: RemoveType,
44   // if target is set, this is means remove mod from community
45   pub(in crate::activities) target: Option<Url>,
46   id: Url,
47   #[serde(rename = "@context")]
48   context: OneOrMany<AnyBase>,
49   #[serde(flatten)]
50   unparsed: Unparsed,
51 }
52
53 impl RemoveMod {
54   pub async fn send(
55     community: &Community,
56     removed_mod: &Person,
57     actor: &Person,
58     context: &LemmyContext,
59   ) -> Result<(), LemmyError> {
60     let id = generate_activity_id(
61       RemoveType::Remove,
62       &context.settings().get_protocol_and_hostname(),
63     )?;
64     let remove = RemoveMod {
65       actor: ObjectId::new(actor.actor_id()),
66       to: [PublicUrl::Public],
67       object: ObjectId::new(removed_mod.actor_id()),
68       target: Some(generate_moderators_url(&community.actor_id)?.into()),
69       id: id.clone(),
70       context: lemmy_context(),
71       cc: [ObjectId::new(community.actor_id())],
72       kind: RemoveType::Remove,
73       unparsed: Default::default(),
74     };
75
76     let activity = AnnouncableActivities::RemoveMod(remove);
77     let inboxes = vec![removed_mod.get_shared_inbox_or_inbox_url()];
78     send_to_community_new(activity, &id, actor, community, inboxes, context).await
79   }
80 }
81
82 #[async_trait::async_trait(?Send)]
83 impl ActivityHandler for RemoveMod {
84   async fn verify(
85     &self,
86     context: &LemmyContext,
87     request_counter: &mut i32,
88   ) -> Result<(), LemmyError> {
89     verify_activity(self, &context.settings())?;
90     if let Some(target) = &self.target {
91       verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
92       verify_mod_action(&self.actor, self.cc[0].clone(), context).await?;
93       verify_add_remove_moderator_target(target, &self.cc[0])?;
94     } else {
95       verify_delete_activity(
96         self.object.inner(),
97         self,
98         &self.cc[0],
99         true,
100         context,
101         request_counter,
102       )
103       .await?;
104     }
105     Ok(())
106   }
107
108   async fn receive(
109     self,
110     context: &LemmyContext,
111     request_counter: &mut i32,
112   ) -> Result<(), LemmyError> {
113     if self.target.is_some() {
114       let community = self.cc[0].dereference(context, request_counter).await?;
115       let remove_mod = self.object.dereference(context, request_counter).await?;
116
117       let form = CommunityModeratorForm {
118         community_id: community.id,
119         person_id: remove_mod.id,
120       };
121       blocking(context.pool(), move |conn| {
122         CommunityModerator::leave(conn, &form)
123       })
124       .await??;
125       // TODO: send websocket notification about removed mod
126       Ok(())
127     } else {
128       receive_remove_action(
129         &self.actor,
130         self.object.inner(),
131         None,
132         context,
133         request_counter,
134       )
135       .await
136     }
137   }
138 }