]> Untitled Git - lemmy.git/blobdiff - crates/apub/src/activities/deletion/undo_delete.rs
Moving settings to Database. (#2492)
[lemmy.git] / crates / apub / src / activities / deletion / undo_delete.rs
index c6e5ddfc0b7e518ca5bb76b2d66b8ab7bf7aef03..f73c780c2de38670340d54a61f00fac5fe860786 100644 (file)
@@ -1,25 +1,35 @@
 use crate::{
   activities::{
-    community::{announce::GetCommunity, send_activity_in_community},
+    community::announce::GetCommunity,
     deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
     generate_activity_id,
-    verify_activity,
-    verify_is_public,
   },
-  activity_lists::AnnouncableActivities,
+  check_apub_id_valid,
+  fetch_local_site_data,
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
 };
-use activitystreams::{activity::kind::UndoType, public};
-use anyhow::anyhow;
-use lemmy_api_common::blocking;
-use lemmy_apub_lib::{
-  data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
+use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
+use activitystreams_kinds::activity::UndoType;
+use lemmy_api_common::utils::blocking;
+use lemmy_db_schema::{
+  source::{
+    comment::{Comment, CommentUpdateForm},
+    community::{Community, CommunityUpdateForm},
+    moderator::{
+      ModRemoveComment,
+      ModRemoveCommentForm,
+      ModRemoveCommunity,
+      ModRemoveCommunityForm,
+      ModRemovePost,
+      ModRemovePostForm,
+    },
+    post::{Post, PostUpdateForm},
+  },
+  traits::Crud,
 };
-use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{
   send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
   LemmyContext,
@@ -30,19 +40,28 @@ use url::Url;
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for UndoDelete {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
+
+  #[tracing::instrument(skip_all)]
   async fn verify(
     &self,
     context: &Data<LemmyContext>,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    verify_is_public(&self.to, &self.cc)?;
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
+    let local_site_data = blocking(context.pool(), fetch_local_site_data).await??;
+    check_apub_id_valid(self.id(), &local_site_data, context.settings())
+      .map_err(LemmyError::from_message)?;
     self.object.verify(context, request_counter).await?;
-    let community = self.get_community(context, request_counter).await?;
     verify_delete_activity(
-      &self.object.object,
-      &self.actor,
-      &community,
+      &self.object,
       self.object.summary.is_some(),
       context,
       request_counter,
@@ -51,16 +70,25 @@ impl ActivityHandler for UndoDelete {
     Ok(())
   }
 
+  #[tracing::instrument(skip_all)]
   async fn receive(
     self,
     context: &Data<LemmyContext>,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     if self.object.summary.is_some() {
-      UndoDelete::receive_undo_remove_action(&self.object.object, context).await
+      UndoDelete::receive_undo_remove_action(
+        &self
+          .actor
+          .dereference(context, local_instance(context), request_counter)
+          .await?,
+        self.object.object.id(),
+        context,
+      )
+      .await
     } else {
       receive_delete_action(
-        &self.object.object,
+        self.object.object.id(),
         &self.actor,
         false,
         context,
@@ -72,34 +100,36 @@ impl ActivityHandler for UndoDelete {
 }
 
 impl UndoDelete {
-  pub(in crate::activities::deletion) async fn send(
+  #[tracing::instrument(skip_all)]
+  pub(in crate::activities::deletion) fn new(
     actor: &ApubPerson,
-    community: &ApubCommunity,
-    object_id: Url,
+    object: DeletableObjects,
+    to: Url,
+    community: Option<&Community>,
     summary: Option<String>,
     context: &LemmyContext,
-  ) -> Result<(), LemmyError> {
-    let object = Delete::new(actor, community, object_id, summary, context)?;
+  ) -> Result<UndoDelete, LemmyError> {
+    let object = Delete::new(actor, object, to.clone(), community, summary, context)?;
 
     let id = generate_activity_id(
       UndoType::Undo,
       &context.settings().get_protocol_and_hostname(),
     )?;
-    let undo = UndoDelete {
-      actor: ObjectId::new(actor.actor_id()),
-      to: vec![public()],
+    let cc: Option<Url> = community.map(|c| c.actor_id.clone().into());
+    Ok(UndoDelete {
+      actor: ObjectId::new(actor.actor_id.clone()),
+      to: vec![to],
       object,
-      cc: vec![community.actor_id()],
+      cc: cc.into_iter().collect(),
       kind: UndoType::Undo,
-      id: id.clone(),
+      id,
       unparsed: Default::default(),
-    };
-
-    let activity = AnnouncableActivities::UndoDelete(undo);
-    send_activity_in_community(activity, &id, actor, community, vec![], context).await
+    })
   }
 
+  #[tracing::instrument(skip_all)]
   pub(in crate::activities) async fn receive_undo_remove_action(
+    actor: &ApubPerson,
     object: &Url,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
@@ -107,28 +137,74 @@ impl UndoDelete {
     match DeletableObjects::read_from_db(object, context).await? {
       DeletableObjects::Community(community) => {
         if community.local {
-          return Err(anyhow!("Only local admin can restore community").into());
+          return Err(LemmyError::from_message(
+            "Only local admin can restore community",
+          ));
         }
+        let form = ModRemoveCommunityForm {
+          mod_person_id: actor.id,
+          community_id: community.id,
+          removed: Some(false),
+          reason: None,
+          expires: None,
+        };
+        blocking(context.pool(), move |conn| {
+          ModRemoveCommunity::create(conn, &form)
+        })
+        .await??;
         let deleted_community = blocking(context.pool(), move |conn| {
-          Community::update_removed(conn, community.id, false)
+          Community::update(
+            conn,
+            community.id,
+            &CommunityUpdateForm::builder().removed(Some(false)).build(),
+          )
         })
         .await??;
         send_community_ws_message(deleted_community.id, EditCommunity, None, None, context).await?;
       }
       DeletableObjects::Post(post) => {
+        let form = ModRemovePostForm {
+          mod_person_id: actor.id,
+          post_id: post.id,
+          removed: Some(false),
+          reason: None,
+        };
+        blocking(context.pool(), move |conn| {
+          ModRemovePost::create(conn, &form)
+        })
+        .await??;
         let removed_post = blocking(context.pool(), move |conn| {
-          Post::update_removed(conn, post.id, false)
+          Post::update(
+            conn,
+            post.id,
+            &PostUpdateForm::builder().removed(Some(false)).build(),
+          )
         })
         .await??;
         send_post_ws_message(removed_post.id, EditPost, None, None, context).await?;
       }
       DeletableObjects::Comment(comment) => {
+        let form = ModRemoveCommentForm {
+          mod_person_id: actor.id,
+          comment_id: comment.id,
+          removed: Some(false),
+          reason: None,
+        };
+        blocking(context.pool(), move |conn| {
+          ModRemoveComment::create(conn, &form)
+        })
+        .await??;
         let removed_comment = blocking(context.pool(), move |conn| {
-          Comment::update_removed(conn, comment.id, false)
+          Comment::update(
+            conn,
+            comment.id,
+            &CommentUpdateForm::builder().removed(Some(false)).build(),
+          )
         })
         .await??;
         send_comment_ws_message_simple(removed_comment.id, EditComment, context).await?;
       }
+      DeletableObjects::PrivateMessage(_) => unimplemented!(),
     }
     Ok(())
   }
@@ -136,6 +212,7 @@ impl UndoDelete {
 
 #[async_trait::async_trait(?Send)]
 impl GetCommunity for UndoDelete {
+  #[tracing::instrument(skip_all)]
   async fn get_community(
     &self,
     context: &LemmyContext,