-///
-/// Note that only one of allowlist and blacklist can be enabled, not both.
-pub fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
- let settings = Settings::get();
- let domain = apub_id.domain().context(location_info!())?.to_string();
- let local_instance = settings.get_hostname_without_port()?;
-
- if !settings.federation().enabled {
- return if domain == local_instance {
- Ok(())
- } else {
- Err(
- anyhow!(
- "Trying to connect with {}, but federation is disabled",
- domain
- )
- .into(),
- )
- };
- }
-
- let host = apub_id.host_str().context(location_info!())?;
- let host_as_ip = host.parse::<IpAddr>();
- if host == "localhost" || host_as_ip.is_ok() {
- return Err(anyhow!("invalid hostname {}: {}", host, apub_id).into());
- }
-
- if apub_id.scheme() != Settings::get().get_protocol_string() {
- return Err(anyhow!("invalid apub id scheme {}: {}", apub_id.scheme(), apub_id).into());
- }
-
- let allowed_instances = Settings::get().get_allowed_instances();
- let blocked_instances = Settings::get().get_blocked_instances();
-
- if allowed_instances.is_none() && blocked_instances.is_none() {
- Ok(())
- } else if let Some(mut allowed) = allowed_instances {
- // need to allow this explicitly because apub receive might contain objects from our local
- // instance. split is needed to remove the port in our federation test setup.
- allowed.push(local_instance);
-
- if allowed.contains(&domain) {
- Ok(())
- } else {
- Err(anyhow!("{} not in federation allowlist", domain).into())
- }
- } else if let Some(blocked) = blocked_instances {
- if blocked.contains(&domain) {
- Err(anyhow!("{} is in federation blocklist", domain).into())
- } else {
- Ok(())
- }
- } else {
- panic!("Invalid config, both allowed_instances and blocked_instances are specified");
- }
-}
-
-/// Common functions for ActivityPub objects, which are implemented by most (but not all) objects
-/// and actors in Lemmy.
-#[async_trait::async_trait(?Send)]
-pub trait ApubObjectType {
- async fn send_create(&self, creator: &DbPerson, context: &LemmyContext)
- -> Result<(), LemmyError>;
- async fn send_update(&self, creator: &DbPerson, context: &LemmyContext)
- -> Result<(), LemmyError>;
- async fn send_delete(&self, creator: &DbPerson, context: &LemmyContext)
- -> Result<(), LemmyError>;
- async fn send_undo_delete(
- &self,
- creator: &DbPerson,
- context: &LemmyContext,
- ) -> Result<(), LemmyError>;
- async fn send_remove(&self, mod_: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>;
- async fn send_undo_remove(
- &self,
- mod_: &DbPerson,
- context: &LemmyContext,
- ) -> Result<(), LemmyError>;
-}
-
-#[async_trait::async_trait(?Send)]
-pub trait ApubLikeableType {
- async fn send_like(&self, creator: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>;
- async fn send_dislike(
- &self,
- creator: &DbPerson,
- context: &LemmyContext,
- ) -> Result<(), LemmyError>;
- async fn send_undo_like(
- &self,
- creator: &DbPerson,
- context: &LemmyContext,
- ) -> Result<(), LemmyError>;
-}
-
-/// Common methods provided by ActivityPub actors (community and person). Not all methods are
-/// implemented by all actors.
-#[async_trait::async_trait(?Send)]
-pub trait ActorType {
- fn is_local(&self) -> bool;
- fn actor_id(&self) -> Url;
-
- // TODO: every actor should have a public key, so this shouldnt be an option (needs to be fixed in db)
- fn public_key(&self) -> Option<String>;
- fn private_key(&self) -> Option<String>;
-
- fn get_shared_inbox_or_inbox_url(&self) -> Url;
-
- /// Outbox URL is not generally used by Lemmy, so it can be generated on the fly (but only for
- /// local actors).
- fn get_outbox_url(&self) -> Result<Url, LemmyError> {
- /* TODO
- if !self.is_local() {
- return Err(anyhow!("get_outbox_url() called for remote actor").into());
- }
- */
- Ok(Url::parse(&format!("{}/outbox", &self.actor_id()))?)
- }
-
- fn get_public_key_ext(&self) -> Result<PublicKeyExtension, LemmyError> {
- Ok(
- PublicKey {
- id: format!("{}#main-key", self.actor_id()),
- owner: self.actor_id(),
- public_key_pem: self.public_key().context(location_info!())?,
- }
- .to_ext(),
- )