]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/lock_page.rs
Dont return error in case optional auth is invalid (#2879)
[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::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 = local_user_view_from_jwt(&request.auth, context).await?;
119     // For backwards compat with 0.17
120     CreateOrUpdatePage::send(
121       &response.post_view.post,
122       local_user_view.person.id,
123       CreateOrUpdateType::Update,
124       context,
125     )
126     .await?;
127     let id = generate_activity_id(
128       LockType::Lock,
129       &context.settings().get_protocol_and_hostname(),
130     )?;
131     let community_id = response.post_view.community.actor_id.clone();
132     let actor = local_user_view.person.actor_id.clone().into();
133     let lock = LockPage {
134       actor,
135       to: vec![public()],
136       object: response.post_view.post.ap_id.clone().into(),
137       cc: vec![community_id.clone().into()],
138       kind: LockType::Lock,
139       id,
140       audience: Some(community_id.into()),
141     };
142     let activity = if request.locked {
143       AnnouncableActivities::LockPost(lock)
144     } else {
145       let id = generate_activity_id(
146         UndoType::Undo,
147         &context.settings().get_protocol_and_hostname(),
148       )?;
149       let undo = UndoLockPage {
150         actor: lock.actor.clone(),
151         to: vec![public()],
152         cc: lock.cc.clone(),
153         kind: UndoType::Undo,
154         id,
155         audience: lock.audience.clone(),
156         object: lock,
157       };
158       AnnouncableActivities::UndoLockPost(undo)
159     };
160     let community = Community::read(context.pool(), response.post_view.community.id).await?;
161     send_activity_in_community(
162       activity,
163       &local_user_view.person.into(),
164       &community.into(),
165       vec![],
166       true,
167       context,
168     )
169     .await?;
170     Ok(())
171   }
172 }