]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/lock_page.rs
498c3a324983b0028396a89b65ecd5da82a123ea
[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_activity,
12   protocol::{
13     activities::{
14       community::lock_page::{LockPage, LockType, UndoLockPage},
15       create_or_update::page::CreateOrUpdatePage,
16       CreateOrUpdateType,
17     },
18     InCommunity,
19   },
20   SendActivity,
21 };
22 use activitypub_federation::{
23   config::Data,
24   kinds::{activity::UndoType, public},
25   traits::ActivityHandler,
26 };
27 use lemmy_api_common::{
28   context::LemmyContext,
29   post::{LockPost, PostResponse},
30   utils::get_local_user_view_from_jwt,
31 };
32 use lemmy_db_schema::{
33   source::{
34     community::Community,
35     post::{Post, PostUpdateForm},
36   },
37   traits::Crud,
38 };
39 use lemmy_utils::error::LemmyError;
40 use url::Url;
41
42 #[async_trait::async_trait]
43 impl ActivityHandler for LockPage {
44   type DataType = LemmyContext;
45   type Error = LemmyError;
46
47   fn id(&self) -> &Url {
48     &self.id
49   }
50
51   fn actor(&self) -> &Url {
52     self.actor.inner()
53   }
54
55   async fn verify(&self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
56     verify_is_public(&self.to, &self.cc)?;
57     let community = self.community(context).await?;
58     verify_person_in_community(&self.actor, &community, context).await?;
59     check_community_deleted_or_removed(&community)?;
60     verify_mod_action(&self.actor, self.object.inner(), community.id, context).await?;
61     Ok(())
62   }
63
64   async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
65     let form = PostUpdateForm::builder().locked(Some(true)).build();
66     let post = self.object.dereference(context).await?;
67     Post::update(context.pool(), post.id, &form).await?;
68     Ok(())
69   }
70 }
71
72 #[async_trait::async_trait]
73 impl ActivityHandler for UndoLockPage {
74   type DataType = LemmyContext;
75   type Error = LemmyError;
76
77   fn id(&self) -> &Url {
78     &self.id
79   }
80
81   fn actor(&self) -> &Url {
82     self.actor.inner()
83   }
84
85   async fn verify(&self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
86     verify_is_public(&self.to, &self.cc)?;
87     let community = self.community(context).await?;
88     verify_person_in_community(&self.actor, &community, context).await?;
89     check_community_deleted_or_removed(&community)?;
90     verify_mod_action(
91       &self.actor,
92       self.object.object.inner(),
93       community.id,
94       context,
95     )
96     .await?;
97     Ok(())
98   }
99
100   async fn receive(self, context: &Data<Self::DataType>) -> Result<(), Self::Error> {
101     insert_activity(&self.id, &self, false, false, context).await?;
102     let form = PostUpdateForm::builder().locked(Some(false)).build();
103     let post = self.object.object.dereference(context).await?;
104     Post::update(context.pool(), post.id, &form).await?;
105     Ok(())
106   }
107 }
108
109 #[async_trait::async_trait]
110 impl SendActivity for LockPost {
111   type Response = PostResponse;
112
113   async fn send_activity(
114     request: &Self,
115     response: &Self::Response,
116     context: &Data<LemmyContext>,
117   ) -> Result<(), LemmyError> {
118     let local_user_view =
119       get_local_user_view_from_jwt(&request.auth, context.pool(), context.secret()).await?;
120     // For backwards compat with 0.17
121     CreateOrUpdatePage::send(
122       &response.post_view.post,
123       local_user_view.person.id,
124       CreateOrUpdateType::Update,
125       context,
126     )
127     .await?;
128     let id = generate_activity_id(
129       LockType::Lock,
130       &context.settings().get_protocol_and_hostname(),
131     )?;
132     let community_id = response.post_view.community.actor_id.clone();
133     let actor = local_user_view.person.actor_id.clone().into();
134     let lock = LockPage {
135       actor,
136       to: vec![public()],
137       object: response.post_view.post.ap_id.clone().into(),
138       cc: vec![community_id.clone().into()],
139       kind: LockType::Lock,
140       id,
141       audience: Some(community_id.into()),
142     };
143     let activity = if request.locked {
144       AnnouncableActivities::LockPost(lock)
145     } else {
146       let id = generate_activity_id(
147         UndoType::Undo,
148         &context.settings().get_protocol_and_hostname(),
149       )?;
150       let undo = UndoLockPage {
151         actor: lock.actor.clone(),
152         to: vec![public()],
153         cc: lock.cc.clone(),
154         kind: UndoType::Undo,
155         id,
156         audience: lock.audience.clone(),
157         object: lock,
158       };
159       AnnouncableActivities::UndoLockPost(undo)
160     };
161     let community = Community::read(context.pool(), response.post_view.community.id).await?;
162     send_activity_in_community(
163       activity,
164       &local_user_view.person.into(),
165       &community.into(),
166       vec![],
167       true,
168       context,
169     )
170     .await?;
171     Ok(())
172   }
173 }