]> Untitled Git - lemmy.git/blob - crates/apub/src/http/community.rs
Dont serve apub json for removed objects (ref #2522) (#2538)
[lemmy.git] / crates / apub / src / http / community.rs
1 use crate::{
2   activity_lists::GroupInboxActivities,
3   collections::{
4     community_moderators::ApubCommunityModerators,
5     community_outbox::ApubCommunityOutbox,
6     CommunityContext,
7   },
8   generate_outbox_url,
9   http::{create_apub_response, create_apub_tombstone_response, receive_lemmy_activity},
10   local_instance,
11   objects::{community::ApubCommunity, person::ApubPerson},
12   protocol::collections::group_followers::GroupFollowers,
13 };
14 use activitypub_federation::{
15   core::object_id::ObjectId,
16   deser::context::WithContext,
17   traits::ApubObject,
18 };
19 use actix_web::{web, HttpRequest, HttpResponse};
20 use lemmy_api_common::utils::blocking;
21 use lemmy_db_schema::{source::community::Community, traits::ApubActor};
22 use lemmy_utils::error::LemmyError;
23 use lemmy_websocket::LemmyContext;
24 use serde::Deserialize;
25
26 #[derive(Deserialize)]
27 pub(crate) struct CommunityQuery {
28   community_name: String,
29 }
30
31 /// Return the ActivityPub json representation of a local community over HTTP.
32 #[tracing::instrument(skip_all)]
33 pub(crate) async fn get_apub_community_http(
34   info: web::Path<CommunityQuery>,
35   context: web::Data<LemmyContext>,
36 ) -> Result<HttpResponse, LemmyError> {
37   let community: ApubCommunity = blocking(context.pool(), move |conn| {
38     Community::read_from_name(conn, &info.community_name, true)
39   })
40   .await??
41   .into();
42
43   if !community.deleted && !community.removed {
44     let apub = community.into_apub(&**context).await?;
45
46     Ok(create_apub_response(&apub))
47   } else {
48     Ok(create_apub_tombstone_response(community.actor_id.clone()))
49   }
50 }
51
52 /// Handler for all incoming receive to community inboxes.
53 #[tracing::instrument(skip_all)]
54 pub async fn community_inbox(
55   request: HttpRequest,
56   payload: String,
57   context: web::Data<LemmyContext>,
58 ) -> Result<HttpResponse, LemmyError> {
59   receive_lemmy_activity::<WithContext<GroupInboxActivities>, ApubPerson>(request, payload, context)
60     .await
61 }
62
63 /// Returns an empty followers collection, only populating the size (for privacy).
64 pub(crate) async fn get_apub_community_followers(
65   info: web::Path<CommunityQuery>,
66   context: web::Data<LemmyContext>,
67 ) -> Result<HttpResponse, LemmyError> {
68   let community = blocking(context.pool(), move |conn| {
69     Community::read_from_name(conn, &info.community_name, false)
70   })
71   .await??;
72   let followers = GroupFollowers::new(community, &context).await?;
73   Ok(create_apub_response(&followers))
74 }
75
76 /// Returns the community outbox, which is populated by a maximum of 20 posts (but no other
77 /// activites like votes or comments).
78 pub(crate) async fn get_apub_community_outbox(
79   info: web::Path<CommunityQuery>,
80   context: web::Data<LemmyContext>,
81 ) -> Result<HttpResponse, LemmyError> {
82   let community = blocking(context.pool(), move |conn| {
83     Community::read_from_name(conn, &info.community_name, false)
84   })
85   .await??;
86   if community.deleted || community.removed {
87     return Err(LemmyError::from_message("deleted"));
88   }
89
90   let id = ObjectId::new(generate_outbox_url(&community.actor_id)?);
91   let outbox_data = CommunityContext(community.into(), context.get_ref().clone());
92   let outbox: ApubCommunityOutbox = id
93     .dereference(&outbox_data, local_instance(&context), &mut 0)
94     .await?;
95   Ok(create_apub_response(&outbox.into_apub(&outbox_data).await?))
96 }
97
98 #[tracing::instrument(skip_all)]
99 pub(crate) async fn get_apub_community_moderators(
100   info: web::Path<CommunityQuery>,
101   context: web::Data<LemmyContext>,
102 ) -> Result<HttpResponse, LemmyError> {
103   let community: ApubCommunity = blocking(context.pool(), move |conn| {
104     Community::read_from_name(conn, &info.community_name, false)
105   })
106   .await??
107   .into();
108   if community.deleted || community.removed {
109     return Err(LemmyError::from_message("deleted"));
110   }
111
112   let id = ObjectId::new(generate_outbox_url(&community.actor_id)?);
113   let outbox_data = CommunityContext(community, context.get_ref().clone());
114   let moderators: ApubCommunityModerators = id
115     .dereference(&outbox_data, local_instance(&context), &mut 0)
116     .await?;
117   Ok(create_apub_response(
118     &moderators.into_apub(&outbox_data).await?,
119   ))
120 }