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