]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/add_mod.rs
For verify_is_public() we also need to check cc field
[lemmy.git] / crates / apub / src / activities / community / add_mod.rs
1 use crate::{
2   activities::{
3     community::{announce::GetCommunity, get_community_from_moderators_url, send_to_community},
4     generate_activity_id,
5     verify_activity,
6     verify_add_remove_moderator_target,
7     verify_is_public,
8     verify_mod_action,
9     verify_person_in_community,
10   },
11   activity_lists::AnnouncableActivities,
12   generate_moderators_url,
13   objects::{community::ApubCommunity, person::ApubPerson},
14   protocol::activities::community::add_mod::AddMod,
15 };
16 use activitystreams::{activity::kind::AddType, public};
17 use lemmy_api_common::blocking;
18 use lemmy_apub_lib::{
19   data::Data,
20   object_id::ObjectId,
21   traits::{ActivityHandler, ActorType},
22 };
23 use lemmy_db_schema::{
24   source::community::{CommunityModerator, CommunityModeratorForm},
25   traits::Joinable,
26 };
27 use lemmy_utils::LemmyError;
28 use lemmy_websocket::LemmyContext;
29
30 impl AddMod {
31   pub async fn send(
32     community: &ApubCommunity,
33     added_mod: &ApubPerson,
34     actor: &ApubPerson,
35     context: &LemmyContext,
36   ) -> Result<(), LemmyError> {
37     let id = generate_activity_id(
38       AddType::Add,
39       &context.settings().get_protocol_and_hostname(),
40     )?;
41     let add = AddMod {
42       actor: ObjectId::new(actor.actor_id()),
43       to: vec![public()],
44       object: ObjectId::new(added_mod.actor_id()),
45       target: generate_moderators_url(&community.actor_id)?.into(),
46       cc: vec![community.actor_id()],
47       kind: AddType::Add,
48       id: id.clone(),
49       unparsed: Default::default(),
50     };
51
52     let activity = AnnouncableActivities::AddMod(add);
53     let inboxes = vec![added_mod.shared_inbox_or_inbox_url()];
54     send_to_community(activity, &id, actor, community, inboxes, context).await
55   }
56 }
57
58 #[async_trait::async_trait(?Send)]
59 impl ActivityHandler for AddMod {
60   type DataType = LemmyContext;
61
62   async fn verify(
63     &self,
64     context: &Data<LemmyContext>,
65     request_counter: &mut i32,
66   ) -> Result<(), LemmyError> {
67     verify_is_public(&self.to, &self.cc)?;
68     verify_activity(&self.id, self.actor.inner(), &context.settings())?;
69     let community = self.get_community(context, request_counter).await?;
70     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
71     verify_mod_action(&self.actor, &community, context, request_counter).await?;
72     verify_add_remove_moderator_target(&self.target, &community)?;
73     Ok(())
74   }
75
76   async fn receive(
77     self,
78     context: &Data<LemmyContext>,
79     request_counter: &mut i32,
80   ) -> Result<(), LemmyError> {
81     let community = self.get_community(context, request_counter).await?;
82     let new_mod = self.object.dereference(context, request_counter).await?;
83
84     // If we had to refetch the community while parsing the activity, then the new mod has already
85     // been added. Skip it here as it would result in a duplicate key error.
86     let new_mod_id = new_mod.id;
87     let moderated_communities = blocking(context.pool(), move |conn| {
88       CommunityModerator::get_person_moderated_communities(conn, new_mod_id)
89     })
90     .await??;
91     if !moderated_communities.contains(&community.id) {
92       let form = CommunityModeratorForm {
93         community_id: community.id,
94         person_id: new_mod.id,
95       };
96       blocking(context.pool(), move |conn| {
97         CommunityModerator::join(conn, &form)
98       })
99       .await??;
100     }
101     // TODO: send websocket notification about added mod
102     Ok(())
103   }
104 }
105
106 #[async_trait::async_trait(?Send)]
107 impl GetCommunity for AddMod {
108   async fn get_community(
109     &self,
110     context: &LemmyContext,
111     request_counter: &mut i32,
112   ) -> Result<ApubCommunity, LemmyError> {
113     get_community_from_moderators_url(&self.target, context, request_counter).await
114   }
115 }