]> Untitled Git - lemmy.git/blob - crates/apub_receive/src/activities/community/update.rs
Apub inbox rewrite (#1652)
[lemmy.git] / crates / apub_receive / src / activities / community / update.rs
1 use crate::activities::{
2   community::send_websocket_message,
3   verify_activity,
4   verify_mod_action,
5   verify_person_in_community,
6 };
7 use activitystreams::activity::kind::UpdateType;
8 use lemmy_api_common::blocking;
9 use lemmy_apub::{objects::FromApubToForm, GroupExt};
10 use lemmy_apub_lib::{ActivityCommonFields, ActivityHandler, PublicUrl};
11 use lemmy_db_queries::{ApubObject, Crud};
12 use lemmy_db_schema::source::community::{Community, CommunityForm};
13 use lemmy_utils::LemmyError;
14 use lemmy_websocket::{LemmyContext, UserOperationCrud};
15 use url::Url;
16
17 /// This activity is received from a remote community mod, and updates the description or other
18 /// fields of a local community.
19 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
20 #[serde(rename_all = "camelCase")]
21 pub struct UpdateCommunity {
22   to: PublicUrl,
23   object: GroupExt,
24   cc: [Url; 1],
25   #[serde(rename = "type")]
26   kind: UpdateType,
27   #[serde(flatten)]
28   common: ActivityCommonFields,
29 }
30
31 #[async_trait::async_trait(?Send)]
32 impl ActivityHandler for UpdateCommunity {
33   async fn verify(
34     &self,
35     context: &LemmyContext,
36     request_counter: &mut i32,
37   ) -> Result<(), LemmyError> {
38     verify_activity(self.common())?;
39     verify_person_in_community(&self.common.actor, &self.cc, context, request_counter).await?;
40     verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
41     Ok(())
42   }
43
44   async fn receive(
45     &self,
46     context: &LemmyContext,
47     request_counter: &mut i32,
48   ) -> Result<(), LemmyError> {
49     let cc = self.cc[0].clone().into();
50     let community = blocking(context.pool(), move |conn| {
51       Community::read_from_apub_id(conn, &cc)
52     })
53     .await??;
54
55     let updated_community = CommunityForm::from_apub(
56       &self.object,
57       context,
58       community.actor_id.clone().into(),
59       request_counter,
60       false,
61     )
62     .await?;
63     let cf = CommunityForm {
64       name: updated_community.name,
65       title: updated_community.title,
66       description: updated_community.description,
67       nsfw: updated_community.nsfw,
68       // TODO: icon and banner would be hosted on the other instance, ideally we would copy it to ours
69       icon: updated_community.icon,
70       banner: updated_community.banner,
71       ..CommunityForm::default()
72     };
73     let updated_community = blocking(context.pool(), move |conn| {
74       Community::update(conn, community.id, &cf)
75     })
76     .await??;
77
78     send_websocket_message(
79       updated_community.id,
80       UserOperationCrud::EditCommunity,
81       context,
82     )
83     .await
84   }
85
86   fn common(&self) -> &ActivityCommonFields {
87     &self.common
88   }
89 }