]> Untitled Git - lemmy.git/blobdiff - crates/apub/src/activities/block/mod.rs
Make functions work with both connection and pool (#3420)
[lemmy.git] / crates / apub / src / activities / block / mod.rs
index bb35d7d211621d2492a493f8eacb89a477cd7b6c..7ee9ec17739d97b0c1d1791d15d96074ee492b95 100644 (file)
@@ -1,16 +1,30 @@
 use crate::{
   objects::{community::ApubCommunity, instance::ApubSite, person::ApubPerson},
-  protocol::objects::{group::Group, instance::Instance},
+  protocol::{
+    activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
+    objects::{group::Group, instance::Instance},
+  },
+  SendActivity,
+};
+use activitypub_federation::{
+  config::Data,
+  fetch::object_id::ObjectId,
+  traits::{Actor, Object},
 };
 use chrono::NaiveDateTime;
-use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  object_id::ObjectId,
-  traits::{ActorType, ApubObject},
+use lemmy_api_common::{
+  community::{BanFromCommunity, BanFromCommunityResponse},
+  context::LemmyContext,
+  person::{BanPerson, BanPersonResponse},
+  utils::local_user_view_from_jwt,
+};
+use lemmy_db_schema::{
+  source::{community::Community, person::Person, site::Site},
+  traits::Crud,
+  utils::DbPool,
 };
-use lemmy_db_schema::{source::site::Site, utils::DbPool};
-use lemmy_utils::LemmyError;
-use lemmy_websocket::LemmyContext;
+use lemmy_db_views::structs::SiteView;
+use lemmy_utils::{error::LemmyError, utils::time::naive_from_unix};
 use serde::Deserialize;
 use url::Url;
 
@@ -30,12 +44,11 @@ pub enum InstanceOrGroup {
   Group(Group),
 }
 
-#[async_trait::async_trait(?Send)]
-impl ApubObject for SiteOrCommunity {
+#[async_trait::async_trait]
+impl Object for SiteOrCommunity {
   type DataType = LemmyContext;
-  type ApubType = InstanceOrGroup;
-  type DbType = ();
-  type TombstoneType = ();
+  type Kind = InstanceOrGroup;
+  type Error = LemmyError;
 
   #[tracing::instrument(skip_all)]
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
@@ -46,66 +59,51 @@ impl ApubObject for SiteOrCommunity {
   }
 
   #[tracing::instrument(skip_all)]
-  async fn read_from_apub_id(
+  async fn read_from_id(
     object_id: Url,
-    data: &Self::DataType,
+    data: &Data<Self::DataType>,
   ) -> Result<Option<Self>, LemmyError>
   where
     Self: Sized,
   {
-    let site = ApubSite::read_from_apub_id(object_id.clone(), data).await?;
+    let site = ApubSite::read_from_id(object_id.clone(), data).await?;
     Ok(match site {
       Some(o) => Some(SiteOrCommunity::Site(o)),
-      None => ApubCommunity::read_from_apub_id(object_id, data)
+      None => ApubCommunity::read_from_id(object_id, data)
         .await?
         .map(SiteOrCommunity::Community),
     })
   }
 
-  async fn delete(self, _data: &Self::DataType) -> Result<(), LemmyError> {
-    unimplemented!()
-  }
-
-  async fn into_apub(self, _data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
+  async fn delete(self, _data: &Data<Self::DataType>) -> Result<(), LemmyError> {
     unimplemented!()
   }
 
-  fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
+  async fn into_json(self, _data: &Data<Self::DataType>) -> Result<Self::Kind, LemmyError> {
     unimplemented!()
   }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
-    apub: &Self::ApubType,
+    apub: &Self::Kind,
     expected_domain: &Url,
-    data: &Self::DataType,
-    request_counter: &mut i32,
+    data: &Data<Self::DataType>,
   ) -> Result<(), LemmyError> {
     match apub {
-      InstanceOrGroup::Instance(i) => {
-        ApubSite::verify(i, expected_domain, data, request_counter).await
-      }
-      InstanceOrGroup::Group(g) => {
-        ApubCommunity::verify(g, expected_domain, data, request_counter).await
-      }
+      InstanceOrGroup::Instance(i) => ApubSite::verify(i, expected_domain, data).await,
+      InstanceOrGroup::Group(g) => ApubCommunity::verify(g, expected_domain, data).await,
     }
   }
 
   #[tracing::instrument(skip_all)]
-  async fn from_apub(
-    apub: Self::ApubType,
-    data: &Self::DataType,
-    request_counter: &mut i32,
-  ) -> Result<Self, LemmyError>
+  async fn from_json(apub: Self::Kind, data: &Data<Self::DataType>) -> Result<Self, LemmyError>
   where
     Self: Sized,
   {
     Ok(match apub {
-      InstanceOrGroup::Instance(p) => {
-        SiteOrCommunity::Site(ApubSite::from_apub(p, data, request_counter).await?)
-      }
+      InstanceOrGroup::Instance(p) => SiteOrCommunity::Site(ApubSite::from_json(p, data).await?),
       InstanceOrGroup::Group(n) => {
-        SiteOrCommunity::Community(ApubCommunity::from_apub(n, data, request_counter).await?)
+        SiteOrCommunity::Community(ApubCommunity::from_json(n, data).await?)
       }
     })
   }
@@ -114,32 +112,107 @@ impl ApubObject for SiteOrCommunity {
 impl SiteOrCommunity {
   fn id(&self) -> ObjectId<SiteOrCommunity> {
     match self {
-      SiteOrCommunity::Site(s) => ObjectId::new(s.actor_id.clone()),
-      SiteOrCommunity::Community(c) => ObjectId::new(c.actor_id.clone()),
+      SiteOrCommunity::Site(s) => ObjectId::from(s.actor_id.clone()),
+      SiteOrCommunity::Community(c) => ObjectId::from(c.actor_id.clone()),
     }
   }
 }
 
-async fn generate_cc(target: &SiteOrCommunity, pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
+async fn generate_cc(
+  target: &SiteOrCommunity,
+  pool: &mut DbPool<'_>,
+) -> Result<Vec<Url>, LemmyError> {
   Ok(match target {
-    SiteOrCommunity::Site(_) => blocking(pool, Site::read_remote_sites)
-      .await??
+    SiteOrCommunity::Site(_) => Site::read_remote_sites(pool)
+      .await?
       .into_iter()
       .map(|s| s.actor_id.into())
       .collect(),
-    SiteOrCommunity::Community(c) => vec![c.actor_id()],
+    SiteOrCommunity::Community(c) => vec![c.id()],
   })
 }
 
-async fn generate_instance_inboxes(
-  blocked_user: &ApubPerson,
-  pool: &DbPool,
-) -> Result<Vec<Url>, LemmyError> {
-  let mut inboxes: Vec<Url> = blocking(pool, Site::read_remote_sites)
-    .await??
-    .into_iter()
-    .map(|s| s.inbox_url.into())
-    .collect();
-  inboxes.push(blocked_user.shared_inbox_or_inbox_url());
-  Ok(inboxes)
+#[async_trait::async_trait]
+impl SendActivity for BanPerson {
+  type Response = BanPersonResponse;
+
+  async fn send_activity(
+    request: &Self,
+    _response: &Self::Response,
+    context: &Data<LemmyContext>,
+  ) -> Result<(), LemmyError> {
+    let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
+    let person = Person::read(&mut context.pool(), request.person_id).await?;
+    let site = SiteOrCommunity::Site(SiteView::read_local(&mut context.pool()).await?.site.into());
+    let expires = request.expires.map(naive_from_unix);
+
+    // if the action affects a local user, federate to other instances
+    if person.local {
+      if request.ban {
+        BlockUser::send(
+          &site,
+          &person.into(),
+          &local_user_view.person.into(),
+          request.remove_data.unwrap_or(false),
+          request.reason.clone(),
+          expires,
+          context,
+        )
+        .await
+      } else {
+        UndoBlockUser::send(
+          &site,
+          &person.into(),
+          &local_user_view.person.into(),
+          request.reason.clone(),
+          context,
+        )
+        .await
+      }
+    } else {
+      Ok(())
+    }
+  }
+}
+
+#[async_trait::async_trait]
+impl SendActivity for BanFromCommunity {
+  type Response = BanFromCommunityResponse;
+
+  async fn send_activity(
+    request: &Self,
+    _response: &Self::Response,
+    context: &Data<LemmyContext>,
+  ) -> Result<(), LemmyError> {
+    let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
+    let community: ApubCommunity = Community::read(&mut context.pool(), request.community_id)
+      .await?
+      .into();
+    let banned_person: ApubPerson = Person::read(&mut context.pool(), request.person_id)
+      .await?
+      .into();
+    let expires = request.expires.map(naive_from_unix);
+
+    if request.ban {
+      BlockUser::send(
+        &SiteOrCommunity::Community(community),
+        &banned_person,
+        &local_user_view.person.clone().into(),
+        request.remove_data.unwrap_or(false),
+        request.reason.clone(),
+        expires,
+        context,
+      )
+      .await
+    } else {
+      UndoBlockUser::send(
+        &SiteOrCommunity::Community(community),
+        &banned_person,
+        &local_user_view.person.clone().into(),
+        request.reason.clone(),
+        context,
+      )
+      .await
+    }
+  }
 }