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