]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/receive/mod.rs
Move most code into crates/ subfolder
[lemmy.git] / crates / apub / src / activities / receive / mod.rs
1 use crate::fetcher::user::get_or_fetch_and_upsert_user;
2 use activitystreams::{
3   activity::{ActorAndObjectRef, ActorAndObjectRefExt},
4   base::{AsBase, BaseExt},
5   error::DomainError,
6 };
7 use anyhow::{anyhow, Context};
8 use lemmy_db_schema::source::user::User_;
9 use lemmy_utils::{location_info, LemmyError};
10 use lemmy_websocket::LemmyContext;
11 use log::debug;
12 use std::fmt::Debug;
13 use url::Url;
14
15 pub(crate) mod comment;
16 pub(crate) mod comment_undo;
17 pub(crate) mod community;
18 pub(crate) mod post;
19 pub(crate) mod post_undo;
20 pub(crate) mod private_message;
21
22 /// Return HTTP 501 for unsupported activities in inbox.
23 pub(crate) fn receive_unhandled_activity<A>(activity: A) -> Result<(), LemmyError>
24 where
25   A: Debug,
26 {
27   debug!("received unhandled activity type: {:?}", activity);
28   Err(anyhow!("Activity not supported").into())
29 }
30
31 /// Reads the actor field of an activity and returns the corresponding `User_`.
32 pub(crate) async fn get_actor_as_user<T, A>(
33   activity: &T,
34   context: &LemmyContext,
35   request_counter: &mut i32,
36 ) -> Result<User_, LemmyError>
37 where
38   T: AsBase<A> + ActorAndObjectRef,
39 {
40   let actor = activity.actor()?;
41   let user_uri = actor.as_single_xsd_any_uri().context(location_info!())?;
42   get_or_fetch_and_upsert_user(&user_uri, context, request_counter).await
43 }
44
45 /// Ensure that the ID of an incoming activity comes from the same domain as the actor. Optionally
46 /// also checks the ID of the inner object.
47 ///
48 /// The reason that this starts with the actor ID is that it was already confirmed as correct by the
49 /// HTTP signature.
50 pub(crate) fn verify_activity_domains_valid<T, Kind>(
51   activity: &T,
52   actor_id: &Url,
53   object_domain_must_match: bool,
54 ) -> Result<(), LemmyError>
55 where
56   T: AsBase<Kind> + ActorAndObjectRef,
57 {
58   let expected_domain = actor_id.domain().context(location_info!())?;
59
60   activity.id(expected_domain)?;
61
62   let object_id = match activity.object().to_owned().single_xsd_any_uri() {
63     // object is just an ID
64     Some(id) => id,
65     // object is something like an activity, a comment or a post
66     None => activity
67       .object()
68       .to_owned()
69       .one()
70       .context(location_info!())?
71       .id()
72       .context(location_info!())?
73       .to_owned(),
74   };
75
76   if object_domain_must_match && object_id.domain() != Some(expected_domain) {
77     return Err(DomainError.into());
78   }
79
80   Ok(())
81 }