]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/lock_page.rs
add enable_federated_downvotes site option
[lemmy.git] / crates / apub / src / activities / community / lock_page.rs
1 use crate::{
2   activities::{
3     check_community_deleted_or_removed,
4     community::send_activity_in_community,
5     generate_activity_id,
6     verify_is_public,
7     verify_mod_action,
8     verify_person_in_community,
9   },
10   activity_lists::AnnouncableActivities,
11   insert_received_activity,
12   objects::community::ApubCommunity,
13   protocol::{
14     activities::community::lock_page::{LockPage, LockType, UndoLockPage},
15     InCommunity,
16   },
17 };
18 use activitypub_federation::{
19   config::Data,
20   fetch::object_id::ObjectId,
21   kinds::{activity::UndoType, public},
22   traits::ActivityHandler,
23 };
24 use lemmy_api_common::context::LemmyContext;
25 use lemmy_db_schema::{
26   source::{
27     community::Community,
28     person::Person,
29     post::{Post, PostUpdateForm},
30   },
31   traits::Crud,
32 };
33 use lemmy_utils::error::LemmyError;
34 use url::Url;
35
36 #[async_trait::async_trait]
37 impl ActivityHandler for LockPage {
38   type DataType = LemmyContext;
39   type Error = LemmyError;
40
41   fn id(&self) -> &Url {
42     &self.id
43   }
44
45   fn actor(&self) -> &Url {
46     self.actor.inner()
47   }
48
49   async fn verify(&self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
50     verify_is_public(&self.to, &self.cc)?;
51     let community = self.community(context).await?;
52     verify_person_in_community(&self.actor, &community, context).await?;
53     check_community_deleted_or_removed(&community)?;
54     verify_mod_action(&self.actor, self.object.inner(), community.id, context).await?;
55     Ok(())
56   }
57
58   async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
59     let form = PostUpdateForm {
60       locked: Some(true),
61       ..Default::default()
62     };
63     let post = self.object.dereference(context).await?;
64     Post::update(&mut context.pool(), post.id, &form).await?;
65     Ok(())
66   }
67 }
68
69 #[async_trait::async_trait]
70 impl ActivityHandler for UndoLockPage {
71   type DataType = LemmyContext;
72   type Error = LemmyError;
73
74   fn id(&self) -> &Url {
75     &self.id
76   }
77
78   fn actor(&self) -> &Url {
79     self.actor.inner()
80   }
81
82   async fn verify(&self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
83     insert_received_activity(&self.id, context).await?;
84     verify_is_public(&self.to, &self.cc)?;
85     let community = self.community(context).await?;
86     verify_person_in_community(&self.actor, &community, context).await?;
87     check_community_deleted_or_removed(&community)?;
88     verify_mod_action(
89       &self.actor,
90       self.object.object.inner(),
91       community.id,
92       context,
93     )
94     .await?;
95     Ok(())
96   }
97
98   async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
99     let form = PostUpdateForm {
100       locked: Some(false),
101       ..Default::default()
102     };
103     let post = self.object.object.dereference(context).await?;
104     Post::update(&mut context.pool(), post.id, &form).await?;
105     Ok(())
106   }
107 }
108
109 pub(crate) async fn send_lock_post(
110   post: Post,
111   actor: Person,
112   locked: bool,
113   context: Data<LemmyContext>,
114 ) -> Result<(), LemmyError> {
115   let community: ApubCommunity = Community::read(&mut context.pool(), post.community_id)
116     .await?
117     .into();
118   let id = generate_activity_id(
119     LockType::Lock,
120     &context.settings().get_protocol_and_hostname(),
121   )?;
122   let community_id = community.actor_id.inner().clone();
123   let lock = LockPage {
124     actor: actor.actor_id.clone().into(),
125     to: vec![public()],
126     object: ObjectId::from(post.ap_id),
127     cc: vec![community_id.clone()],
128     kind: LockType::Lock,
129     id,
130     audience: Some(community_id.into()),
131   };
132   let activity = if locked {
133     AnnouncableActivities::LockPost(lock)
134   } else {
135     let id = generate_activity_id(
136       UndoType::Undo,
137       &context.settings().get_protocol_and_hostname(),
138     )?;
139     let undo = UndoLockPage {
140       actor: lock.actor.clone(),
141       to: vec![public()],
142       cc: lock.cc.clone(),
143       kind: UndoType::Undo,
144       id,
145       audience: lock.audience.clone(),
146       object: lock,
147     };
148     AnnouncableActivities::UndoLockPost(undo)
149   };
150   send_activity_in_community(activity, &actor.into(), &community, vec![], true, &context).await?;
151   Ok(())
152 }