]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/add_mod.rs
Merge pull request #1683 from LemmyNet/fix/comment_count_trigger_issues
[lemmy.git] / crates / apub / src / activities / community / add_mod.rs
1 use crate::{
2   activities::{
3     verify_activity,
4     verify_add_remove_moderator_target,
5     verify_mod_action,
6     verify_person_in_community,
7   },
8   fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
9   CommunityType,
10 };
11 use activitystreams::{activity::kind::AddType, base::AnyBase};
12 use lemmy_api_common::blocking;
13 use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler};
14 use lemmy_db_queries::{source::community::CommunityModerator_, Joinable};
15 use lemmy_db_schema::source::community::{CommunityModerator, CommunityModeratorForm};
16 use lemmy_utils::LemmyError;
17 use lemmy_websocket::LemmyContext;
18 use url::Url;
19
20 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
21 #[serde(rename_all = "camelCase")]
22 pub struct AddMod {
23   to: PublicUrl,
24   object: Url,
25   target: Url,
26   cc: [Url; 1],
27   #[serde(rename = "type")]
28   kind: AddType,
29   #[serde(flatten)]
30   common: ActivityCommonFields,
31 }
32
33 #[async_trait::async_trait(?Send)]
34 impl ActivityHandler for AddMod {
35   async fn verify(
36     &self,
37     context: &LemmyContext,
38     request_counter: &mut i32,
39   ) -> Result<(), LemmyError> {
40     verify_activity(self.common())?;
41     verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
42     verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
43     verify_add_remove_moderator_target(&self.target, self.cc[0].clone())?;
44     Ok(())
45   }
46
47   async fn receive(
48     &self,
49     context: &LemmyContext,
50     request_counter: &mut i32,
51   ) -> Result<(), LemmyError> {
52     let community =
53       get_or_fetch_and_upsert_community(&self.cc[0], context, request_counter).await?;
54     let new_mod = get_or_fetch_and_upsert_person(&self.object, context, request_counter).await?;
55
56     // If we had to refetch the community while parsing the activity, then the new mod has already
57     // been added. Skip it here as it would result in a duplicate key error.
58     let new_mod_id = new_mod.id;
59     let moderated_communities = blocking(context.pool(), move |conn| {
60       CommunityModerator::get_person_moderated_communities(conn, new_mod_id)
61     })
62     .await??;
63     if !moderated_communities.contains(&community.id) {
64       let form = CommunityModeratorForm {
65         community_id: community.id,
66         person_id: new_mod.id,
67       };
68       blocking(context.pool(), move |conn| {
69         CommunityModerator::join(conn, &form)
70       })
71       .await??;
72     }
73     if community.local {
74       let anybase = AnyBase::from_arbitrary_json(serde_json::to_string(self)?)?;
75       community
76         .send_announce(anybase, Some(self.object.clone()), context)
77         .await?;
78     }
79     // TODO: send websocket notification about added mod
80     Ok(())
81   }
82
83   fn common(&self) -> &ActivityCommonFields {
84     &self.common
85   }
86 }