]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/remove_mod.rs
Move @context out of object/activity definitions
[lemmy.git] / crates / apub / src / activities / community / remove_mod.rs
1 use crate::{
2   activities::{
3     community::{
4       announce::{AnnouncableActivities, GetCommunity},
5       get_community_from_moderators_url,
6       send_to_community,
7     },
8     generate_activity_id,
9     verify_activity,
10     verify_add_remove_moderator_target,
11     verify_is_public,
12     verify_mod_action,
13     verify_person_in_community,
14   },
15   fetcher::object_id::ObjectId,
16   generate_moderators_url,
17   objects::{community::ApubCommunity, person::ApubPerson},
18 };
19 use activitystreams::{activity::kind::RemoveType, public, unparsed::Unparsed};
20 use lemmy_api_common::blocking;
21 use lemmy_apub_lib::{
22   data::Data,
23   traits::{ActivityFields, ActivityHandler, ActorType},
24 };
25 use lemmy_db_schema::{
26   source::community::{CommunityModerator, CommunityModeratorForm},
27   traits::Joinable,
28 };
29 use lemmy_utils::LemmyError;
30 use lemmy_websocket::LemmyContext;
31 use serde::{Deserialize, Serialize};
32 use url::Url;
33
34 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
35 #[serde(rename_all = "camelCase")]
36 pub struct RemoveMod {
37   actor: ObjectId<ApubPerson>,
38   to: Vec<Url>,
39   pub(in crate::activities) object: ObjectId<ApubPerson>,
40   cc: Vec<Url>,
41   #[serde(rename = "type")]
42   kind: RemoveType,
43   pub(in crate::activities) target: Url,
44   id: Url,
45   #[serde(flatten)]
46   unparsed: Unparsed,
47 }
48
49 impl RemoveMod {
50   pub async fn send(
51     community: &ApubCommunity,
52     removed_mod: &ApubPerson,
53     actor: &ApubPerson,
54     context: &LemmyContext,
55   ) -> Result<(), LemmyError> {
56     let id = generate_activity_id(
57       RemoveType::Remove,
58       &context.settings().get_protocol_and_hostname(),
59     )?;
60     let remove = RemoveMod {
61       actor: ObjectId::new(actor.actor_id()),
62       to: vec![public()],
63       object: ObjectId::new(removed_mod.actor_id()),
64       target: generate_moderators_url(&community.actor_id)?.into(),
65       id: id.clone(),
66       cc: vec![community.actor_id()],
67       kind: RemoveType::Remove,
68       unparsed: Default::default(),
69     };
70
71     let activity = AnnouncableActivities::RemoveMod(remove);
72     let inboxes = vec![removed_mod.shared_inbox_or_inbox_url()];
73     send_to_community(activity, &id, actor, community, inboxes, context).await
74   }
75 }
76
77 #[async_trait::async_trait(?Send)]
78 impl ActivityHandler for RemoveMod {
79   type DataType = LemmyContext;
80   async fn verify(
81     &self,
82     context: &Data<LemmyContext>,
83     request_counter: &mut i32,
84   ) -> Result<(), LemmyError> {
85     verify_is_public(&self.to)?;
86     verify_activity(self, &context.settings())?;
87     let community = self.get_community(context, request_counter).await?;
88     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
89     verify_mod_action(&self.actor, &community, context, request_counter).await?;
90     verify_add_remove_moderator_target(&self.target, &community)?;
91     Ok(())
92   }
93
94   async fn receive(
95     self,
96     context: &Data<LemmyContext>,
97     request_counter: &mut i32,
98   ) -> Result<(), LemmyError> {
99     let community = self.get_community(context, request_counter).await?;
100     let remove_mod = self.object.dereference(context, request_counter).await?;
101
102     let form = CommunityModeratorForm {
103       community_id: community.id,
104       person_id: remove_mod.id,
105     };
106     blocking(context.pool(), move |conn| {
107       CommunityModerator::leave(conn, &form)
108     })
109     .await??;
110     // TODO: send websocket notification about removed mod
111     Ok(())
112   }
113 }
114
115 #[async_trait::async_trait(?Send)]
116 impl GetCommunity for RemoveMod {
117   async fn get_community(
118     &self,
119     context: &LemmyContext,
120     request_counter: &mut i32,
121   ) -> Result<ApubCommunity, LemmyError> {
122     get_community_from_moderators_url(&self.target, context, request_counter).await
123   }
124 }