2 activity::ActorAndObjectRefExt,
3 base::{AsBase, BaseExt, Extends},
7 use actix_web::HttpRequest;
8 use anyhow::{anyhow, Context};
9 use lemmy_api_common::blocking;
11 check_is_apub_id_valid,
12 extensions::signatures::verify_signature,
13 fetcher::get_or_fetch_and_upsert_actor,
14 get_activity_to_and_cc,
17 use lemmy_db_queries::{
18 source::{activity::Activity_, community::Community_},
22 use lemmy_db_schema::source::{activity::Activity, community::Community, person::Person};
23 use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
24 use lemmy_websocket::LemmyContext;
29 pub mod community_inbox;
31 pub(crate) mod receive_for_community;
34 pub(crate) fn get_activity_id<T, Kind>(activity: &T, creator_uri: &Url) -> Result<Url, LemmyError>
36 T: BaseExt<Kind> + Extends<Kind> + Debug,
38 <T as Extends<Kind>>::Error: From<serde_json::Error> + Send + Sync + 'static,
40 let creator_domain = creator_uri.host_str().context(location_info!())?;
41 let activity_id = activity.id(creator_domain)?;
42 Ok(activity_id.context(location_info!())?.to_owned())
45 pub(crate) async fn is_activity_already_known(
48 ) -> Result<bool, LemmyError> {
49 let activity_id = activity_id.to_owned().into();
50 let existing = blocking(pool, move |conn| {
51 Activity::read_from_apub_id(&conn, &activity_id)
60 pub(crate) fn verify_is_addressed_to_public<T, Kind>(activity: &T) -> Result<(), LemmyError>
62 T: AsBase<Kind> + AsObject<Kind> + ActorAndObjectRefExt,
64 let to_and_cc = get_activity_to_and_cc(activity);
65 if to_and_cc.contains(&public()) {
68 Err(anyhow!("Activity is not addressed to public").into())
72 pub(crate) async fn inbox_verify_http_signature<T, Kind>(
74 context: &LemmyContext,
76 request_counter: &mut i32,
77 ) -> Result<Box<dyn ActorType>, LemmyError>
79 T: AsObject<Kind> + ActorAndObjectRefExt + Extends<Kind> + AsBase<Kind>,
81 <T as Extends<Kind>>::Error: From<serde_json::Error> + Send + Sync + 'static,
83 let actor_id = activity
87 .context(location_info!())?;
88 check_is_apub_id_valid(&actor_id, false)?;
89 let actor = get_or_fetch_and_upsert_actor(&actor_id, &context, request_counter).await?;
90 verify_signature(&request, actor.as_ref())?;
94 /// Returns true if `to_and_cc` contains at least one local user.
95 pub(crate) async fn is_addressed_to_local_person(
98 ) -> Result<bool, LemmyError> {
99 for url in to_and_cc {
100 let url = url.to_owned();
101 let person = blocking(&pool, move |conn| {
102 Person::read_from_apub_id(&conn, &url.into())
105 if let Ok(u) = person {
114 /// If `to_and_cc` contains the followers collection of a remote community, returns this community
115 /// (like `https://example.com/c/main/followers`)
116 pub(crate) async fn is_addressed_to_community_followers(
119 ) -> Result<Option<Community>, LemmyError> {
120 for url in to_and_cc {
121 let url = url.to_owned().into();
122 let community = blocking(&pool, move |conn| {
123 // ignore errors here, because the current url might not actually be a followers url
124 Community::read_from_followers_url(&conn, &url).ok()
127 if let Some(c) = community {
136 pub(in crate::inbox) fn assert_activity_not_local<T, Kind>(activity: &T) -> Result<(), LemmyError>
138 T: BaseExt<Kind> + Debug,
140 let id = activity.id_unchecked().context(location_info!())?;
141 let activity_domain = id.domain().context(location_info!())?;
143 if activity_domain == Settings::get().hostname() {
146 "Error: received activity which was sent by local instance: {:?}",