]> Untitled Git - lemmy.git/commitdiff
Major refactor, adding newtypes for apub crate
authorFelix Ableitner <me@nutomic.com>
Mon, 18 Oct 2021 21:36:44 +0000 (23:36 +0200)
committerFelix Ableitner <me@nutomic.com>
Wed, 20 Oct 2021 10:28:09 +0000 (12:28 +0200)
- this allows moving FromApub/ToApub traits into apub lib

69 files changed:
Cargo.lock
crates/api/src/comment.rs
crates/api/src/comment_report.rs
crates/api/src/community.rs
crates/api/src/post.rs
crates/api/src/post_report.rs
crates/api_common/src/lib.rs
crates/api_crud/src/comment/create.rs
crates/api_crud/src/comment/delete.rs
crates/api_crud/src/comment/update.rs
crates/api_crud/src/community/create.rs
crates/api_crud/src/community/delete.rs
crates/api_crud/src/community/read.rs
crates/api_crud/src/community/update.rs
crates/api_crud/src/post/create.rs
crates/api_crud/src/post/delete.rs
crates/api_crud/src/post/update.rs
crates/api_crud/src/private_message/create.rs
crates/api_crud/src/private_message/delete.rs
crates/api_crud/src/private_message/update.rs
crates/api_crud/src/user/read.rs
crates/apub/src/activities/comment/create_or_update.rs
crates/apub/src/activities/comment/mod.rs
crates/apub/src/activities/community/add_mod.rs
crates/apub/src/activities/community/announce.rs
crates/apub/src/activities/community/block_user.rs
crates/apub/src/activities/community/mod.rs
crates/apub/src/activities/community/remove_mod.rs
crates/apub/src/activities/community/undo_block_user.rs
crates/apub/src/activities/community/update.rs
crates/apub/src/activities/deletion/delete.rs
crates/apub/src/activities/deletion/mod.rs
crates/apub/src/activities/deletion/undo_delete.rs
crates/apub/src/activities/following/accept.rs
crates/apub/src/activities/following/follow.rs
crates/apub/src/activities/following/undo.rs
crates/apub/src/activities/mod.rs
crates/apub/src/activities/post/create_or_update.rs
crates/apub/src/activities/private_message/create_or_update.rs
crates/apub/src/activities/private_message/delete.rs
crates/apub/src/activities/private_message/undo_delete.rs
crates/apub/src/activities/report.rs
crates/apub/src/activities/undo_remove.rs
crates/apub/src/activities/voting/mod.rs
crates/apub/src/activities/voting/undo_vote.rs
crates/apub/src/activities/voting/vote.rs
crates/apub/src/fetcher/community.rs
crates/apub/src/fetcher/mod.rs
crates/apub/src/fetcher/object_id.rs
crates/apub/src/fetcher/post_or_comment.rs
crates/apub/src/fetcher/search.rs
crates/apub/src/http/comment.rs
crates/apub/src/http/community.rs
crates/apub/src/http/person.rs
crates/apub/src/http/post.rs
crates/apub/src/objects/comment.rs
crates/apub/src/objects/community.rs
crates/apub/src/objects/mod.rs
crates/apub/src/objects/person.rs
crates/apub/src/objects/post.rs
crates/apub/src/objects/private_message.rs
crates/apub_lib/src/traits.rs
crates/db_schema/Cargo.toml
crates/db_schema/src/impls/comment.rs
crates/db_schema/src/impls/community.rs
crates/db_schema/src/impls/person.rs
crates/db_schema/src/impls/post.rs
crates/db_schema/src/impls/private_message.rs
crates/websocket/src/send.rs

index 06361214fb601f6c00f36c404a617f63545e1513..120f6827843081239a9f54f740553b22c9f85127 100644 (file)
@@ -1839,7 +1839,6 @@ dependencies = [
  "diesel-derive-newtype",
  "diesel_migrations",
  "lazy_static",
- "lemmy_apub_lib",
  "lemmy_utils",
  "log",
  "regex",
index d626c2eaeef9986240a51ab15659a84bba8e11b9..62b01b33facbf4c7c96ac20f3af325ca9d50b062 100644 (file)
@@ -191,7 +191,7 @@ impl Perform for CreateCommentLike {
 
     // Only add the like if the score isnt 0
     let comment = orig_comment.comment;
-    let object = PostOrComment::Comment(comment);
+    let object = PostOrComment::Comment(comment.into());
     let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
     if do_add {
       let like_form2 = like_form.clone();
@@ -202,7 +202,7 @@ impl Perform for CreateCommentLike {
 
       Vote::send(
         &object,
-        &local_user_view.person,
+        &local_user_view.person.clone().into(),
         orig_comment.community.id,
         like_form.score.try_into()?,
         context,
@@ -212,7 +212,7 @@ impl Perform for CreateCommentLike {
       // API doesn't distinguish between Undo/Like and Undo/Dislike
       UndoVote::send(
         &object,
-        &local_user_view.person,
+        &local_user_view.person.clone().into(),
         orig_comment.community.id,
         VoteType::Like,
         context,
index 86f636a6b50ee4d25eaeda321763b803d472794f..a7299b7ae508009d79495b78351b845d3f0d9d21 100644 (file)
@@ -79,8 +79,8 @@ impl Perform for CreateCommentReport {
 
     Report::send(
       ObjectId::new(comment_view.comment.ap_id),
-      &local_user_view.person,
-      comment_view.community.id,
+      &local_user_view.person.into(),
+      ObjectId::new(comment_view.community.actor_id),
       reason.to_string(),
       context,
     )
index 5d7317b2a0af8565dc5ec65b856fac298ddd1c28..ac39751c86320a977a5d3668a410d64f5e5ec722 100644 (file)
@@ -9,14 +9,17 @@ use lemmy_api_common::{
   get_local_user_view_from_jwt,
   is_mod_or_admin,
 };
-use lemmy_apub::activities::{
-  community::{
-    add_mod::AddMod,
-    block_user::BlockUserFromCommunity,
-    remove_mod::RemoveMod,
-    undo_block_user::UndoBlockUserFromCommunity,
+use lemmy_apub::{
+  activities::{
+    community::{
+      add_mod::AddMod,
+      block_user::BlockUserFromCommunity,
+      remove_mod::RemoveMod,
+      undo_block_user::UndoBlockUserFromCommunity,
+    },
+    following::{follow::FollowCommunity as FollowCommunityApub, undo::UndoFollowCommunity},
   },
-  following::{follow::FollowCommunity as FollowCommunityApub, undo::UndoFollowCommunity},
+  objects::{community::ApubCommunity, person::ApubPerson},
 };
 use lemmy_db_schema::{
   source::{
@@ -68,10 +71,11 @@ impl Perform for FollowCommunity {
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
     let community_id = data.community_id;
-    let community = blocking(context.pool(), move |conn| {
+    let community: ApubCommunity = blocking(context.pool(), move |conn| {
       Community::read(conn, community_id)
     })
-    .await??;
+    .await??
+    .into();
     let community_follower_form = CommunityFollowerForm {
       community_id: data.community_id,
       person_id: local_user_view.person.id,
@@ -97,9 +101,11 @@ impl Perform for FollowCommunity {
     } else if data.follow {
       // Dont actually add to the community followers here, because you need
       // to wait for the accept
-      FollowCommunityApub::send(&local_user_view.person, &community, context).await?;
+      FollowCommunityApub::send(&local_user_view.person.clone().into(), &community, context)
+        .await?;
     } else {
-      UndoFollowCommunity::send(&local_user_view.person, &community, context).await?;
+      UndoFollowCommunity::send(&local_user_view.person.clone().into(), &community, context)
+        .await?;
       let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
       blocking(context.pool(), unfollow)
         .await?
@@ -165,7 +171,7 @@ impl Perform for BlockCommunity {
         Community::read(conn, community_id)
       })
       .await??;
-      UndoFollowCommunity::send(&local_user_view.person, &community, context).await?;
+      UndoFollowCommunity::send(&local_user_view.person.into(), &community.into(), context).await?;
     } else {
       let unblock = move |conn: &'_ _| CommunityBlock::unblock(conn, &community_block_form);
       blocking(context.pool(), unblock)
@@ -209,14 +215,16 @@ impl Perform for BanFromCommunity {
       person_id: data.person_id,
     };
 
-    let community = blocking(context.pool(), move |conn: &'_ _| {
+    let community: ApubCommunity = blocking(context.pool(), move |conn: &'_ _| {
       Community::read(conn, community_id)
     })
-    .await??;
-    let banned_person = blocking(context.pool(), move |conn: &'_ _| {
+    .await??
+    .into();
+    let banned_person: ApubPerson = blocking(context.pool(), move |conn: &'_ _| {
       Person::read(conn, banned_person_id)
     })
-    .await??;
+    .await??
+    .into();
 
     if data.ban {
       let ban = move |conn: &'_ _| CommunityPersonBan::ban(conn, &community_user_ban_form);
@@ -236,8 +244,13 @@ impl Perform for BanFromCommunity {
       .await?
       .ok();
 
-      BlockUserFromCommunity::send(&community, &banned_person, &local_user_view.person, context)
-        .await?;
+      BlockUserFromCommunity::send(
+        &community,
+        &banned_person,
+        &local_user_view.person.clone().into(),
+        context,
+      )
+      .await?;
     } else {
       let unban = move |conn: &'_ _| CommunityPersonBan::unban(conn, &community_user_ban_form);
       blocking(context.pool(), unban)
@@ -246,7 +259,7 @@ impl Perform for BanFromCommunity {
       UndoBlockUserFromCommunity::send(
         &community,
         &banned_person,
-        &local_user_view.person,
+        &local_user_view.person.clone().into(),
         context,
       )
       .await?;
@@ -368,18 +381,32 @@ impl Perform for AddModToCommunity {
 
     // Send to federated instances
     let updated_mod_id = data.person_id;
-    let updated_mod = blocking(context.pool(), move |conn| {
+    let updated_mod: ApubPerson = blocking(context.pool(), move |conn| {
       Person::read(conn, updated_mod_id)
     })
-    .await??;
-    let community = blocking(context.pool(), move |conn| {
+    .await??
+    .into();
+    let community: ApubCommunity = blocking(context.pool(), move |conn| {
       Community::read(conn, community_id)
     })
-    .await??;
+    .await??
+    .into();
     if data.added {
-      AddMod::send(&community, &updated_mod, &local_user_view.person, context).await?;
+      AddMod::send(
+        &community,
+        &updated_mod,
+        &local_user_view.person.into(),
+        context,
+      )
+      .await?;
     } else {
-      RemoveMod::send(&community, &updated_mod, &local_user_view.person, context).await?;
+      RemoveMod::send(
+        &community,
+        &updated_mod,
+        &local_user_view.person.into(),
+        context,
+      )
+      .await?;
     }
 
     // Note: in case a remote mod is added, this returns the old moderators list, it will only get
index 60cdafb9a2c63f4fefb7dc03c8ec93c07b7cacf8..488c8f590aef4c52ab38c5a070ca49be39dffe95 100644 (file)
@@ -21,6 +21,7 @@ use lemmy_apub::{
     CreateOrUpdateType,
   },
   fetcher::post_or_comment::PostOrComment,
+  objects::post::ApubPost,
 };
 use lemmy_db_schema::{
   source::{moderator::*, post::*},
@@ -49,7 +50,9 @@ impl Perform for CreatePostLike {
 
     // Check for a community ban
     let post_id = data.post_id;
-    let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+    let post: ApubPost = blocking(context.pool(), move |conn| Post::read(conn, post_id))
+      .await??
+      .into();
 
     check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;
     check_community_deleted_or_removed(post.community_id, context.pool()).await?;
@@ -83,7 +86,7 @@ impl Perform for CreatePostLike {
 
       Vote::send(
         &object,
-        &local_user_view.person,
+        &local_user_view.person.clone().into(),
         community_id,
         like_form.score.try_into()?,
         context,
@@ -93,7 +96,7 @@ impl Perform for CreatePostLike {
       // API doesn't distinguish between Undo/Like and Undo/Dislike
       UndoVote::send(
         &object,
-        &local_user_view.person,
+        &local_user_view.person.clone().into(),
         community_id,
         VoteType::Like,
         context,
@@ -150,10 +153,11 @@ impl Perform for LockPost {
     // Update the post
     let post_id = data.post_id;
     let locked = data.locked;
-    let updated_post = blocking(context.pool(), move |conn| {
+    let updated_post: ApubPost = blocking(context.pool(), move |conn| {
       Post::update_locked(conn, post_id, locked)
     })
-    .await??;
+    .await??
+    .into();
 
     // Mod tables
     let form = ModLockPostForm {
@@ -166,7 +170,7 @@ impl Perform for LockPost {
     // apub updates
     CreateOrUpdatePost::send(
       &updated_post,
-      &local_user_view.person,
+      &local_user_view.person.clone().into(),
       CreateOrUpdateType::Update,
       context,
     )
@@ -218,10 +222,11 @@ impl Perform for StickyPost {
     // Update the post
     let post_id = data.post_id;
     let stickied = data.stickied;
-    let updated_post = blocking(context.pool(), move |conn| {
+    let updated_post: ApubPost = blocking(context.pool(), move |conn| {
       Post::update_stickied(conn, post_id, stickied)
     })
-    .await??;
+    .await??
+    .into();
 
     // Mod tables
     let form = ModStickyPostForm {
@@ -238,7 +243,7 @@ impl Perform for StickyPost {
     // TODO stickied should pry work like locked for ease of use
     CreateOrUpdatePost::send(
       &updated_post,
-      &local_user_view.person,
+      &local_user_view.person.clone().into(),
       CreateOrUpdateType::Update,
       context,
     )
index 35a734d441a820c42c4679e68d0a2658f504a4aa..3e610bff8f14800b3cdeab017fa3a8976534d21d 100644 (file)
@@ -88,8 +88,8 @@ impl Perform for CreatePostReport {
 
     Report::send(
       ObjectId::new(post_view.post.ap_id),
-      &local_user_view.person,
-      post_view.community.id,
+      &local_user_view.person.into(),
+      ObjectId::new(post_view.community.actor_id),
       reason.to_string(),
       context,
     )
index f28c34b017816c5a7f9b798d21a086ca6237e4a8..bf6246a0dc087f67307bba8d410b773265e27487 100644 (file)
@@ -6,15 +6,11 @@ pub mod site;
 pub mod websocket;
 
 use crate::site::FederatedInstances;
-use diesel::PgConnection;
 use lemmy_db_schema::{
   newtypes::{CommunityId, LocalUserId, PersonId, PostId},
   source::{
-    comment::Comment,
     community::Community,
-    person::Person,
     person_block::PersonBlock,
-    person_mention::{PersonMention, PersonMentionForm},
     post::{Post, PostRead, PostReadForm},
     secret::Secret,
     site::Site,
@@ -27,15 +23,7 @@ use lemmy_db_views_actor::{
   community_person_ban_view::CommunityPersonBanView,
   community_view::CommunityView,
 };
-use lemmy_utils::{
-  claims::Claims,
-  email::send_email,
-  settings::structs::{FederationConfig, Settings},
-  utils::MentionData,
-  ApiError,
-  LemmyError,
-};
-use log::error;
+use lemmy_utils::{claims::Claims, settings::structs::FederationConfig, ApiError, LemmyError};
 use url::Url;
 
 pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
@@ -54,160 +42,6 @@ where
   res
 }
 
-pub async fn send_local_notifs(
-  mentions: Vec<MentionData>,
-  comment: Comment,
-  person: Person,
-  post: Post,
-  pool: &DbPool,
-  do_send_email: bool,
-  settings: &Settings,
-) -> Result<Vec<LocalUserId>, LemmyError> {
-  let settings = settings.to_owned();
-  let ids = blocking(pool, move |conn| {
-    do_send_local_notifs(
-      conn,
-      &mentions,
-      &comment,
-      &person,
-      &post,
-      do_send_email,
-      &settings,
-    )
-  })
-  .await?;
-
-  Ok(ids)
-}
-
-fn do_send_local_notifs(
-  conn: &PgConnection,
-  mentions: &[MentionData],
-  comment: &Comment,
-  person: &Person,
-  post: &Post,
-  do_send_email: bool,
-  settings: &Settings,
-) -> Vec<LocalUserId> {
-  let mut recipient_ids = Vec::new();
-
-  // Send the local mentions
-  for mention in mentions
-    .iter()
-    .filter(|m| m.is_local(&settings.hostname) && m.name.ne(&person.name))
-    .collect::<Vec<&MentionData>>()
-  {
-    if let Ok(mention_user_view) = LocalUserView::read_from_name(conn, &mention.name) {
-      // TODO
-      // At some point, make it so you can't tag the parent creator either
-      // This can cause two notifications, one for reply and the other for mention
-      recipient_ids.push(mention_user_view.local_user.id);
-
-      let user_mention_form = PersonMentionForm {
-        recipient_id: mention_user_view.person.id,
-        comment_id: comment.id,
-        read: None,
-      };
-
-      // Allow this to fail softly, since comment edits might re-update or replace it
-      // Let the uniqueness handle this fail
-      PersonMention::create(conn, &user_mention_form).ok();
-
-      // Send an email to those local users that have notifications on
-      if do_send_email {
-        send_email_to_user(
-          &mention_user_view,
-          "Mentioned by",
-          "Person Mention",
-          &comment.content,
-          settings,
-        )
-      }
-    }
-  }
-
-  // Send notifs to the parent commenter / poster
-  match comment.parent_id {
-    Some(parent_id) => {
-      if let Ok(parent_comment) = Comment::read(conn, parent_id) {
-        // Don't send a notif to yourself
-        if parent_comment.creator_id != person.id {
-          // Get the parent commenter local_user
-          if let Ok(parent_user_view) = LocalUserView::read_person(conn, parent_comment.creator_id)
-          {
-            recipient_ids.push(parent_user_view.local_user.id);
-
-            if do_send_email {
-              send_email_to_user(
-                &parent_user_view,
-                "Reply from",
-                "Comment Reply",
-                &comment.content,
-                settings,
-              )
-            }
-          }
-        }
-      }
-    }
-    // Its a post
-    None => {
-      if post.creator_id != person.id {
-        if let Ok(parent_user_view) = LocalUserView::read_person(conn, post.creator_id) {
-          recipient_ids.push(parent_user_view.local_user.id);
-
-          if do_send_email {
-            send_email_to_user(
-              &parent_user_view,
-              "Reply from",
-              "Post Reply",
-              &comment.content,
-              settings,
-            )
-          }
-        }
-      }
-    }
-  };
-  recipient_ids
-}
-
-pub fn send_email_to_user(
-  local_user_view: &LocalUserView,
-  subject_text: &str,
-  body_text: &str,
-  comment_content: &str,
-  settings: &Settings,
-) {
-  if local_user_view.person.banned || !local_user_view.local_user.send_notifications_to_email {
-    return;
-  }
-
-  if let Some(user_email) = &local_user_view.local_user.email {
-    let subject = &format!(
-      "{} - {} {}",
-      subject_text, settings.hostname, local_user_view.person.name,
-    );
-    let html = &format!(
-      "<h1>{}</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
-      body_text,
-      local_user_view.person.name,
-      comment_content,
-      settings.get_protocol_and_hostname()
-    );
-    match send_email(
-      subject,
-      user_email,
-      &local_user_view.person.name,
-      html,
-      settings,
-    ) {
-      Ok(_o) => _o,
-      Err(e) => error!("{}", e),
-    };
-  }
-}
-
 pub async fn is_mod_or_admin(
   pool: &DbPool,
   person_id: PersonId,
index ff2442b15e20f73dec077afdd7e593adc046f873..690a50820438425b2ff5e1837fdb290b8b1746eb 100644 (file)
@@ -9,7 +9,6 @@ use lemmy_api_common::{
   comment::*,
   get_local_user_view_from_jwt,
   get_post,
-  send_local_notifs,
 };
 use lemmy_apub::{
   activities::{
@@ -35,7 +34,11 @@ use lemmy_utils::{
   ConnectionId,
   LemmyError,
 };
-use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
+use lemmy_websocket::{
+  send::{send_comment_ws_message, send_local_notifs},
+  LemmyContext,
+  UserOperationCrud,
+};
 
 #[async_trait::async_trait(?Send)]
 impl PerformCrud for CreateComment {
@@ -117,8 +120,8 @@ impl PerformCrud for CreateComment {
       .map_err(|e| ApiError::err("couldnt_create_comment", e))?;
 
     CreateOrUpdateComment::send(
-      &updated_comment,
-      &local_user_view.person,
+      &updated_comment.clone().into(),
+      &local_user_view.person.clone().into(),
       CreateOrUpdateType::Create,
       context,
     )
@@ -129,12 +132,11 @@ impl PerformCrud for CreateComment {
     let mentions = scrape_text_for_mentions(&comment_form.content);
     let recipient_ids = send_local_notifs(
       mentions,
-      updated_comment.clone(),
-      local_user_view.person.clone(),
-      post,
-      context.pool(),
+      &updated_comment,
+      &local_user_view.person,
+      &post,
       true,
-      &context.settings(),
+      context,
     )
     .await?;
 
@@ -151,10 +153,10 @@ impl PerformCrud for CreateComment {
       .await?
       .map_err(|e| ApiError::err("couldnt_like_comment", e))?;
 
-    let object = PostOrComment::Comment(updated_comment);
+    let object = PostOrComment::Comment(updated_comment.into());
     Vote::send(
       &object,
-      &local_user_view.person,
+      &local_user_view.person.clone().into(),
       community_id,
       VoteType::Like,
       context,
index 07c920f7cd197e06ae4f5dc2a009a6829de61741..19851f0c0556a093f1d50ab0739182301fca244c 100644 (file)
@@ -6,7 +6,6 @@ use lemmy_api_common::{
   comment::*,
   get_local_user_view_from_jwt,
   is_mod_or_admin,
-  send_local_notifs,
 };
 use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
 use lemmy_db_schema::{
@@ -20,7 +19,11 @@ use lemmy_db_schema::{
 };
 use lemmy_db_views::comment_view::CommentView;
 use lemmy_utils::{ApiError, ConnectionId, LemmyError};
-use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
+use lemmy_websocket::{
+  send::{send_comment_ws_message, send_local_notifs},
+  LemmyContext,
+  UserOperationCrud,
+};
 
 #[async_trait::async_trait(?Send)]
 impl PerformCrud for DeleteComment {
@@ -67,8 +70,8 @@ impl PerformCrud for DeleteComment {
     })
     .await??;
     send_apub_delete(
-      &local_user_view.person,
-      &community,
+      &local_user_view.person.clone().into(),
+      &community.clone().into(),
       updated_comment.ap_id.clone().into(),
       deleted,
       context,
@@ -79,12 +82,11 @@ impl PerformCrud for DeleteComment {
     let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
     let recipient_ids = send_local_notifs(
       vec![],
-      updated_comment,
-      local_user_view.person.clone(),
-      post,
-      context.pool(),
+      &updated_comment,
+      &local_user_view.person,
+      &post,
       false,
-      &context.settings(),
+      context,
     )
     .await?;
 
@@ -161,8 +163,8 @@ impl PerformCrud for RemoveComment {
     })
     .await??;
     send_apub_remove(
-      &local_user_view.person,
-      &community,
+      &local_user_view.person.clone().into(),
+      &community.into(),
       updated_comment.ap_id.clone().into(),
       data.reason.clone().unwrap_or_else(|| "".to_string()),
       removed,
@@ -174,12 +176,11 @@ impl PerformCrud for RemoveComment {
     let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
     let recipient_ids = send_local_notifs(
       vec![],
-      updated_comment,
-      local_user_view.person.clone(),
-      post,
-      context.pool(),
+      &updated_comment,
+      &local_user_view.person.clone(),
+      &post,
       false,
-      &context.settings(),
+      context,
     )
     .await?;
 
index 7d45b9403389dcb773c07789917af9c09ca4625e..9a164fc3fef1d3508e6719d8f965b57612888981 100644 (file)
@@ -7,7 +7,6 @@ use lemmy_api_common::{
   check_post_deleted_or_removed,
   comment::*,
   get_local_user_view_from_jwt,
-  send_local_notifs,
 };
 use lemmy_apub::activities::{
   comment::create_or_update::CreateOrUpdateComment,
@@ -21,7 +20,11 @@ use lemmy_utils::{
   ConnectionId,
   LemmyError,
 };
-use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
+use lemmy_websocket::{
+  send::{send_comment_ws_message, send_local_notifs},
+  LemmyContext,
+  UserOperationCrud,
+};
 
 #[async_trait::async_trait(?Send)]
 impl PerformCrud for EditComment {
@@ -69,8 +72,8 @@ impl PerformCrud for EditComment {
 
     // Send the apub update
     CreateOrUpdateComment::send(
-      &updated_comment,
-      &local_user_view.person,
+      &updated_comment.clone().into(),
+      &local_user_view.person.clone().into(),
       CreateOrUpdateType::Update,
       context,
     )
@@ -81,12 +84,11 @@ impl PerformCrud for EditComment {
     let mentions = scrape_text_for_mentions(&updated_comment_content);
     let recipient_ids = send_local_notifs(
       mentions,
-      updated_comment,
-      local_user_view.person.clone(),
-      orig_comment.post,
-      context.pool(),
+      &updated_comment,
+      &local_user_view.person,
+      &orig_comment.post,
       false,
-      &context.settings(),
+      context,
     )
     .await?;
 
index cc0e62db4c47b9bf982d899f91fa5c6bcaa855d9..8b7daeb7b7ac834e0828fa889a70db3fd4277bac 100644 (file)
@@ -12,6 +12,7 @@ use lemmy_apub::{
   generate_followers_url,
   generate_inbox_url,
   generate_shared_inbox_url,
+  objects::community::ApubCommunity,
   EndpointType,
 };
 use lemmy_db_schema::{
@@ -71,7 +72,7 @@ impl PerformCrud for CreateCommunity {
       &data.name,
       &context.settings().get_protocol_and_hostname(),
     )?;
-    let community_actor_id_wrapped = ObjectId::<Community>::new(community_actor_id.clone());
+    let community_actor_id_wrapped = ObjectId::<ApubCommunity>::new(community_actor_id.clone());
     let community_dupe = community_actor_id_wrapped.dereference_local(context).await;
     if community_dupe.is_ok() {
       return Err(ApiError::err_plain("community_already_exists").into());
index 5f9fbb44e9d3f5b303149cff7dc2404f48cceb76..bf59e786f721969ca770dcf1b128a939cbf276f7 100644 (file)
@@ -49,8 +49,8 @@ impl PerformCrud for DeleteCommunity {
 
     // Send apub messages
     send_apub_delete(
-      &local_user_view.person,
-      &updated_community,
+      &local_user_view.person.clone().into(),
+      &updated_community.clone().into(),
       updated_community.actor_id.clone().into(),
       deleted,
       context,
@@ -109,8 +109,8 @@ impl PerformCrud for RemoveCommunity {
 
     // Apub messages
     send_apub_remove(
-      &local_user_view.person,
-      &updated_community,
+      &local_user_view.person.clone().into(),
+      &updated_community.clone().into(),
       updated_community.actor_id.clone().into(),
       data.reason.clone().unwrap_or_else(|| "".to_string()),
       removed,
index 3b9405aff55b09e829443833f629af6549a8fd33..d18ef99f6616329edef22a7192d8939492a95964 100644 (file)
@@ -1,10 +1,14 @@
 use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt_opt};
-use lemmy_apub::{build_actor_id_from_shortname, fetcher::object_id::ObjectId, EndpointType};
+use lemmy_apub::{
+  build_actor_id_from_shortname,
+  fetcher::object_id::ObjectId,
+  objects::community::ApubCommunity,
+  EndpointType,
+};
 use lemmy_db_schema::{
   from_opt_str_to_opt_enum,
-  source::community::Community,
   traits::DeleteableOrRemoveable,
   ListingType,
   SortType,
@@ -37,7 +41,7 @@ impl PerformCrud for GetCommunity {
         let community_actor_id =
           build_actor_id_from_shortname(EndpointType::Community, &name, &context.settings())?;
 
-        ObjectId::<Community>::new(community_actor_id)
+        ObjectId::<ApubCommunity>::new(community_actor_id)
           .dereference(context, &mut 0)
           .await
           .map_err(|e| ApiError::err("couldnt_find_community", e))?
index f269807b528523d76889072db06a4d5cfb41c0ff..97722a98b0c24b05d6ef70bd5a9327bde0eb024b 100644 (file)
@@ -71,7 +71,12 @@ impl PerformCrud for EditCommunity {
     .await?
     .map_err(|e| ApiError::err("couldnt_update_community", e))?;
 
-    UpdateCommunity::send(&updated_community, &local_user_view.person, context).await?;
+    UpdateCommunity::send(
+      &updated_community.into(),
+      &local_user_view.person.into(),
+      context,
+    )
+    .await?;
 
     let op = UserOperationCrud::EditCommunity;
     send_community_ws_message(data.community_id, op, websocket_id, None, context).await
index e75999e59517999c05e53ffb51a4c280b13767c6..3e5fb41e1ff5a2ddb5679b862dd80488fb839450 100644 (file)
@@ -109,8 +109,8 @@ impl PerformCrud for CreatePost {
     .map_err(|e| ApiError::err("couldnt_create_post", e))?;
 
     CreateOrUpdatePost::send(
-      &updated_post,
-      &local_user_view.person,
+      &updated_post.clone().into(),
+      &local_user_view.person.clone().into(),
       CreateOrUpdateType::Create,
       context,
     )
@@ -146,10 +146,10 @@ impl PerformCrud for CreatePost {
       }
     }
 
-    let object = PostOrComment::Post(Box::new(updated_post));
+    let object = PostOrComment::Post(Box::new(updated_post.into()));
     Vote::send(
       &object,
-      &local_user_view.person,
+      &local_user_view.person.clone().into(),
       inserted_post.community_id,
       VoteType::Like,
       context,
index 1a9044c37adef4d211ea565ed5acee519c6bab0d..a701e835560e86b2061e34a9e8331fdd718d1f90 100644 (file)
@@ -63,8 +63,8 @@ impl PerformCrud for DeletePost {
     })
     .await??;
     send_apub_delete(
-      &local_user_view.person,
-      &community,
+      &local_user_view.person.clone().into(),
+      &community.into(),
       updated_post.ap_id.into(),
       deleted,
       context,
@@ -139,8 +139,8 @@ impl PerformCrud for RemovePost {
     })
     .await??;
     send_apub_remove(
-      &local_user_view.person,
-      &community,
+      &local_user_view.person.clone().into(),
+      &community.into(),
       updated_post.ap_id.into(),
       data.reason.clone().unwrap_or_else(|| "".to_string()),
       removed,
index 8c346b882e131c03dc540d8c166c06f60a20c7a7..96e4400a5a2e1c9ccc9a2256aee765058a03b10d 100644 (file)
@@ -104,8 +104,8 @@ impl PerformCrud for EditPost {
 
     // Send apub update
     CreateOrUpdatePost::send(
-      &updated_post,
-      &local_user_view.person,
+      &updated_post.into(),
+      &local_user_view.person.clone().into(),
       CreateOrUpdateType::Update,
       context,
     )
index 9e3351252062ecc365ea181cde72b48cae5e95f9..d6560be257ca033d7e29245b1e554131acf093dd 100644 (file)
@@ -5,7 +5,6 @@ use lemmy_api_common::{
   check_person_block,
   get_local_user_view_from_jwt,
   person::{CreatePrivateMessage, PrivateMessageResponse},
-  send_email_to_user,
 };
 use lemmy_apub::{
   activities::{
@@ -21,7 +20,11 @@ use lemmy_db_schema::{
 };
 use lemmy_db_views::local_user_view::LocalUserView;
 use lemmy_utils::{utils::remove_slurs, ApiError, ConnectionId, LemmyError};
-use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
+use lemmy_websocket::{
+  send::{send_email_to_user, send_pm_ws_message},
+  LemmyContext,
+  UserOperationCrud,
+};
 
 #[async_trait::async_trait(?Send)]
 impl PerformCrud for CreatePrivateMessage {
@@ -80,8 +83,8 @@ impl PerformCrud for CreatePrivateMessage {
     .map_err(|e| ApiError::err("couldnt_create_private_message", e))?;
 
     CreateOrUpdatePrivateMessage::send(
-      &updated_private_message,
-      &local_user_view.person,
+      &updated_private_message.into(),
+      &local_user_view.person.into(),
       CreateOrUpdateType::Create,
       context,
     )
index 0c61a09b0635726a6fefb634a6d31db4cf148825..f369f82b1aa7776324c37a5ad66ec21e018fdbd9 100644 (file)
@@ -51,14 +51,20 @@ impl PerformCrud for DeletePrivateMessage {
     // Send the apub update
     if data.deleted {
       DeletePrivateMessageApub::send(
-        &local_user_view.person,
-        &updated_private_message.blank_out_deleted_or_removed_info(),
+        &local_user_view.person.into(),
+        &updated_private_message
+          .blank_out_deleted_or_removed_info()
+          .into(),
         context,
       )
       .await?;
     } else {
-      UndoDeletePrivateMessage::send(&local_user_view.person, &updated_private_message, context)
-        .await?;
+      UndoDeletePrivateMessage::send(
+        &local_user_view.person.into(),
+        &updated_private_message.into(),
+        context,
+      )
+      .await?;
     }
 
     let op = UserOperationCrud::DeletePrivateMessage;
index 026a047e22b2fc2f330a92ba4fcbd5481d18b173..d72e3b13772bd6734843aa502c8974856cceb61e 100644 (file)
@@ -47,8 +47,8 @@ impl PerformCrud for EditPrivateMessage {
 
     // Send the apub update
     CreateOrUpdatePrivateMessage::send(
-      &updated_private_message,
-      &local_user_view.person,
+      &updated_private_message.into(),
+      &local_user_view.person.into(),
       CreateOrUpdateType::Update,
       context,
     )
index 4eb6771ee55cfc4b4bc974f82ba7f1a8f53e91db..a5b69ba45653893fc61ba08500bbad68e38759de 100644 (file)
@@ -1,8 +1,13 @@
 use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, person::*};
-use lemmy_apub::{build_actor_id_from_shortname, fetcher::object_id::ObjectId, EndpointType};
-use lemmy_db_schema::{from_opt_str_to_opt_enum, source::person::Person, SortType};
+use lemmy_apub::{
+  build_actor_id_from_shortname,
+  fetcher::object_id::ObjectId,
+  objects::person::ApubPerson,
+  EndpointType,
+};
+use lemmy_db_schema::{from_opt_str_to_opt_enum, SortType};
 use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder};
 use lemmy_db_views_actor::{
   community_moderator_view::CommunityModeratorView,
@@ -44,7 +49,7 @@ impl PerformCrud for GetPersonDetails {
         let actor_id =
           build_actor_id_from_shortname(EndpointType::Person, &name, &context.settings())?;
 
-        let person = ObjectId::<Person>::new(actor_id)
+        let person = ObjectId::<ApubPerson>::new(actor_id)
           .dereference(context, &mut 0)
           .await;
         person
index c9b111837692f7395a9a4caf0e0492b2610cb530..c4591c7c84b3b5e8818817a426e1ef64ad8c87fb 100644 (file)
@@ -11,18 +11,22 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
-  objects::{comment::Note, FromApub, ToApub},
+  objects::{
+    comment::{ApubComment, Note},
+    community::ApubCommunity,
+    person::ApubPerson,
+  },
 };
 use activitystreams::{base::AnyBase, link::Mention, primitives::OneOrMany, unparsed::Unparsed};
 use lemmy_api_common::{blocking, check_post_deleted_or_removed};
 use lemmy_apub_lib::{
   data::Data,
-  traits::{ActivityFields, ActivityHandler, ActorType},
+  traits::{ActivityFields, ActivityHandler, ActorType, FromApub, ToApub},
   values::PublicUrl,
   verify::verify_domains_match,
 };
 use lemmy_db_schema::{
-  source::{comment::Comment, community::Community, person::Person, post::Post},
+  source::{community::Community, post::Post},
   traits::Crud,
 };
 use lemmy_utils::LemmyError;
@@ -33,7 +37,7 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct CreateOrUpdateComment {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
   object: Note,
   cc: Vec<Url>,
@@ -49,8 +53,8 @@ pub struct CreateOrUpdateComment {
 
 impl CreateOrUpdateComment {
   pub async fn send(
-    comment: &Comment,
-    actor: &Person,
+    comment: &ApubComment,
+    actor: &ApubPerson,
     kind: CreateOrUpdateType,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
@@ -58,10 +62,11 @@ impl CreateOrUpdateComment {
     let post_id = comment.post_id;
     let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
     let community_id = post.community_id;
-    let community = blocking(context.pool(), move |conn| {
+    let community: ApubCommunity = blocking(context.pool(), move |conn| {
       Community::read(conn, community_id)
     })
-    .await??;
+    .await??
+    .into();
 
     let id = generate_activity_id(
       kind.clone(),
@@ -117,7 +122,7 @@ impl ActivityHandler for CreateOrUpdateComment {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     let comment =
-      Comment::from_apub(&self.object, context, self.actor.inner(), request_counter).await?;
+      ApubComment::from_apub(&self.object, context, self.actor.inner(), request_counter).await?;
     let recipients = get_notif_recipients(&self.actor, &comment, context, request_counter).await?;
     let notif_type = match self.kind {
       CreateOrUpdateType::Create => UserOperationCrud::CreateComment,
index 1ac320cb9915f4f1f7207c8c3d4b30a9dfe6a4db..9eb2bb447b38d9588d1fb571cedfae7e58f1a078 100644 (file)
@@ -1,15 +1,18 @@
-use crate::fetcher::object_id::ObjectId;
+use crate::{
+  fetcher::object_id::ObjectId,
+  objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson},
+};
 use activitystreams::{
   base::BaseExt,
   link::{LinkExt, Mention},
 };
 use anyhow::anyhow;
 use itertools::Itertools;
-use lemmy_api_common::{blocking, send_local_notifs};
+use lemmy_api_common::blocking;
 use lemmy_apub_lib::{traits::ActorType, webfinger::WebfingerResponse};
 use lemmy_db_schema::{
   newtypes::LocalUserId,
-  source::{comment::Comment, community::Community, person::Person, post::Post},
+  source::{comment::Comment, person::Person, post::Post},
   traits::Crud,
   DbPool,
 };
@@ -18,14 +21,14 @@ use lemmy_utils::{
   utils::{scrape_text_for_mentions, MentionData},
   LemmyError,
 };
-use lemmy_websocket::LemmyContext;
+use lemmy_websocket::{send::send_local_notifs, LemmyContext};
 use log::debug;
 use url::Url;
 
 pub mod create_or_update;
 
 async fn get_notif_recipients(
-  actor: &ObjectId<Person>,
+  actor: &ObjectId<ApubPerson>,
   comment: &Comment,
   context: &LemmyContext,
   request_counter: &mut i32,
@@ -40,16 +43,7 @@ async fn get_notif_recipients(
   // anyway.
   // TODO: for compatibility with other projects, it would be much better to read this from cc or tags
   let mentions = scrape_text_for_mentions(&comment.content);
-  send_local_notifs(
-    mentions,
-    comment.clone(),
-    actor,
-    post,
-    context.pool(),
-    true,
-    &context.settings(),
-  )
-  .await
+  send_local_notifs(mentions, comment, &*actor, &post, true, context).await
 }
 
 pub struct MentionsAndAddresses {
@@ -62,12 +56,12 @@ pub struct MentionsAndAddresses {
 /// and mention tags, so they know where to be sent to.
 /// Addresses are the persons / addresses that go in the cc field.
 pub async fn collect_non_local_mentions(
-  comment: &Comment,
-  community: &Community,
+  comment: &ApubComment,
+  community: &ApubCommunity,
   context: &LemmyContext,
 ) -> Result<MentionsAndAddresses, LemmyError> {
   let parent_creator = get_comment_parent_creator(context.pool(), comment).await?;
-  let mut addressed_ccs = vec![community.actor_id(), parent_creator.actor_id()];
+  let mut addressed_ccs: Vec<Url> = vec![community.actor_id(), parent_creator.actor_id()];
   // Note: dont include community inbox here, as we send to it separately with `send_to_community()`
   let mut inboxes = vec![parent_creator.shared_inbox_or_inbox_url()];
 
@@ -84,9 +78,9 @@ pub async fn collect_non_local_mentions(
   for mention in &mentions {
     // TODO should it be fetching it every time?
     if let Ok(actor_id) = fetch_webfinger_url(mention, context).await {
-      let actor_id: ObjectId<Person> = ObjectId::new(actor_id);
+      let actor_id: ObjectId<ApubPerson> = ObjectId::new(actor_id);
       debug!("mention actor_id: {}", actor_id);
-      addressed_ccs.push(actor_id.to_owned().to_string().parse()?);
+      addressed_ccs.push(actor_id.to_string().parse()?);
 
       let mention_person = actor_id.dereference(context, &mut 0).await?;
       inboxes.push(mention_person.shared_inbox_or_inbox_url());
@@ -113,7 +107,7 @@ pub async fn collect_non_local_mentions(
 async fn get_comment_parent_creator(
   pool: &DbPool,
   comment: &Comment,
-) -> Result<Person, LemmyError> {
+) -> Result<ApubPerson, LemmyError> {
   let parent_creator_id = if let Some(parent_comment_id) = comment.parent_id {
     let parent_comment =
       blocking(pool, move |conn| Comment::read(conn, parent_comment_id)).await??;
@@ -123,7 +117,11 @@ async fn get_comment_parent_creator(
     let parent_post = blocking(pool, move |conn| Post::read(conn, parent_post_id)).await??;
     parent_post.creator_id
   };
-  Ok(blocking(pool, move |conn| Person::read(conn, parent_creator_id)).await??)
+  Ok(
+    blocking(pool, move |conn| Person::read(conn, parent_creator_id))
+      .await??
+      .into(),
+  )
 }
 
 /// Turns a person id like `@name@example.com` into an apub ID, like `https://example.com/user/name`,
index 149b92cd212ed812606f9fe76fec27bfdf32b67e..e1cf03e0d0238be91c6fdc0c1d5f9bf1594db9da 100644 (file)
@@ -10,6 +10,7 @@ use crate::{
   context::lemmy_context,
   fetcher::object_id::ObjectId,
   generate_moderators_url,
+  objects::{community::ApubCommunity, person::ApubPerson},
 };
 use activitystreams::{
   activity::kind::AddType,
@@ -24,10 +25,7 @@ use lemmy_apub_lib::{
   values::PublicUrl,
 };
 use lemmy_db_schema::{
-  source::{
-    community::{Community, CommunityModerator, CommunityModeratorForm},
-    person::Person,
-  },
+  source::community::{CommunityModerator, CommunityModeratorForm},
   traits::Joinable,
 };
 use lemmy_utils::LemmyError;
@@ -38,11 +36,11 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct AddMod {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
-  object: ObjectId<Person>,
+  object: ObjectId<ApubPerson>,
   target: Url,
-  cc: [ObjectId<Community>; 1],
+  cc: [ObjectId<ApubCommunity>; 1],
   #[serde(rename = "type")]
   kind: AddType,
   id: Url,
@@ -54,9 +52,9 @@ pub struct AddMod {
 
 impl AddMod {
   pub async fn send(
-    community: &Community,
-    added_mod: &Person,
-    actor: &Person,
+    community: &ApubCommunity,
+    added_mod: &ApubPerson,
+    actor: &ApubPerson,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let id = generate_activity_id(
@@ -92,7 +90,7 @@ impl ActivityHandler for AddMod {
   ) -> Result<(), LemmyError> {
     verify_activity(self, &context.settings())?;
     verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
-    verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
+    verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
     verify_add_remove_moderator_target(&self.target, &self.cc[0])?;
     Ok(())
   }
index ec72b842949190b7cbe831f5d966e4c1211b657d..183dbfd5f90eaaef83701175aabf31b09cd90b78 100644 (file)
@@ -21,6 +21,7 @@ use crate::{
   fetcher::object_id::ObjectId,
   http::is_activity_already_known,
   insert_activity,
+  objects::community::ApubCommunity,
   send_lemmy_activity,
   CommunityType,
 };
@@ -35,7 +36,6 @@ use lemmy_apub_lib::{
   traits::{ActivityFields, ActivityHandler, ActorType},
   values::PublicUrl,
 };
-use lemmy_db_schema::source::community::Community;
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
@@ -62,7 +62,7 @@ pub enum AnnouncableActivities {
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct AnnounceActivity {
-  actor: ObjectId<Community>,
+  actor: ObjectId<ApubCommunity>,
   to: [PublicUrl; 1],
   object: AnnouncableActivities,
   cc: Vec<Url>,
@@ -78,7 +78,7 @@ pub struct AnnounceActivity {
 impl AnnounceActivity {
   pub async fn send(
     object: AnnouncableActivities,
-    community: &Community,
+    community: &ApubCommunity,
     additional_inboxes: Vec<Url>,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
index 9b4c3e8137f6c5e122eec9bc95592198a7dd6da0..a1c76c23b88d47d4c21116dd8b8868447ce3a60f 100644 (file)
@@ -8,6 +8,7 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
 };
 use activitystreams::{
   activity::kind::BlockType,
@@ -22,15 +23,11 @@ use lemmy_apub_lib::{
   values::PublicUrl,
 };
 use lemmy_db_schema::{
-  source::{
-    community::{
-      Community,
-      CommunityFollower,
-      CommunityFollowerForm,
-      CommunityPersonBan,
-      CommunityPersonBanForm,
-    },
-    person::Person,
+  source::community::{
+    CommunityFollower,
+    CommunityFollowerForm,
+    CommunityPersonBan,
+    CommunityPersonBanForm,
   },
   traits::{Bannable, Followable},
 };
@@ -42,10 +39,10 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct BlockUserFromCommunity {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
-  pub(in crate::activities::community) object: ObjectId<Person>,
-  cc: [ObjectId<Community>; 1],
+  pub(in crate::activities::community) object: ObjectId<ApubPerson>,
+  cc: [ObjectId<ApubCommunity>; 1],
   #[serde(rename = "type")]
   kind: BlockType,
   id: Url,
@@ -57,9 +54,9 @@ pub struct BlockUserFromCommunity {
 
 impl BlockUserFromCommunity {
   pub(in crate::activities::community) fn new(
-    community: &Community,
-    target: &Person,
-    actor: &Person,
+    community: &ApubCommunity,
+    target: &ApubPerson,
+    actor: &ApubPerson,
     context: &LemmyContext,
   ) -> Result<BlockUserFromCommunity, LemmyError> {
     Ok(BlockUserFromCommunity {
@@ -78,9 +75,9 @@ impl BlockUserFromCommunity {
   }
 
   pub async fn send(
-    community: &Community,
-    target: &Person,
-    actor: &Person,
+    community: &ApubCommunity,
+    target: &ApubPerson,
+    actor: &ApubPerson,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let block = BlockUserFromCommunity::new(community, target, actor, context)?;
@@ -102,7 +99,7 @@ impl ActivityHandler for BlockUserFromCommunity {
   ) -> Result<(), LemmyError> {
     verify_activity(self, &context.settings())?;
     verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
-    verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
+    verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
     Ok(())
   }
 
index dd6ccb7ffa6f4813a21b0dd39662ec1d909ed79a..f69ee026ecf08f3cb308a66fec80a57b68ff41ae 100644 (file)
@@ -2,12 +2,12 @@ use crate::{
   activities::community::announce::{AnnouncableActivities, AnnounceActivity},
   check_is_apub_id_valid,
   insert_activity,
+  objects::community::ApubCommunity,
   send_lemmy_activity,
   CommunityType,
 };
 use itertools::Itertools;
 use lemmy_apub_lib::traits::ActorType;
-use lemmy_db_schema::source::community::Community;
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
 use url::Url;
@@ -20,7 +20,7 @@ pub mod undo_block_user;
 pub mod update;
 
 async fn list_community_follower_inboxes(
-  community: &Community,
+  community: &ApubCommunity,
   additional_inboxes: Vec<Url>,
   context: &LemmyContext,
 ) -> Result<Vec<Url>, LemmyError> {
@@ -45,7 +45,7 @@ pub(crate) async fn send_to_community<T: ActorType>(
   activity: AnnouncableActivities,
   activity_id: &Url,
   actor: &T,
-  community: &Community,
+  community: &ApubCommunity,
   additional_inboxes: Vec<Url>,
   context: &LemmyContext,
 ) -> Result<(), LemmyError> {
index 4f980d01a1e64098d8f3ba6017b2cd03a54580a7..b145e7171f9d539a3c7a3565b7a83849b6e6f097 100644 (file)
@@ -11,6 +11,7 @@ use crate::{
   context::lemmy_context,
   fetcher::object_id::ObjectId,
   generate_moderators_url,
+  objects::{community::ApubCommunity, person::ApubPerson},
 };
 use activitystreams::{
   activity::kind::RemoveType,
@@ -25,10 +26,7 @@ use lemmy_apub_lib::{
   values::PublicUrl,
 };
 use lemmy_db_schema::{
-  source::{
-    community::{Community, CommunityModerator, CommunityModeratorForm},
-    person::Person,
-  },
+  source::community::{CommunityModerator, CommunityModeratorForm},
   traits::Joinable,
 };
 use lemmy_utils::LemmyError;
@@ -39,10 +37,10 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct RemoveMod {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
-  pub(in crate::activities) object: ObjectId<Person>,
-  cc: [ObjectId<Community>; 1],
+  pub(in crate::activities) object: ObjectId<ApubPerson>,
+  cc: [ObjectId<ApubCommunity>; 1],
   #[serde(rename = "type")]
   kind: RemoveType,
   // if target is set, this is means remove mod from community
@@ -56,9 +54,9 @@ pub struct RemoveMod {
 
 impl RemoveMod {
   pub async fn send(
-    community: &Community,
-    removed_mod: &Person,
-    actor: &Person,
+    community: &ApubCommunity,
+    removed_mod: &ApubPerson,
+    actor: &ApubPerson,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let id = generate_activity_id(
@@ -94,7 +92,7 @@ impl ActivityHandler for RemoveMod {
     verify_activity(self, &context.settings())?;
     if let Some(target) = &self.target {
       verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
-      verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
+      verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
       verify_add_remove_moderator_target(target, &self.cc[0])?;
     } else {
       verify_delete_activity(
index 47cace42ce0cddaaecc930792c55bc54b4a1262d..1614de672d9b131439ddbf425326fca5950c50f0 100644 (file)
@@ -12,6 +12,7 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
 };
 use activitystreams::{
   activity::kind::UndoType,
@@ -26,10 +27,7 @@ use lemmy_apub_lib::{
   values::PublicUrl,
 };
 use lemmy_db_schema::{
-  source::{
-    community::{Community, CommunityPersonBan, CommunityPersonBanForm},
-    person::Person,
-  },
+  source::community::{CommunityPersonBan, CommunityPersonBanForm},
   traits::Bannable,
 };
 use lemmy_utils::LemmyError;
@@ -40,10 +38,10 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct UndoBlockUserFromCommunity {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
   object: BlockUserFromCommunity,
-  cc: [ObjectId<Community>; 1],
+  cc: [ObjectId<ApubCommunity>; 1],
   #[serde(rename = "type")]
   kind: UndoType,
   id: Url,
@@ -55,9 +53,9 @@ pub struct UndoBlockUserFromCommunity {
 
 impl UndoBlockUserFromCommunity {
   pub async fn send(
-    community: &Community,
-    target: &Person,
-    actor: &Person,
+    community: &ApubCommunity,
+    target: &ApubPerson,
+    actor: &ApubPerson,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let block = BlockUserFromCommunity::new(community, target, actor, context)?;
@@ -93,7 +91,7 @@ impl ActivityHandler for UndoBlockUserFromCommunity {
   ) -> Result<(), LemmyError> {
     verify_activity(self, &context.settings())?;
     verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
-    verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
+    verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
     self.object.verify(context, request_counter).await?;
     Ok(())
   }
index 02b7126ad76423fe93080609ece54f0cf007cbee..1120bd8bb70d136a2f23f24133b940c6782740b3 100644 (file)
@@ -8,7 +8,10 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
-  objects::{community::Group, ToApub},
+  objects::{
+    community::{ApubCommunity, Group},
+    person::ApubPerson,
+  },
 };
 use activitystreams::{
   activity::kind::UpdateType,
@@ -19,14 +22,11 @@ use activitystreams::{
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
   data::Data,
-  traits::{ActivityFields, ActivityHandler, ActorType},
+  traits::{ActivityFields, ActivityHandler, ActorType, ToApub},
   values::PublicUrl,
 };
 use lemmy_db_schema::{
-  source::{
-    community::{Community, CommunityForm},
-    person::Person,
-  },
+  source::community::{Community, CommunityForm},
   traits::Crud,
 };
 use lemmy_utils::LemmyError;
@@ -39,11 +39,11 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct UpdateCommunity {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
   // TODO: would be nice to use a separate struct here, which only contains the fields updated here
   object: Group,
-  cc: [ObjectId<Community>; 1],
+  cc: [ObjectId<ApubCommunity>; 1],
   #[serde(rename = "type")]
   kind: UpdateType,
   id: Url,
@@ -55,8 +55,8 @@ pub struct UpdateCommunity {
 
 impl UpdateCommunity {
   pub async fn send(
-    community: &Community,
-    actor: &Person,
+    community: &ApubCommunity,
+    actor: &ApubPerson,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let id = generate_activity_id(
@@ -89,7 +89,7 @@ impl ActivityHandler for UpdateCommunity {
   ) -> Result<(), LemmyError> {
     verify_activity(self, &context.settings())?;
     verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
-    verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
+    verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
     Ok(())
   }
 
index 251a3ffa411e29e99461ecb081e83d656b99dd8d..02df7dc38a2d87de5f133179fa09689e55060e3a 100644 (file)
@@ -12,6 +12,7 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
 };
 use activitystreams::{
   activity::kind::DeleteType,
@@ -38,7 +39,6 @@ use lemmy_db_schema::{
       ModRemovePost,
       ModRemovePostForm,
     },
-    person::Person,
     post::Post,
   },
   traits::Crud,
@@ -65,10 +65,10 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct Delete {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
   pub(in crate::activities::deletion) object: Url,
-  pub(in crate::activities::deletion) cc: [ObjectId<Community>; 1],
+  pub(in crate::activities::deletion) cc: [ObjectId<ApubCommunity>; 1],
   #[serde(rename = "type")]
   kind: DeleteType,
   /// If summary is present, this is a mod action (Remove in Lemmy terms). Otherwise, its a user
@@ -136,8 +136,8 @@ impl ActivityHandler for Delete {
 
 impl Delete {
   pub(in crate::activities::deletion) fn new(
-    actor: &Person,
-    community: &Community,
+    actor: &ApubPerson,
+    community: &ApubCommunity,
     object_id: Url,
     summary: Option<String>,
     context: &LemmyContext,
@@ -158,8 +158,8 @@ impl Delete {
     })
   }
   pub(in crate::activities::deletion) async fn send(
-    actor: &Person,
-    community: &Community,
+    actor: &ApubPerson,
+    community: &ApubCommunity,
     object_id: Url,
     summary: Option<String>,
     context: &LemmyContext,
@@ -173,7 +173,7 @@ impl Delete {
 }
 
 pub(in crate::activities) async fn receive_remove_action(
-  actor: &ObjectId<Person>,
+  actor: &ObjectId<ApubPerson>,
   object: &Url,
   reason: Option<String>,
   context: &LemmyContext,
index 3a38f2a22b408bee63b050ec3e22d2b1f7325fb8..4352afe87a51f3b8a646e76eb57fb73313fce8a4 100644 (file)
@@ -5,14 +5,14 @@ use crate::{
     verify_person_in_community,
   },
   fetcher::object_id::ObjectId,
+  objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
 };
-use diesel::PgConnection;
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
   traits::{ActivityFields, ActorType, ApubObject},
   verify::verify_domains_match,
 };
-use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
+use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
 use lemmy_utils::LemmyError;
 use lemmy_websocket::{
   send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
@@ -25,8 +25,8 @@ pub mod delete;
 pub mod undo_delete;
 
 pub async fn send_apub_delete(
-  actor: &Person,
-  community: &Community,
+  actor: &ApubPerson,
+  community: &ApubCommunity,
   object_id: Url,
   deleted: bool,
   context: &LemmyContext,
@@ -41,8 +41,8 @@ pub async fn send_apub_delete(
 // TODO: remove reason is actually optional in lemmy. we set an empty string in that case, but its
 //       ugly
 pub async fn send_apub_remove(
-  actor: &Person,
-  community: &Community,
+  actor: &ApubPerson,
+  community: &ApubCommunity,
   object_id: Url,
   reason: String,
   removed: bool,
@@ -56,9 +56,9 @@ pub async fn send_apub_remove(
 }
 
 pub enum DeletableObjects {
-  Community(Box<Community>),
-  Comment(Box<Comment>),
-  Post(Box<Post>),
+  Community(Box<ApubCommunity>),
+  Comment(Box<ApubComment>),
+  Post(Box<ApubPost>),
 }
 
 impl DeletableObjects {
@@ -66,39 +66,23 @@ impl DeletableObjects {
     ap_id: &Url,
     context: &LemmyContext,
   ) -> Result<DeletableObjects, LemmyError> {
-    if let Some(c) =
-      DeletableObjects::read_type_from_db::<Community>(ap_id.clone(), context).await?
-    {
+    if let Some(c) = ApubCommunity::read_from_apub_id(ap_id.clone(), context).await? {
       return Ok(DeletableObjects::Community(Box::new(c)));
     }
-    if let Some(p) = DeletableObjects::read_type_from_db::<Post>(ap_id.clone(), context).await? {
+    if let Some(p) = ApubPost::read_from_apub_id(ap_id.clone(), context).await? {
       return Ok(DeletableObjects::Post(Box::new(p)));
     }
-    if let Some(c) = DeletableObjects::read_type_from_db::<Comment>(ap_id.clone(), context).await? {
+    if let Some(c) = ApubComment::read_from_apub_id(ap_id.clone(), context).await? {
       return Ok(DeletableObjects::Comment(Box::new(c)));
     }
     Err(diesel::NotFound.into())
   }
-
-  // TODO: a method like this should be provided by fetcher module
-  async fn read_type_from_db<Type>(
-    ap_id: Url,
-    context: &LemmyContext,
-  ) -> Result<Option<Type>, LemmyError>
-  where
-    Type: ApubObject<DataType = PgConnection> + Send + 'static,
-  {
-    blocking(context.pool(), move |conn| {
-      Type::read_from_apub_id(conn, ap_id)
-    })
-    .await?
-  }
 }
 
 pub(in crate::activities) async fn verify_delete_activity(
   object: &Url,
   activity: &dyn ActivityFields,
-  community_id: &ObjectId<Community>,
+  community_id: &ObjectId<ApubCommunity>,
   is_mod_action: bool,
   context: &LemmyContext,
   request_counter: &mut i32,
@@ -115,7 +99,7 @@ pub(in crate::activities) async fn verify_delete_activity(
       // community deletion is always a mod (or admin) action
       verify_mod_action(
         &actor,
-        ObjectId::new(c.actor_id()),
+        &ObjectId::new(c.actor_id()),
         context,
         request_counter,
       )
@@ -124,7 +108,7 @@ pub(in crate::activities) async fn verify_delete_activity(
     DeletableObjects::Post(p) => {
       verify_delete_activity_post_or_comment(
         activity,
-        &p.ap_id.into(),
+        &p.ap_id.clone().into(),
         community_id,
         is_mod_action,
         context,
@@ -135,7 +119,7 @@ pub(in crate::activities) async fn verify_delete_activity(
     DeletableObjects::Comment(c) => {
       verify_delete_activity_post_or_comment(
         activity,
-        &c.ap_id.into(),
+        &c.ap_id.clone().into(),
         community_id,
         is_mod_action,
         context,
@@ -150,7 +134,7 @@ pub(in crate::activities) async fn verify_delete_activity(
 async fn verify_delete_activity_post_or_comment(
   activity: &dyn ActivityFields,
   object_id: &Url,
-  community_id: &ObjectId<Community>,
+  community_id: &ObjectId<ApubCommunity>,
   is_mod_action: bool,
   context: &LemmyContext,
   request_counter: &mut i32,
@@ -158,7 +142,7 @@ async fn verify_delete_activity_post_or_comment(
   let actor = ObjectId::new(activity.actor().clone());
   verify_person_in_community(&actor, community_id, context, request_counter).await?;
   if is_mod_action {
-    verify_mod_action(&actor, community_id.clone(), context, request_counter).await?;
+    verify_mod_action(&actor, community_id, context, request_counter).await?;
   } else {
     // domain of post ap_id and post.creator ap_id are identical, so we just check the former
     verify_domains_match(activity.actor(), object_id)?;
@@ -177,7 +161,7 @@ struct WebsocketMessages {
 ///       because of the mod log
 async fn receive_delete_action(
   object: &Url,
-  actor: &ObjectId<Person>,
+  actor: &ObjectId<ApubPerson>,
   ws_messages: WebsocketMessages,
   deleted: bool,
   context: &LemmyContext,
index 7a96d430182517ed42604e4363f8635d1063f482..327bf86c03a6ac28888d733b62f149f36c4fc6da 100644 (file)
@@ -13,6 +13,7 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
 };
 use activitystreams::{
   activity::kind::UndoType,
@@ -27,7 +28,7 @@ use lemmy_apub_lib::{
   traits::{ActivityFields, ActivityHandler, ActorType},
   values::PublicUrl,
 };
-use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
+use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
 use lemmy_utils::LemmyError;
 use lemmy_websocket::{
   send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
@@ -40,10 +41,10 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct UndoDelete {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
   object: Delete,
-  cc: [ObjectId<Community>; 1],
+  cc: [ObjectId<ApubCommunity>; 1],
   #[serde(rename = "type")]
   kind: UndoType,
   id: Url,
@@ -102,8 +103,8 @@ impl ActivityHandler for UndoDelete {
 
 impl UndoDelete {
   pub(in crate::activities::deletion) async fn send(
-    actor: &Person,
-    community: &Community,
+    actor: &ApubPerson,
+    community: &ApubCommunity,
     object_id: Url,
     summary: Option<String>,
     context: &LemmyContext,
index bfc9ba315f7c5b45949afb1df44e1b293f322c4b..6fa65e7b1080d85749940f2afe34706d11a95c00 100644 (file)
@@ -7,6 +7,7 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
   send_lemmy_activity,
 };
 use activitystreams::{
@@ -21,13 +22,7 @@ use lemmy_apub_lib::{
   traits::{ActivityFields, ActivityHandler, ActorType},
   verify::verify_urls_match,
 };
-use lemmy_db_schema::{
-  source::{
-    community::{Community, CommunityFollower},
-    person::Person,
-  },
-  traits::Followable,
-};
+use lemmy_db_schema::{source::community::CommunityFollower, traits::Followable};
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
@@ -36,8 +31,8 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct AcceptFollowCommunity {
-  actor: ObjectId<Community>,
-  to: ObjectId<Person>,
+  actor: ObjectId<ApubCommunity>,
+  to: ObjectId<ApubPerson>,
   object: FollowCommunity,
   #[serde(rename = "type")]
   kind: AcceptType,
@@ -72,7 +67,7 @@ impl AcceptFollowCommunity {
       context: lemmy_context(),
       unparsed: Default::default(),
     };
-    let inbox = vec![person.inbox_url.into()];
+    let inbox = vec![person.inbox_url()];
     send_lemmy_activity(context, &accept, &accept.id, &community, inbox, true).await
   }
 }
index c75a08cd12904bf8c03f804f74c68d4614f8dc67..144243812a5bc8bea07627384e656ff3aa82acd4 100644 (file)
@@ -7,6 +7,7 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
   send_lemmy_activity,
 };
 use activitystreams::{
@@ -22,10 +23,7 @@ use lemmy_apub_lib::{
   verify::verify_urls_match,
 };
 use lemmy_db_schema::{
-  source::{
-    community::{Community, CommunityFollower, CommunityFollowerForm},
-    person::Person,
-  },
+  source::community::{CommunityFollower, CommunityFollowerForm},
   traits::Followable,
 };
 use lemmy_utils::LemmyError;
@@ -36,10 +34,10 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct FollowCommunity {
-  pub(in crate::activities::following) actor: ObjectId<Person>,
+  pub(in crate::activities::following) actor: ObjectId<ApubPerson>,
   // TODO: is there any reason to put the same community id twice, in to and object?
-  pub(in crate::activities::following) to: ObjectId<Community>,
-  pub(in crate::activities::following) object: ObjectId<Community>,
+  pub(in crate::activities::following) to: ObjectId<ApubCommunity>,
+  pub(in crate::activities::following) object: ObjectId<ApubCommunity>,
   #[serde(rename = "type")]
   kind: FollowType,
   id: Url,
@@ -51,8 +49,8 @@ pub struct FollowCommunity {
 
 impl FollowCommunity {
   pub(in crate::activities::following) fn new(
-    actor: &Person,
-    community: &Community,
+    actor: &ApubPerson,
+    community: &ApubCommunity,
     context: &LemmyContext,
   ) -> Result<FollowCommunity, LemmyError> {
     Ok(FollowCommunity {
@@ -69,8 +67,8 @@ impl FollowCommunity {
     })
   }
   pub async fn send(
-    actor: &Person,
-    community: &Community,
+    actor: &ApubPerson,
+    community: &ApubCommunity,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let community_follower_form = CommunityFollowerForm {
index 2699a98c1071077ecab9dc8dec65418ae4556f1c..5c548ae4835861791a7974585b057067fa1aaa83 100644 (file)
@@ -7,6 +7,7 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
   send_lemmy_activity,
 };
 use activitystreams::{
@@ -22,10 +23,7 @@ use lemmy_apub_lib::{
   verify::verify_urls_match,
 };
 use lemmy_db_schema::{
-  source::{
-    community::{Community, CommunityFollower, CommunityFollowerForm},
-    person::Person,
-  },
+  source::community::{CommunityFollower, CommunityFollowerForm},
   traits::Followable,
 };
 use lemmy_utils::LemmyError;
@@ -36,8 +34,8 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct UndoFollowCommunity {
-  actor: ObjectId<Person>,
-  to: ObjectId<Community>,
+  actor: ObjectId<ApubPerson>,
+  to: ObjectId<ApubCommunity>,
   object: FollowCommunity,
   #[serde(rename = "type")]
   kind: UndoType,
@@ -50,8 +48,8 @@ pub struct UndoFollowCommunity {
 
 impl UndoFollowCommunity {
   pub async fn send(
-    actor: &Person,
-    community: &Community,
+    actor: &ApubPerson,
+    community: &ApubCommunity,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let object = FollowCommunity::new(actor, community, context)?;
index 618c14f50ddca2a88158d62df5d8dffba540df15..0832a85c8086d48d72e2e284db9bc339e9200ba1 100644 (file)
@@ -3,15 +3,17 @@ use crate::{
   check_is_apub_id_valid,
   fetcher::object_id::ObjectId,
   generate_moderators_url,
+  objects::{community::ApubCommunity, person::ApubPerson},
 };
 use anyhow::anyhow;
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{traits::ActivityFields, verify::verify_domains_match};
-use lemmy_db_schema::source::{community::Community, person::Person};
+use lemmy_db_schema::source::community::Community;
 use lemmy_db_views_actor::community_view::CommunityView;
 use lemmy_utils::{settings::structs::Settings, LemmyError};
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
+use std::ops::Deref;
 use strum_macros::ToString;
 use url::{ParseError, Url};
 use uuid::Uuid;
@@ -35,7 +37,7 @@ pub enum CreateOrUpdateType {
 /// Checks that the specified Url actually identifies a Person (by fetching it), and that the person
 /// doesn't have a site ban.
 async fn verify_person(
-  person_id: &ObjectId<Person>,
+  person_id: &ObjectId<ApubPerson>,
   context: &LemmyContext,
   request_counter: &mut i32,
 ) -> Result<(), LemmyError> {
@@ -50,7 +52,7 @@ pub(crate) async fn extract_community(
   cc: &[Url],
   context: &LemmyContext,
   request_counter: &mut i32,
-) -> Result<Community, LemmyError> {
+) -> Result<ApubCommunity, LemmyError> {
   let mut cc_iter = cc.iter();
   loop {
     if let Some(cid) = cc_iter.next() {
@@ -67,19 +69,19 @@ pub(crate) async fn extract_community(
 /// Fetches the person and community to verify their type, then checks if person is banned from site
 /// or community.
 pub(crate) async fn verify_person_in_community(
-  person_id: &ObjectId<Person>,
-  community_id: &ObjectId<Community>,
+  person_id: &ObjectId<ApubPerson>,
+  community_id: &ObjectId<ApubCommunity>,
   context: &LemmyContext,
   request_counter: &mut i32,
 ) -> Result<(), LemmyError> {
   let community = community_id.dereference(context, request_counter).await?;
   let person = person_id.dereference(context, request_counter).await?;
-  check_community_or_site_ban(&person, community.id, context.pool()).await
+  check_community_or_site_ban(person.deref(), community.id, context.pool()).await
 }
 
 /// Simply check that the url actually refers to a valid group.
 async fn verify_community(
-  community_id: &ObjectId<Community>,
+  community_id: &ObjectId<ApubCommunity>,
   context: &LemmyContext,
   request_counter: &mut i32,
 ) -> Result<(), LemmyError> {
@@ -97,8 +99,8 @@ fn verify_activity(activity: &dyn ActivityFields, settings: &Settings) -> Result
 /// because in case of remote communities, admins can also perform mod actions. As admin status
 /// is not federated, we cant verify their actions remotely.
 pub(crate) async fn verify_mod_action(
-  actor_id: &ObjectId<Person>,
-  community_id: ObjectId<Community>,
+  actor_id: &ObjectId<ApubPerson>,
+  community_id: &ObjectId<ApubCommunity>,
   context: &LemmyContext,
   request_counter: &mut i32,
 ) -> Result<(), LemmyError> {
@@ -126,7 +128,7 @@ pub(crate) async fn verify_mod_action(
 /// /c/community/moderators. Any different values are unsupported.
 fn verify_add_remove_moderator_target(
   target: &Url,
-  community: &ObjectId<Community>,
+  community: &ObjectId<ApubCommunity>,
 ) -> Result<(), LemmyError> {
   if target != &generate_moderators_url(&community.clone().into())?.into_inner() {
     return Err(anyhow!("Unkown target url").into());
index 7a1ddc4060e2c378b0f1154afae64acb855f542a..cc7ef5c97c015110616957304f74af2b44a06c32 100644 (file)
@@ -10,21 +10,22 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
-  objects::{post::Page, FromApub, ToApub},
+  objects::{
+    community::ApubCommunity,
+    person::ApubPerson,
+    post::{ApubPost, Page},
+  },
 };
 use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
 use anyhow::anyhow;
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
   data::Data,
-  traits::{ActivityFields, ActivityHandler, ActorType},
+  traits::{ActivityFields, ActivityHandler, ActorType, FromApub, ToApub},
   values::PublicUrl,
   verify::{verify_domains_match, verify_urls_match},
 };
-use lemmy_db_schema::{
-  source::{community::Community, person::Person, post::Post},
-  traits::Crud,
-};
+use lemmy_db_schema::{source::community::Community, traits::Crud};
 use lemmy_utils::LemmyError;
 use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
 use serde::{Deserialize, Serialize};
@@ -33,10 +34,10 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct CreateOrUpdatePost {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
   object: Page,
-  cc: [ObjectId<Community>; 1],
+  cc: [ObjectId<ApubCommunity>; 1],
   #[serde(rename = "type")]
   kind: CreateOrUpdateType,
   id: Url,
@@ -48,16 +49,17 @@ pub struct CreateOrUpdatePost {
 
 impl CreateOrUpdatePost {
   pub async fn send(
-    post: &Post,
-    actor: &Person,
+    post: &ApubPost,
+    actor: &ApubPerson,
     kind: CreateOrUpdateType,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let community_id = post.community_id;
-    let community = blocking(context.pool(), move |conn| {
+    let community: ApubCommunity = blocking(context.pool(), move |conn| {
       Community::read(conn, community_id)
     })
-    .await??;
+    .await??
+    .into();
 
     let id = generate_activity_id(
       kind.clone(),
@@ -109,7 +111,7 @@ impl ActivityHandler for CreateOrUpdatePost {
       CreateOrUpdateType::Update => {
         let is_mod_action = self.object.is_mod_action(context).await?;
         if is_mod_action {
-          verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
+          verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
         } else {
           verify_domains_match(self.actor.inner(), self.object.id_unchecked())?;
           verify_urls_match(self.actor(), self.object.attributed_to.inner())?;
@@ -126,7 +128,8 @@ impl ActivityHandler for CreateOrUpdatePost {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     let actor = self.actor.dereference(context, request_counter).await?;
-    let post = Post::from_apub(&self.object, context, &actor.actor_id(), request_counter).await?;
+    let post =
+      ApubPost::from_apub(&self.object, context, &actor.actor_id(), request_counter).await?;
 
     let notif_type = match self.kind {
       CreateOrUpdateType::Create => UserOperationCrud::CreatePost,
index 6b3bc2b620f34a824f18005938ee423d3e764f09..a1ee5598e639c46b24e4fdf51d19aa230be5b986 100644 (file)
@@ -2,20 +2,20 @@ use crate::{
   activities::{generate_activity_id, verify_activity, verify_person, CreateOrUpdateType},
   context::lemmy_context,
   fetcher::object_id::ObjectId,
-  objects::{private_message::Note, FromApub, ToApub},
+  objects::{
+    person::ApubPerson,
+    private_message::{ApubPrivateMessage, Note},
+  },
   send_lemmy_activity,
 };
 use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
   data::Data,
-  traits::{ActivityFields, ActivityHandler, ActorType},
+  traits::{ActivityFields, ActivityHandler, ActorType, FromApub, ToApub},
   verify::verify_domains_match,
 };
-use lemmy_db_schema::{
-  source::{person::Person, private_message::PrivateMessage},
-  traits::Crud,
-};
+use lemmy_db_schema::{source::person::Person, traits::Crud};
 use lemmy_utils::LemmyError;
 use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
 use serde::{Deserialize, Serialize};
@@ -27,8 +27,8 @@ pub struct CreateOrUpdatePrivateMessage {
   #[serde(rename = "@context")]
   pub context: OneOrMany<AnyBase>,
   id: Url,
-  actor: ObjectId<Person>,
-  to: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
+  to: ObjectId<ApubPerson>,
   object: Note,
   #[serde(rename = "type")]
   kind: CreateOrUpdateType,
@@ -38,14 +38,16 @@ pub struct CreateOrUpdatePrivateMessage {
 
 impl CreateOrUpdatePrivateMessage {
   pub async fn send(
-    private_message: &PrivateMessage,
-    actor: &Person,
+    private_message: &ApubPrivateMessage,
+    actor: &ApubPerson,
     kind: CreateOrUpdateType,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let recipient_id = private_message.recipient_id;
-    let recipient =
-      blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
+    let recipient: ApubPerson =
+      blocking(context.pool(), move |conn| Person::read(conn, recipient_id))
+        .await??
+        .into();
 
     let id = generate_activity_id(
       kind.clone(),
@@ -85,7 +87,8 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     let private_message =
-      PrivateMessage::from_apub(&self.object, context, self.actor.inner(), request_counter).await?;
+      ApubPrivateMessage::from_apub(&self.object, context, self.actor.inner(), request_counter)
+        .await?;
 
     let notif_type = match self.kind {
       CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage,
index ded3b3ad4202ba15635b2b42c516f8d07ba1813f..bb374eb47a0582023fbe6956108f9f71d1e651cf 100644 (file)
@@ -2,6 +2,7 @@ use crate::{
   activities::{generate_activity_id, verify_activity, verify_person},
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{person::ApubPerson, private_message::ApubPrivateMessage},
   send_lemmy_activity,
 };
 use activitystreams::{
@@ -28,9 +29,9 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct DeletePrivateMessage {
-  actor: ObjectId<Person>,
-  to: ObjectId<Person>,
-  pub(in crate::activities::private_message) object: ObjectId<PrivateMessage>,
+  actor: ObjectId<ApubPerson>,
+  to: ObjectId<ApubPerson>,
+  pub(in crate::activities::private_message) object: ObjectId<ApubPrivateMessage>,
   #[serde(rename = "type")]
   kind: DeleteType,
   id: Url,
@@ -42,7 +43,7 @@ pub struct DeletePrivateMessage {
 
 impl DeletePrivateMessage {
   pub(in crate::activities::private_message) fn new(
-    actor: &Person,
+    actor: &ApubPerson,
     pm: &PrivateMessage,
     context: &LemmyContext,
   ) -> Result<DeletePrivateMessage, LemmyError> {
@@ -60,16 +61,18 @@ impl DeletePrivateMessage {
     })
   }
   pub async fn send(
-    actor: &Person,
-    pm: &PrivateMessage,
+    actor: &ApubPerson,
+    pm: &ApubPrivateMessage,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let delete = DeletePrivateMessage::new(actor, pm, context)?;
     let delete_id = delete.id.clone();
 
     let recipient_id = pm.recipient_id;
-    let recipient =
-      blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
+    let recipient: ApubPerson =
+      blocking(context.pool(), move |conn| Person::read(conn, recipient_id))
+        .await??
+        .into();
     let inbox = vec![recipient.shared_inbox_or_inbox_url()];
     send_lemmy_activity(context, &delete, &delete_id, actor, inbox, true).await
   }
index 2c5fd0e72d8cb5920dfc555f210f9d2b8af6b27e..0263b81156a40112cca31db5966cd9d099e6a14e 100644 (file)
@@ -7,6 +7,7 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{person::ApubPerson, private_message::ApubPrivateMessage},
   send_lemmy_activity,
 };
 use activitystreams::{
@@ -33,8 +34,8 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct UndoDeletePrivateMessage {
-  actor: ObjectId<Person>,
-  to: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
+  to: ObjectId<ApubPerson>,
   object: DeletePrivateMessage,
   #[serde(rename = "type")]
   kind: UndoType,
@@ -47,13 +48,15 @@ pub struct UndoDeletePrivateMessage {
 
 impl UndoDeletePrivateMessage {
   pub async fn send(
-    actor: &Person,
-    pm: &PrivateMessage,
+    actor: &ApubPerson,
+    pm: &ApubPrivateMessage,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let recipient_id = pm.recipient_id;
-    let recipient =
-      blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
+    let recipient: ApubPerson =
+      blocking(context.pool(), move |conn| Person::read(conn, recipient_id))
+        .await??
+        .into();
 
     let object = DeletePrivateMessage::new(actor, pm, context)?;
     let id = generate_activity_id(
index aee673cfa5beb5a5b00d5bbfdd1ab54ad20a5cfc..d0b1f971c069062fc9f091706757a2b4e4434534 100644 (file)
@@ -2,6 +2,7 @@ use crate::{
   activities::{generate_activity_id, verify_activity, verify_person_in_community},
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
   send_lemmy_activity,
   PostOrComment,
 };
@@ -17,14 +18,11 @@ use lemmy_apub_lib::{
   traits::{ActivityFields, ActivityHandler, ActorType},
 };
 use lemmy_db_schema::{
-  newtypes::CommunityId,
   source::{
     comment_report::{CommentReport, CommentReportForm},
-    community::Community,
-    person::Person,
     post_report::{PostReport, PostReportForm},
   },
-  traits::{Crud, Reportable},
+  traits::Reportable,
 };
 use lemmy_db_views::{comment_report_view::CommentReportView, post_report_view::PostReportView};
 use lemmy_utils::LemmyError;
@@ -35,8 +33,8 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct Report {
-  actor: ObjectId<Person>,
-  to: [ObjectId<Community>; 1],
+  actor: ObjectId<ApubPerson>,
+  to: [ObjectId<ApubCommunity>; 1],
   object: ObjectId<PostOrComment>,
   summary: String,
   #[serde(rename = "type")]
@@ -51,15 +49,12 @@ pub struct Report {
 impl Report {
   pub async fn send(
     object_id: ObjectId<PostOrComment>,
-    actor: &Person,
-    community_id: CommunityId,
+    actor: &ApubPerson,
+    community_id: ObjectId<ApubCommunity>,
     reason: String,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??;
+    let community = community_id.dereference_local(context).await?;
     let kind = FlagType::Flag;
     let id = generate_activity_id(
       kind.clone(),
@@ -111,10 +106,10 @@ impl ActivityHandler for Report {
         let report_form = PostReportForm {
           creator_id: actor.id,
           post_id: post.id,
-          original_post_name: post.name,
-          original_post_url: post.url,
+          original_post_name: post.name.clone(),
+          original_post_url: post.url.clone(),
           reason: self.summary,
-          original_post_body: post.body,
+          original_post_body: post.body.clone(),
         };
 
         let report = blocking(context.pool(), move |conn| {
@@ -138,7 +133,7 @@ impl ActivityHandler for Report {
         let report_form = CommentReportForm {
           creator_id: actor.id,
           comment_id: comment.id,
-          original_comment_text: comment.content,
+          original_comment_text: comment.content.clone(),
           reason: self.summary,
         };
 
index 10305466ce3c0be87d1e9355630aaa1d05b22504..5b41e08687dc30cea74eb5fcccb8c8acd289eceb 100644 (file)
@@ -5,6 +5,7 @@ use crate::{
     verify_activity,
   },
   fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
 };
 use activitystreams::{
   activity::kind::UndoType,
@@ -17,7 +18,6 @@ use lemmy_apub_lib::{
   traits::{ActivityFields, ActivityHandler},
   values::PublicUrl,
 };
-use lemmy_db_schema::source::{community::Community, person::Person};
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
@@ -26,11 +26,11 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct UndoRemovePostCommentOrCommunity {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
   // Note, there is no such thing as Undo/Remove/Mod, so we ignore that
   object: RemoveMod,
-  cc: [ObjectId<Community>; 1],
+  cc: [ObjectId<ApubCommunity>; 1],
   #[serde(rename = "type")]
   kind: UndoType,
   id: Url,
index 90757eebfeccdc14d74aca007cc9506e64357594..829553d35da53d13819cfb70611129fba19d35e3 100644 (file)
@@ -1,10 +1,12 @@
-use crate::activities::voting::vote::VoteType;
+use crate::{
+  activities::voting::vote::VoteType,
+  objects::{comment::ApubComment, person::ApubPerson, post::ApubPost},
+};
 use lemmy_api_common::blocking;
 use lemmy_db_schema::{
   source::{
-    comment::{Comment, CommentLike, CommentLikeForm},
-    person::Person,
-    post::{Post, PostLike, PostLikeForm},
+    comment::{CommentLike, CommentLikeForm},
+    post::{PostLike, PostLikeForm},
   },
   traits::Likeable,
 };
@@ -20,8 +22,8 @@ pub mod vote;
 
 async fn vote_comment(
   vote_type: &VoteType,
-  actor: Person,
-  comment: &Comment,
+  actor: ApubPerson,
+  comment: &ApubComment,
   context: &LemmyContext,
 ) -> Result<(), LemmyError> {
   let comment_id = comment.id;
@@ -44,8 +46,8 @@ async fn vote_comment(
 
 async fn vote_post(
   vote_type: &VoteType,
-  actor: Person,
-  post: &Post,
+  actor: ApubPerson,
+  post: &ApubPost,
   context: &LemmyContext,
 ) -> Result<(), LemmyError> {
   let post_id = post.id;
@@ -66,8 +68,8 @@ async fn vote_post(
 }
 
 async fn undo_vote_comment(
-  actor: Person,
-  comment: &Comment,
+  actor: ApubPerson,
+  comment: &ApubComment,
   context: &LemmyContext,
 ) -> Result<(), LemmyError> {
   let comment_id = comment.id;
@@ -82,8 +84,8 @@ async fn undo_vote_comment(
 }
 
 async fn undo_vote_post(
-  actor: Person,
-  post: &Post,
+  actor: ApubPerson,
+  post: &ApubPost,
   context: &LemmyContext,
 ) -> Result<(), LemmyError> {
   let post_id = post.id;
index 2c87aa8994ca62a160625cf740eabbbfca09f3ad..d72b5245dce641f5bae0a0e472b108c371d4efe6 100644 (file)
@@ -12,6 +12,7 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
   PostOrComment,
 };
 use activitystreams::{
@@ -27,11 +28,7 @@ use lemmy_apub_lib::{
   values::PublicUrl,
   verify::verify_urls_match,
 };
-use lemmy_db_schema::{
-  newtypes::CommunityId,
-  source::{community::Community, person::Person},
-  traits::Crud,
-};
+use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
@@ -41,10 +38,10 @@ use url::Url;
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct UndoVote {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
   object: Vote,
-  cc: [ObjectId<Community>; 1],
+  cc: [ObjectId<ApubCommunity>; 1],
   #[serde(rename = "type")]
   kind: UndoType,
   id: Url,
@@ -57,15 +54,16 @@ pub struct UndoVote {
 impl UndoVote {
   pub async fn send(
     object: &PostOrComment,
-    actor: &Person,
+    actor: &ApubPerson,
     community_id: CommunityId,
     kind: VoteType,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
-    let community = blocking(context.pool(), move |conn| {
+    let community: ApubCommunity = blocking(context.pool(), move |conn| {
       Community::read(conn, community_id)
     })
-    .await??;
+    .await??
+    .into();
 
     let object = Vote::new(object, actor, &community, kind.clone(), context)?;
     let id = generate_activity_id(
index 2463cbc024af7b510a143e349b3f9ebddac890eb..5d4c9066e51f63bee436928f9964b8399e458b1d 100644 (file)
@@ -8,6 +8,7 @@ use crate::{
   },
   context::lemmy_context,
   fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
   PostOrComment,
 };
 use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
@@ -18,11 +19,7 @@ use lemmy_apub_lib::{
   traits::{ActivityFields, ActivityHandler, ActorType},
   values::PublicUrl,
 };
-use lemmy_db_schema::{
-  newtypes::CommunityId,
-  source::{community::Community, person::Person},
-  traits::Crud,
-};
+use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
@@ -60,10 +57,10 @@ impl From<&VoteType> for i16 {
 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
 #[serde(rename_all = "camelCase")]
 pub struct Vote {
-  actor: ObjectId<Person>,
+  actor: ObjectId<ApubPerson>,
   to: [PublicUrl; 1],
   pub(in crate::activities::voting) object: ObjectId<PostOrComment>,
-  cc: [ObjectId<Community>; 1],
+  cc: [ObjectId<ApubCommunity>; 1],
   #[serde(rename = "type")]
   pub(in crate::activities::voting) kind: VoteType,
   id: Url,
@@ -76,8 +73,8 @@ pub struct Vote {
 impl Vote {
   pub(in crate::activities::voting) fn new(
     object: &PostOrComment,
-    actor: &Person,
-    community: &Community,
+    actor: &ApubPerson,
+    community: &ApubCommunity,
     kind: VoteType,
     context: &LemmyContext,
   ) -> Result<Vote, LemmyError> {
@@ -95,7 +92,7 @@ impl Vote {
 
   pub async fn send(
     object: &PostOrComment,
-    actor: &Person,
+    actor: &ApubPerson,
     community_id: CommunityId,
     kind: VoteType,
     context: &LemmyContext,
@@ -103,7 +100,8 @@ impl Vote {
     let community = blocking(context.pool(), move |conn| {
       Community::read(conn, community_id)
     })
-    .await??;
+    .await??
+    .into();
     let vote = Vote::new(object, actor, &community, kind, context)?;
     let vote_id = vote.id.clone();
 
index 646f8fcad01497b7bb7941be5b432c95389bb3b7..aff571b709728e686c0bb5d9db4710c4caabcd0b 100644 (file)
@@ -1,17 +1,14 @@
 use crate::{
   activities::community::announce::AnnounceActivity,
   fetcher::{fetch::fetch_remote_object, object_id::ObjectId},
-  objects::community::Group,
+  objects::{community::Group, person::ApubPerson},
 };
 use activitystreams::collection::{CollectionExt, OrderedCollection};
 use anyhow::Context;
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{data::Data, traits::ActivityHandler};
 use lemmy_db_schema::{
-  source::{
-    community::{Community, CommunityModerator, CommunityModeratorForm},
-    person::Person,
-  },
+  source::community::{Community, CommunityModerator, CommunityModeratorForm},
   traits::Joinable,
 };
 use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
@@ -48,7 +45,7 @@ pub(crate) async fn update_community_mods(
   // Add new mods to database which have been added to moderators collection
   for mod_id in new_moderators {
     let mod_id = ObjectId::new(mod_id);
-    let mod_user: Person = mod_id.dereference(context, request_counter).await?;
+    let mod_user: ApubPerson = mod_id.dereference(context, request_counter).await?;
 
     if !current_moderators
       .clone()
index 641d59f02359edbba2c2e8af06374988371ad190..fd6b982c38811ba53385ed461ea6ab1620806b2c 100644 (file)
@@ -4,13 +4,13 @@ pub mod object_id;
 pub mod post_or_comment;
 pub mod search;
 
-use crate::fetcher::object_id::ObjectId;
+use crate::{
+  fetcher::object_id::ObjectId,
+  objects::{community::ApubCommunity, person::ApubPerson},
+};
 use chrono::NaiveDateTime;
 use lemmy_apub_lib::traits::ActorType;
-use lemmy_db_schema::{
-  naive_now,
-  source::{community::Community, person::Person},
-};
+use lemmy_db_schema::naive_now;
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
 use url::Url;
@@ -28,13 +28,13 @@ pub(crate) async fn get_or_fetch_and_upsert_actor(
   context: &LemmyContext,
   recursion_counter: &mut i32,
 ) -> Result<Box<dyn ActorType>, LemmyError> {
-  let community_id = ObjectId::<Community>::new(apub_id.clone());
+  let community_id = ObjectId::<ApubCommunity>::new(apub_id.clone());
   let community = community_id.dereference(context, recursion_counter).await;
   let actor: Box<dyn ActorType> = match community {
     Ok(c) => Box::new(c),
     Err(_) => {
       let person_id = ObjectId::new(apub_id);
-      let person: Person = person_id.dereference(context, recursion_counter).await?;
+      let person: ApubPerson = person_id.dereference(context, recursion_counter).await?;
       Box::new(person)
     }
   };
index 771c276a5a3210c3c0ac871da3c364f0f54fb210..4e439fb7fa862f16863ec423bc83572590b431fc 100644 (file)
@@ -1,9 +1,11 @@
-use crate::{fetcher::should_refetch_actor, objects::FromApub};
+use crate::fetcher::should_refetch_actor;
 use anyhow::anyhow;
-use diesel::{NotFound, PgConnection};
-use lemmy_api_common::blocking;
-use lemmy_apub_lib::{traits::ApubObject, APUB_JSON_CONTENT_TYPE};
-use lemmy_db_schema::{newtypes::DbUrl, DbPool};
+use diesel::NotFound;
+use lemmy_apub_lib::{
+  traits::{ApubObject, FromApub},
+  APUB_JSON_CONTENT_TYPE,
+};
+use lemmy_db_schema::newtypes::DbUrl;
 use lemmy_utils::{request::retry, settings::structs::Settings, LemmyError};
 use lemmy_websocket::LemmyContext;
 use reqwest::StatusCode;
@@ -22,12 +24,12 @@ static REQUEST_LIMIT: i32 = 25;
 #[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
 pub struct ObjectId<Kind>(Url, #[serde(skip)] PhantomData<Kind>)
 where
-  Kind: FromApub + ApubObject<DataType = PgConnection> + Send + 'static,
+  Kind: FromApub<DataType = LemmyContext> + ApubObject<DataType = LemmyContext> + Send + 'static,
   for<'de2> <Kind as FromApub>::ApubType: serde::Deserialize<'de2>;
 
 impl<Kind> ObjectId<Kind>
 where
-  Kind: FromApub + ApubObject<DataType = PgConnection> + Send + 'static,
+  Kind: FromApub<DataType = LemmyContext> + ApubObject<DataType = LemmyContext> + Send + 'static,
   for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
 {
   pub fn new<T>(url: T) -> Self
@@ -47,7 +49,7 @@ where
     context: &LemmyContext,
     request_counter: &mut i32,
   ) -> Result<Kind, LemmyError> {
-    let db_object = self.dereference_from_db(context.pool()).await?;
+    let db_object = self.dereference_from_db(context).await?;
 
     // if its a local object, only fetch it from the database and not over http
     if self.0.domain() == Some(&Settings::get().get_hostname_without_port()?) {
@@ -77,14 +79,14 @@ where
   /// Fetch an object from the local db. Instead of falling back to http, this throws an error if
   /// the object is not found in the database.
   pub async fn dereference_local(&self, context: &LemmyContext) -> Result<Kind, LemmyError> {
-    let object = self.dereference_from_db(context.pool()).await?;
+    let object = self.dereference_from_db(context).await?;
     object.ok_or_else(|| anyhow!("object not found in database {}", self).into())
   }
 
   /// returning none means the object was not found in local db
-  async fn dereference_from_db(&self, pool: &DbPool) -> Result<Option<Kind>, LemmyError> {
+  async fn dereference_from_db(&self, context: &LemmyContext) -> Result<Option<Kind>, LemmyError> {
     let id = self.0.clone();
-    blocking(pool, move |conn| ApubObject::read_from_apub_id(conn, id)).await?
+    ApubObject::read_from_apub_id(id, context).await
   }
 
   async fn dereference_from_http(
@@ -113,7 +115,7 @@ where
 
     if res.status() == StatusCode::GONE {
       if let Some(db_object) = db_object {
-        blocking(context.pool(), move |conn| db_object.delete(conn)).await??;
+        db_object.delete(context).await?;
       }
       return Err(anyhow!("Fetched remote object {} which was deleted", self).into());
     }
@@ -126,7 +128,7 @@ where
 
 impl<Kind> Display for ObjectId<Kind>
 where
-  Kind: FromApub + ApubObject<DataType = PgConnection> + Send + 'static,
+  Kind: FromApub<DataType = LemmyContext> + ApubObject<DataType = LemmyContext> + Send + 'static,
   for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
 {
   fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
@@ -136,7 +138,7 @@ where
 
 impl<Kind> From<ObjectId<Kind>> for Url
 where
-  Kind: FromApub + ApubObject<DataType = PgConnection> + Send + 'static,
+  Kind: FromApub<DataType = LemmyContext> + ApubObject<DataType = LemmyContext> + Send + 'static,
   for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
 {
   fn from(id: ObjectId<Kind>) -> Self {
@@ -146,7 +148,7 @@ where
 
 impl<Kind> From<ObjectId<Kind>> for DbUrl
 where
-  Kind: FromApub + ApubObject<DataType = PgConnection> + Send + 'static,
+  Kind: FromApub<DataType = LemmyContext> + ApubObject<DataType = LemmyContext> + Send + 'static,
   for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
 {
   fn from(id: ObjectId<Kind>) -> Self {
index 9d700c96043f40e83271718a8e962999113e8be1..fd78ad79ae49f1db06ef378cd898fe586eedb1c7 100644 (file)
@@ -1,11 +1,10 @@
-use crate::objects::{comment::Note, post::Page, FromApub};
-use activitystreams::chrono::NaiveDateTime;
-use diesel::PgConnection;
-use lemmy_apub_lib::traits::ApubObject;
-use lemmy_db_schema::source::{
-  comment::{Comment, CommentForm},
-  post::{Post, PostForm},
+use crate::objects::{
+  comment::{ApubComment, Note},
+  post::{ApubPost, Page},
 };
+use activitystreams::chrono::NaiveDateTime;
+use lemmy_apub_lib::traits::{ApubObject, FromApub};
+use lemmy_db_schema::source::{comment::CommentForm, post::PostForm};
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
@@ -13,8 +12,8 @@ use url::Url;
 
 #[derive(Clone, Debug)]
 pub enum PostOrComment {
-  Post(Box<Post>),
-  Comment(Comment),
+  Post(Box<ApubPost>),
+  Comment(ApubComment),
 }
 
 pub enum PostOrCommentForm {
@@ -31,28 +30,33 @@ pub enum PageOrNote {
 
 #[async_trait::async_trait(?Send)]
 impl ApubObject for PostOrComment {
-  type DataType = PgConnection;
+  type DataType = LemmyContext;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     None
   }
 
   // TODO: this can probably be implemented using a single sql query
-  fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, LemmyError>
+  async fn read_from_apub_id(
+    object_id: Url,
+    data: &Self::DataType,
+  ) -> Result<Option<Self>, LemmyError>
   where
     Self: Sized,
   {
-    let post = Post::read_from_apub_id(conn, object_id.clone())?;
+    let post = ApubPost::read_from_apub_id(object_id.clone(), data).await?;
     Ok(match post {
       Some(o) => Some(PostOrComment::Post(Box::new(o))),
-      None => Comment::read_from_apub_id(conn, object_id)?.map(PostOrComment::Comment),
+      None => ApubComment::read_from_apub_id(object_id, data)
+        .await?
+        .map(PostOrComment::Comment),
     })
   }
 
-  fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
+  async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
     match self {
-      PostOrComment::Post(p) => p.delete(data),
-      PostOrComment::Comment(c) => c.delete(data),
+      PostOrComment::Post(p) => p.delete(data).await,
+      PostOrComment::Comment(c) => c.delete(data).await,
     }
   }
 }
@@ -60,6 +64,7 @@ impl ApubObject for PostOrComment {
 #[async_trait::async_trait(?Send)]
 impl FromApub for PostOrComment {
   type ApubType = PageOrNote;
+  type DataType = LemmyContext;
 
   async fn from_apub(
     apub: &PageOrNote,
@@ -72,10 +77,10 @@ impl FromApub for PostOrComment {
   {
     Ok(match apub {
       PageOrNote::Page(p) => PostOrComment::Post(Box::new(
-        Post::from_apub(p, context, expected_domain, request_counter).await?,
+        ApubPost::from_apub(p, context, expected_domain, request_counter).await?,
       )),
       PageOrNote::Note(n) => PostOrComment::Comment(
-        Comment::from_apub(n, context, expected_domain, request_counter).await?,
+        ApubComment::from_apub(n, context, expected_domain, request_counter).await?,
       ),
     })
   }
index d7b9a0bfd4d4613e4f17b650154831f2cc685702..c67eaa0ff6a1d5195e2cf6becab8845748f09c3b 100644 (file)
@@ -1,18 +1,22 @@
 use crate::{
   fetcher::object_id::ObjectId,
-  objects::{comment::Note, community::Group, person::Person as ApubPerson, post::Page, FromApub},
+  objects::{
+    comment::{ApubComment, Note},
+    community::{ApubCommunity, Group},
+    person::{ApubPerson, Person},
+    post::{ApubPost, Page},
+  },
 };
 use activitystreams::chrono::NaiveDateTime;
 use anyhow::anyhow;
-use diesel::PgConnection;
 use itertools::Itertools;
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
-  traits::ApubObject,
+  traits::{ApubObject, FromApub},
   webfinger::{webfinger_resolve_actor, WebfingerType},
 };
 use lemmy_db_schema::{
-  source::{comment::Comment, community::Community, person::Person, post::Post},
+  source::{community::Community, person::Person as DbPerson},
   DbPool,
 };
 use lemmy_utils::LemmyError;
@@ -73,10 +77,14 @@ async fn find_local_actor_by_name(
   let name: String = name.into();
   Ok(match kind {
     WebfingerType::Group => SearchableObjects::Community(
-      blocking(pool, move |conn| Community::read_from_name(conn, &name)).await??,
+      blocking(pool, move |conn| Community::read_from_name(conn, &name))
+        .await??
+        .into(),
     ),
     WebfingerType::Person => SearchableObjects::Person(
-      blocking(pool, move |conn| Person::find_by_name(conn, &name)).await??,
+      blocking(pool, move |conn| DbPerson::find_by_name(conn, &name))
+        .await??
+        .into(),
     ),
   })
 }
@@ -84,23 +92,24 @@ async fn find_local_actor_by_name(
 /// The types of ActivityPub objects that can be fetched directly by searching for their ID.
 #[derive(Debug)]
 pub enum SearchableObjects {
-  Person(Person),
-  Community(Community),
-  Post(Post),
-  Comment(Comment),
+  Person(ApubPerson),
+  Community(ApubCommunity),
+  Post(ApubPost),
+  Comment(ApubComment),
 }
 
 #[derive(Deserialize)]
 #[serde(untagged)]
 pub enum SearchableApubTypes {
   Group(Group),
-  Person(ApubPerson),
+  Person(Person),
   Page(Page),
   Note(Note),
 }
 
+#[async_trait::async_trait(?Send)]
 impl ApubObject for SearchableObjects {
-  type DataType = PgConnection;
+  type DataType = LemmyContext;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     match self {
@@ -116,32 +125,35 @@ impl ApubObject for SearchableObjects {
   //       a single query.
   //       we could skip this and always return an error, but then it would always fetch objects
   //       over http, and not be able to mark objects as deleted that were deleted by remote server.
-  fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, LemmyError> {
-    let c = Community::read_from_apub_id(conn, object_id.clone())?;
+  async fn read_from_apub_id(
+    object_id: Url,
+    context: &LemmyContext,
+  ) -> Result<Option<Self>, LemmyError> {
+    let c = ApubCommunity::read_from_apub_id(object_id.clone(), context).await?;
     if let Some(c) = c {
       return Ok(Some(SearchableObjects::Community(c)));
     }
-    let p = Person::read_from_apub_id(conn, object_id.clone())?;
+    let p = ApubPerson::read_from_apub_id(object_id.clone(), context).await?;
     if let Some(p) = p {
       return Ok(Some(SearchableObjects::Person(p)));
     }
-    let p = Post::read_from_apub_id(conn, object_id.clone())?;
+    let p = ApubPost::read_from_apub_id(object_id.clone(), context).await?;
     if let Some(p) = p {
       return Ok(Some(SearchableObjects::Post(p)));
     }
-    let c = Comment::read_from_apub_id(conn, object_id)?;
+    let c = ApubComment::read_from_apub_id(object_id, context).await?;
     if let Some(c) = c {
       return Ok(Some(SearchableObjects::Comment(c)));
     }
     Ok(None)
   }
 
-  fn delete(self, conn: &Self::DataType) -> Result<(), LemmyError> {
+  async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
     match self {
-      SearchableObjects::Person(p) => p.delete(conn),
-      SearchableObjects::Community(c) => c.delete(conn),
-      SearchableObjects::Post(p) => p.delete(conn),
-      SearchableObjects::Comment(c) => c.delete(conn),
+      SearchableObjects::Person(p) => p.delete(data).await,
+      SearchableObjects::Community(c) => c.delete(data).await,
+      SearchableObjects::Post(p) => p.delete(data).await,
+      SearchableObjects::Comment(c) => c.delete(data).await,
     }
   }
 }
@@ -149,6 +161,7 @@ impl ApubObject for SearchableObjects {
 #[async_trait::async_trait(?Send)]
 impl FromApub for SearchableObjects {
   type ApubType = SearchableApubTypes;
+  type DataType = LemmyContext;
 
   async fn from_apub(
     apub: &Self::ApubType,
@@ -159,10 +172,10 @@ impl FromApub for SearchableObjects {
     use SearchableApubTypes as SAT;
     use SearchableObjects as SO;
     Ok(match apub {
-      SAT::Group(g) => SO::Community(Community::from_apub(g, context, ed, rc).await?),
-      SAT::Person(p) => SO::Person(Person::from_apub(p, context, ed, rc).await?),
-      SAT::Page(p) => SO::Post(Post::from_apub(p, context, ed, rc).await?),
-      SAT::Note(n) => SO::Comment(Comment::from_apub(n, context, ed, rc).await?),
+      SAT::Group(g) => SO::Community(ApubCommunity::from_apub(g, context, ed, rc).await?),
+      SAT::Person(p) => SO::Person(ApubPerson::from_apub(p, context, ed, rc).await?),
+      SAT::Page(p) => SO::Post(ApubPost::from_apub(p, context, ed, rc).await?),
+      SAT::Note(n) => SO::Comment(ApubComment::from_apub(n, context, ed, rc).await?),
     })
   }
 }
index 769a9dd85340f4fb9b1da69014ea5049f162fa7f..58543a5bb5f5ee2c18ade5f716e8cd9cd760561c 100644 (file)
@@ -1,10 +1,11 @@
 use crate::{
   http::{create_apub_response, create_apub_tombstone_response},
-  objects::ToApub,
+  objects::comment::ApubComment,
 };
 use actix_web::{body::Body, web, web::Path, HttpResponse};
 use diesel::result::Error::NotFound;
 use lemmy_api_common::blocking;
+use lemmy_apub_lib::traits::ToApub;
 use lemmy_db_schema::{newtypes::CommentId, source::comment::Comment, traits::Crud};
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -21,7 +22,9 @@ pub(crate) async fn get_apub_comment(
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse<Body>, LemmyError> {
   let id = CommentId(info.comment_id.parse::<i32>()?);
-  let comment = blocking(context.pool(), move |conn| Comment::read(conn, id)).await??;
+  let comment: ApubComment = blocking(context.pool(), move |conn| Comment::read(conn, id))
+    .await??
+    .into();
   if !comment.local {
     return Err(NotFound.into());
   }
index 2094d15d3918f934092b91f642ffc07d889ea68d..7c66ca9db7cf78d1d754f4439fc35ea51ec973d5 100644 (file)
@@ -14,7 +14,7 @@ use crate::{
     payload_to_string,
     receive_activity,
   },
-  objects::ToApub,
+  objects::community::ApubCommunity,
 };
 use activitystreams::{
   base::{AnyBase, BaseExt},
@@ -23,7 +23,7 @@ use activitystreams::{
 };
 use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
 use lemmy_api_common::blocking;
-use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler};
+use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler, ToApub};
 use lemmy_db_schema::source::{activity::Activity, community::Community};
 use lemmy_db_views_actor::{
   community_follower_view::CommunityFollowerView,
@@ -44,10 +44,11 @@ pub(crate) async fn get_apub_community_http(
   info: web::Path<CommunityQuery>,
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse<Body>, LemmyError> {
-  let community = blocking(context.pool(), move |conn| {
+  let community: ApubCommunity = blocking(context.pool(), move |conn| {
     Community::read_from_name(conn, &info.community_name)
   })
-  .await??;
+  .await??
+  .into();
 
   if !community.deleted {
     let apub = community.to_apub(context.pool()).await?;
@@ -173,10 +174,11 @@ pub(crate) async fn get_apub_community_moderators(
   info: web::Path<CommunityQuery>,
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse<Body>, LemmyError> {
-  let community = blocking(context.pool(), move |conn| {
+  let community: ApubCommunity = blocking(context.pool(), move |conn| {
     Community::read_from_name(conn, &info.community_name)
   })
-  .await??;
+  .await??
+  .into();
 
   // The attributed to, is an ordered vector with the creator actor_ids first,
   // then the rest of the moderators
index 36b6b7d9da59ca51c21884454e1e2ea9b8ab7aac..16f1bc5c47c11ffd4f0d23b0aa52524c8fc89d53 100644 (file)
@@ -16,7 +16,7 @@ use crate::{
     payload_to_string,
     receive_activity,
   },
-  objects::ToApub,
+  objects::person::ApubPerson,
 };
 use activitystreams::{
   base::BaseExt,
@@ -24,7 +24,7 @@ use activitystreams::{
 };
 use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
 use lemmy_api_common::blocking;
-use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler};
+use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler, ToApub};
 use lemmy_db_schema::source::person::Person;
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -44,10 +44,11 @@ pub(crate) async fn get_apub_person_http(
 ) -> Result<HttpResponse<Body>, LemmyError> {
   let user_name = info.into_inner().user_name;
   // TODO: this needs to be able to read deleted persons, so that it can send tombstones
-  let person = blocking(context.pool(), move |conn| {
+  let person: ApubPerson = blocking(context.pool(), move |conn| {
     Person::find_by_name(conn, &user_name)
   })
-  .await??;
+  .await??
+  .into();
 
   if !person.deleted {
     let apub = person.to_apub(context.pool()).await?;
index c5f22d01ccf5b2dda419efc40fd057a2840845c6..2ce712bc96ac531a944ce0ffd9f86ab38a08797d 100644 (file)
@@ -1,10 +1,11 @@
 use crate::{
   http::{create_apub_response, create_apub_tombstone_response},
-  objects::ToApub,
+  objects::post::ApubPost,
 };
 use actix_web::{body::Body, web, HttpResponse};
 use diesel::result::Error::NotFound;
 use lemmy_api_common::blocking;
+use lemmy_apub_lib::traits::ToApub;
 use lemmy_db_schema::{newtypes::PostId, source::post::Post, traits::Crud};
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -21,7 +22,9 @@ pub(crate) async fn get_apub_post(
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse<Body>, LemmyError> {
   let id = PostId(info.post_id.parse::<i32>()?);
-  let post = blocking(context.pool(), move |conn| Post::read(conn, id)).await??;
+  let post: ApubPost = blocking(context.pool(), move |conn| Post::read(conn, id))
+    .await??
+    .into();
   if !post.local {
     return Err(NotFound.into());
   }
index 1748af791a2216434a710472ed75428b357460c8..5745778c79bda95c8bcc7182a97c56fdb54c5b58 100644 (file)
@@ -3,11 +3,12 @@ use crate::{
   context::lemmy_context,
   fetcher::object_id::ObjectId,
   migrations::CommentInReplyToMigration,
-  objects::{create_tombstone, FromApub, Source, ToApub},
+  objects::{create_tombstone, person::ApubPerson, post::ApubPost, Source},
   PostOrComment,
 };
 use activitystreams::{
   base::AnyBase,
+  chrono::NaiveDateTime,
   object::{kind::NoteType, Tombstone},
   primitives::OneOrMany,
   unparsed::Unparsed,
@@ -16,7 +17,7 @@ use anyhow::{anyhow, Context};
 use chrono::{DateTime, FixedOffset};
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
-  traits::ActorType,
+  traits::{ApubObject, FromApub, ToApub},
   values::{MediaTypeHtml, MediaTypeMarkdown, PublicUrl},
   verify::verify_domains_match,
 };
@@ -50,7 +51,7 @@ pub struct Note {
   context: OneOrMany<AnyBase>,
   r#type: NoteType,
   id: Url,
-  pub(crate) attributed_to: ObjectId<Person>,
+  pub(crate) attributed_to: ObjectId<ApubPerson>,
   /// Indicates that the object is publicly readable. Unlike [`Post.to`], this one doesn't contain
   /// the community ID, as it would be incompatible with Pleroma (and we can get the community from
   /// the post in [`in_reply_to`]).
@@ -78,7 +79,7 @@ impl Note {
     &self,
     context: &LemmyContext,
     request_counter: &mut i32,
-  ) -> Result<(Post, Option<CommentId>), LemmyError> {
+  ) -> Result<(ApubPost, Option<CommentId>), LemmyError> {
     match &self.in_reply_to {
       CommentInReplyToMigration::Old(in_reply_to) => {
         // This post, or the parent comment might not yet exist on this server yet, fetch them.
@@ -90,7 +91,7 @@ impl Note {
         // Nested comments will automatically get fetched recursively
         let parent_id: Option<CommentId> = match in_reply_to.get(1) {
           Some(comment_id) => {
-            let comment_id = ObjectId::<Comment>::new(comment_id.clone());
+            let comment_id = ObjectId::<ApubComment>::new(comment_id.clone());
             let parent_comment = Box::pin(comment_id.dereference(context, request_counter)).await?;
 
             Some(parent_comment.id)
@@ -104,16 +105,16 @@ impl Note {
         let parent = Box::pin(in_reply_to.dereference(context, request_counter).await?);
         match parent.deref() {
           PostOrComment::Post(p) => {
-            // Workaround because I cant figure ut how to get the post out of the box (and we dont
+            // Workaround because I cant figure out how to get the post out of the box (and we dont
             // want to stackoverflow in a deep comment hierarchy).
             let post_id = p.id;
             let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
-            Ok((post, None))
+            Ok((post.into(), None))
           }
           PostOrComment::Comment(c) => {
             let post_id = c.post_id;
             let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
-            Ok((post, Some(c.id)))
+            Ok((post.into(), Some(c.id)))
           }
         }
       }
@@ -138,7 +139,7 @@ impl Note {
     verify_domains_match(self.attributed_to.inner(), &self.id)?;
     verify_person_in_community(
       &self.attributed_to,
-      &ObjectId::new(community.actor_id()),
+      &ObjectId::new(community.actor_id),
       context,
       request_counter,
     )
@@ -147,9 +148,57 @@ impl Note {
   }
 }
 
+#[derive(Clone, Debug)]
+pub struct ApubComment(Comment);
+
+impl Deref for ApubComment {
+  type Target = Comment;
+  fn deref(&self) -> &Self::Target {
+    &self.0
+  }
+}
+
+impl From<Comment> for ApubComment {
+  fn from(c: Comment) -> Self {
+    ApubComment { 0: c }
+  }
+}
+
+#[async_trait::async_trait(?Send)]
+impl ApubObject for ApubComment {
+  type DataType = LemmyContext;
+
+  fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
+    None
+  }
+
+  async fn read_from_apub_id(
+    object_id: Url,
+    context: &LemmyContext,
+  ) -> Result<Option<Self>, LemmyError> {
+    Ok(
+      blocking(context.pool(), move |conn| {
+        Comment::read_from_apub_id(conn, object_id)
+      })
+      .await??
+      .map(Into::into),
+    )
+  }
+
+  async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
+    blocking(context.pool(), move |conn| {
+      Comment::update_deleted(conn, self.id, true)
+    })
+    .await??;
+    Ok(())
+  }
+}
+
 #[async_trait::async_trait(?Send)]
-impl ToApub for Comment {
+impl ToApub for ApubComment {
   type ApubType = Note;
+  type TombstoneType = Tombstone;
+  type DataType = DbPool;
 
   async fn to_apub(&self, pool: &DbPool) -> Result<Note, LemmyError> {
     let creator_id = self.creator_id;
@@ -200,8 +249,9 @@ impl ToApub for Comment {
 }
 
 #[async_trait::async_trait(?Send)]
-impl FromApub for Comment {
+impl FromApub for ApubComment {
   type ApubType = Note;
+  type DataType = LemmyContext;
 
   /// Converts a `Note` to `Comment`.
   ///
@@ -211,7 +261,7 @@ impl FromApub for Comment {
     context: &LemmyContext,
     expected_domain: &Url,
     request_counter: &mut i32,
-  ) -> Result<Comment, LemmyError> {
+  ) -> Result<ApubComment, LemmyError> {
     let ap_id = Some(note.id(expected_domain)?.clone().into());
     let creator = note
       .attributed_to
@@ -238,6 +288,7 @@ impl FromApub for Comment {
       ap_id,
       local: Some(false),
     };
-    Ok(blocking(context.pool(), move |conn| Comment::upsert(conn, &form)).await??)
+    let comment = blocking(context.pool(), move |conn| Comment::upsert(conn, &form)).await??;
+    Ok(comment.into())
   }
 }
index 324ae259c88450c0c81b5a773b8f594169cf02c7..56a86cc85c5bdc384d95b9c86334d7e92b291583 100644 (file)
@@ -4,12 +4,13 @@ use crate::{
   fetcher::community::{fetch_community_outbox, update_community_mods},
   generate_moderators_url,
   generate_outbox_url,
-  objects::{create_tombstone, FromApub, ImageObject, Source, ToApub},
+  objects::{create_tombstone, ImageObject, Source},
   CommunityType,
 };
 use activitystreams::{
   actor::{kind::GroupType, Endpoints},
   base::AnyBase,
+  chrono::NaiveDateTime,
   object::{kind::ImageType, Tombstone},
   primitives::OneOrMany,
   unparsed::Unparsed,
@@ -19,7 +20,7 @@ use itertools::Itertools;
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
   signatures::PublicKey,
-  traits::ActorType,
+  traits::{ActorType, ApubObject, FromApub, ToApub},
   values::{MediaTypeHtml, MediaTypeMarkdown},
   verify::verify_domains_match,
 };
@@ -37,6 +38,7 @@ use lemmy_utils::{
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
+use std::ops::Deref;
 use url::Url;
 
 #[skip_serializing_none]
@@ -117,9 +119,83 @@ impl Group {
   }
 }
 
+#[derive(Clone, Debug)]
+pub struct ApubCommunity(Community);
+
+impl Deref for ApubCommunity {
+  type Target = Community;
+  fn deref(&self) -> &Self::Target {
+    &self.0
+  }
+}
+
+impl From<Community> for ApubCommunity {
+  fn from(c: Community) -> Self {
+    ApubCommunity { 0: c }
+  }
+}
+
+#[async_trait::async_trait(?Send)]
+impl ApubObject for ApubCommunity {
+  type DataType = LemmyContext;
+
+  fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
+    Some(self.last_refreshed_at)
+  }
+
+  async fn read_from_apub_id(
+    object_id: Url,
+    context: &LemmyContext,
+  ) -> Result<Option<Self>, LemmyError> {
+    Ok(
+      blocking(context.pool(), move |conn| {
+        Community::read_from_apub_id(conn, object_id)
+      })
+      .await??
+      .map(Into::into),
+    )
+  }
+
+  async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
+    blocking(context.pool(), move |conn| {
+      Community::update_deleted(conn, self.id, true)
+    })
+    .await??;
+    Ok(())
+  }
+}
+
+impl ActorType for ApubCommunity {
+  fn is_local(&self) -> bool {
+    self.local
+  }
+  fn actor_id(&self) -> Url {
+    self.actor_id.to_owned().into()
+  }
+  fn name(&self) -> String {
+    self.name.clone()
+  }
+  fn public_key(&self) -> Option<String> {
+    self.public_key.to_owned()
+  }
+  fn private_key(&self) -> Option<String> {
+    self.private_key.to_owned()
+  }
+
+  fn inbox_url(&self) -> Url {
+    self.inbox_url.clone().into()
+  }
+
+  fn shared_inbox_url(&self) -> Option<Url> {
+    self.shared_inbox_url.clone().map(|s| s.into_inner())
+  }
+}
+
 #[async_trait::async_trait(?Send)]
-impl ToApub for Community {
+impl ToApub for ApubCommunity {
   type ApubType = Group;
+  type TombstoneType = Tombstone;
+  type DataType = DbPool;
 
   async fn to_apub(&self, _pool: &DbPool) -> Result<Group, LemmyError> {
     let source = self.description.clone().map(|bio| Source {
@@ -174,8 +250,9 @@ impl ToApub for Community {
 }
 
 #[async_trait::async_trait(?Send)]
-impl FromApub for Community {
+impl FromApub for ApubCommunity {
   type ApubType = Group;
+  type DataType = LemmyContext;
 
   /// Converts a `Group` to `Community`, inserts it into the database and updates moderators.
   async fn from_apub(
@@ -183,7 +260,7 @@ impl FromApub for Community {
     context: &LemmyContext,
     expected_domain: &Url,
     request_counter: &mut i32,
-  ) -> Result<Community, LemmyError> {
+  ) -> Result<ApubCommunity, LemmyError> {
     let form = Group::from_apub_to_form(group, expected_domain, &context.settings()).await?;
 
     let community = blocking(context.pool(), move |conn| Community::upsert(conn, &form)).await??;
@@ -192,7 +269,7 @@ impl FromApub for Community {
     // TODO: doing this unconditionally might cause infinite loop for some reason
     fetch_community_outbox(context, &group.outbox, request_counter).await?;
 
-    Ok(community)
+    Ok(community.into())
   }
 }
 
index b558902faa427ea8486ea6c4bdc5b0d1a04f50c7..c5f20c2921088cb414cdea0e98c1afd9291fb80c 100644 (file)
@@ -5,43 +5,14 @@ use activitystreams::{
 use anyhow::anyhow;
 use chrono::NaiveDateTime;
 use lemmy_apub_lib::values::MediaTypeMarkdown;
-use lemmy_db_schema::DbPool;
 use lemmy_utils::{utils::convert_datetime, LemmyError};
-use lemmy_websocket::LemmyContext;
 use url::Url;
 
-pub(crate) mod comment;
-pub(crate) mod community;
-pub(crate) mod person;
-pub(crate) mod post;
-pub(crate) mod private_message;
-
-/// Trait for converting an object or actor into the respective ActivityPub type.
-#[async_trait::async_trait(?Send)]
-pub(crate) trait ToApub {
-  type ApubType;
-  async fn to_apub(&self, pool: &DbPool) -> Result<Self::ApubType, LemmyError>;
-  fn to_tombstone(&self) -> Result<Tombstone, LemmyError>;
-}
-
-#[async_trait::async_trait(?Send)]
-pub trait FromApub {
-  type ApubType;
-  /// Converts an object from ActivityPub type to Lemmy internal type.
-  ///
-  /// * `apub` The object to read from
-  /// * `context` LemmyContext which holds DB pool, HTTP client etc
-  /// * `expected_domain` Domain where the object was received from. None in case of mod action.
-  /// * `mod_action_allowed` True if the object can be a mod activity, ignore `expected_domain` in this case
-  async fn from_apub(
-    apub: &Self::ApubType,
-    context: &LemmyContext,
-    expected_domain: &Url,
-    request_counter: &mut i32,
-  ) -> Result<Self, LemmyError>
-  where
-    Self: Sized;
-}
+pub mod comment;
+pub mod community;
+pub mod person;
+pub mod post;
+pub mod private_message;
 
 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
 #[serde(rename_all = "camelCase")]
index 45c67f443533a1a2cc5877aaaad8e71e2df94d9c..53503d007ff2d5d323b962f767c4a31d99f509b4 100644 (file)
@@ -2,20 +2,21 @@ use crate::{
   check_is_apub_id_valid,
   context::lemmy_context,
   generate_outbox_url,
-  objects::{FromApub, ImageObject, Source, ToApub},
+  objects::{ImageObject, Source},
 };
 use activitystreams::{
   actor::Endpoints,
   base::AnyBase,
-  chrono::{DateTime, FixedOffset},
+  chrono::NaiveDateTime,
   object::{kind::ImageType, Tombstone},
   primitives::OneOrMany,
   unparsed::Unparsed,
 };
+use chrono::{DateTime, FixedOffset};
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
   signatures::PublicKey,
-  traits::ActorType,
+  traits::{ActorType, ApubObject, FromApub, ToApub},
   values::{MediaTypeHtml, MediaTypeMarkdown},
   verify::verify_domains_match,
 };
@@ -31,6 +32,7 @@ use lemmy_utils::{
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
+use std::ops::Deref;
 use url::Url;
 
 #[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
@@ -79,9 +81,85 @@ impl Person {
   }
 }
 
+#[derive(Clone, Debug)]
+pub struct ApubPerson(DbPerson);
+
+impl Deref for ApubPerson {
+  type Target = DbPerson;
+  fn deref(&self) -> &Self::Target {
+    &self.0
+  }
+}
+
+impl From<DbPerson> for ApubPerson {
+  fn from(p: DbPerson) -> Self {
+    ApubPerson { 0: p }
+  }
+}
+
 #[async_trait::async_trait(?Send)]
-impl ToApub for DbPerson {
+impl ApubObject for ApubPerson {
+  type DataType = LemmyContext;
+
+  fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
+    Some(self.last_refreshed_at)
+  }
+
+  async fn read_from_apub_id(
+    object_id: Url,
+    context: &LemmyContext,
+  ) -> Result<Option<Self>, LemmyError> {
+    Ok(
+      blocking(context.pool(), move |conn| {
+        DbPerson::read_from_apub_id(conn, object_id)
+      })
+      .await??
+      .map(Into::into),
+    )
+  }
+
+  async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
+    blocking(context.pool(), move |conn| {
+      DbPerson::update_deleted(conn, self.id, true)
+    })
+    .await??;
+    Ok(())
+  }
+}
+
+impl ActorType for ApubPerson {
+  fn is_local(&self) -> bool {
+    self.local
+  }
+  fn actor_id(&self) -> Url {
+    self.actor_id.to_owned().into_inner()
+  }
+  fn name(&self) -> String {
+    self.name.clone()
+  }
+
+  fn public_key(&self) -> Option<String> {
+    self.public_key.to_owned()
+  }
+
+  fn private_key(&self) -> Option<String> {
+    self.private_key.to_owned()
+  }
+
+  fn inbox_url(&self) -> Url {
+    self.inbox_url.clone().into()
+  }
+
+  fn shared_inbox_url(&self) -> Option<Url> {
+    self.shared_inbox_url.clone().map(|s| s.into_inner())
+  }
+}
+
+#[async_trait::async_trait(?Send)]
+impl ToApub for ApubPerson {
   type ApubType = Person;
+  type TombstoneType = Tombstone;
+  type DataType = DbPool;
 
   async fn to_apub(&self, _pool: &DbPool) -> Result<Person, LemmyError> {
     let kind = if self.bot_account {
@@ -133,15 +211,16 @@ impl ToApub for DbPerson {
 }
 
 #[async_trait::async_trait(?Send)]
-impl FromApub for DbPerson {
+impl FromApub for ApubPerson {
   type ApubType = Person;
+  type DataType = LemmyContext;
 
   async fn from_apub(
     person: &Person,
     context: &LemmyContext,
     expected_domain: &Url,
     _request_counter: &mut i32,
-  ) -> Result<DbPerson, LemmyError> {
+  ) -> Result<ApubPerson, LemmyError> {
     let actor_id = Some(person.id(expected_domain)?.clone().into());
     let name = person.preferred_username.clone();
     let display_name: Option<String> = person.name.clone();
@@ -184,6 +263,6 @@ impl FromApub for DbPerson {
       DbPerson::upsert(conn, &person_form)
     })
     .await??;
-    Ok(person)
+    Ok(person.into())
   }
 }
index bb301038072deec592e263b1635341f778aba150..dc6d965180383597b42360af48b768baa2649df9 100644 (file)
@@ -2,7 +2,7 @@ use crate::{
   activities::{extract_community, verify_person_in_community},
   context::lemmy_context,
   fetcher::object_id::ObjectId,
-  objects::{create_tombstone, FromApub, ImageObject, Source, ToApub},
+  objects::{create_tombstone, person::ApubPerson, ImageObject, Source},
 };
 use activitystreams::{
   base::AnyBase,
@@ -14,10 +14,10 @@ use activitystreams::{
   public,
   unparsed::Unparsed,
 };
-use chrono::{DateTime, FixedOffset};
+use chrono::{DateTime, FixedOffset, NaiveDateTime};
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
-  traits::ActorType,
+  traits::{ActorType, ApubObject, FromApub, ToApub},
   values::{MediaTypeHtml, MediaTypeMarkdown},
   verify::verify_domains_match,
 };
@@ -39,6 +39,7 @@ use lemmy_utils::{
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
+use std::ops::Deref;
 use url::Url;
 
 #[skip_serializing_none]
@@ -49,7 +50,7 @@ pub struct Page {
   context: OneOrMany<AnyBase>,
   r#type: PageType,
   id: Url,
-  pub(crate) attributed_to: ObjectId<Person>,
+  pub(crate) attributed_to: ObjectId<ApubPerson>,
   to: [Url; 2],
   name: String,
   content: Option<String>,
@@ -80,7 +81,7 @@ impl Page {
   ///
   /// Both stickied and locked need to be false on a newly created post (verified in [[CreatePost]].
   pub(crate) async fn is_mod_action(&self, context: &LemmyContext) -> Result<bool, LemmyError> {
-    let old_post = ObjectId::<Post>::new(self.id.clone())
+    let old_post = ObjectId::<ApubPost>::new(self.id.clone())
       .dereference_local(context)
       .await;
 
@@ -112,9 +113,57 @@ impl Page {
   }
 }
 
+#[derive(Clone, Debug)]
+pub struct ApubPost(Post);
+
+impl Deref for ApubPost {
+  type Target = Post;
+  fn deref(&self) -> &Self::Target {
+    &self.0
+  }
+}
+
+impl From<Post> for ApubPost {
+  fn from(p: Post) -> Self {
+    ApubPost { 0: p }
+  }
+}
+
+#[async_trait::async_trait(?Send)]
+impl ApubObject for ApubPost {
+  type DataType = LemmyContext;
+
+  fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
+    None
+  }
+
+  async fn read_from_apub_id(
+    object_id: Url,
+    context: &LemmyContext,
+  ) -> Result<Option<Self>, LemmyError> {
+    Ok(
+      blocking(context.pool(), move |conn| {
+        Post::read_from_apub_id(conn, object_id)
+      })
+      .await??
+      .map(Into::into),
+    )
+  }
+
+  async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
+    blocking(context.pool(), move |conn| {
+      Post::update_deleted(conn, self.id, true)
+    })
+    .await??;
+    Ok(())
+  }
+}
+
 #[async_trait::async_trait(?Send)]
-impl ToApub for Post {
+impl ToApub for ApubPost {
   type ApubType = Page;
+  type TombstoneType = Tombstone;
+  type DataType = DbPool;
 
   // Turn a Lemmy post into an ActivityPub page that can be sent out over the network.
   async fn to_apub(&self, pool: &DbPool) -> Result<Page, LemmyError> {
@@ -165,15 +214,16 @@ impl ToApub for Post {
 }
 
 #[async_trait::async_trait(?Send)]
-impl FromApub for Post {
+impl FromApub for ApubPost {
   type ApubType = Page;
+  type DataType = LemmyContext;
 
   async fn from_apub(
     page: &Page,
     context: &LemmyContext,
     expected_domain: &Url,
     request_counter: &mut i32,
-  ) -> Result<Post, LemmyError> {
+  ) -> Result<ApubPost, LemmyError> {
     // We can't verify the domain in case of mod action, because the mod may be on a different
     // instance from the post author.
     let ap_id = if page.is_mod_action(context).await? {
@@ -222,6 +272,7 @@ impl FromApub for Post {
       ap_id,
       local: Some(false),
     };
-    Ok(blocking(context.pool(), move |conn| Post::upsert(conn, &form)).await??)
+    let post = blocking(context.pool(), move |conn| Post::upsert(conn, &form)).await??;
+    Ok(post.into())
   }
 }
index 8cf40c9e46b8495e16ec90ae0b97595c7bef11c7..cde1966ed8228335443b9b765431fe4abc0ee781 100644 (file)
@@ -1,10 +1,11 @@
 use crate::{
   context::lemmy_context,
   fetcher::object_id::ObjectId,
-  objects::{create_tombstone, FromApub, Source, ToApub},
+  objects::{create_tombstone, person::ApubPerson, Source},
 };
 use activitystreams::{
   base::AnyBase,
+  chrono::NaiveDateTime,
   object::{kind::NoteType, Tombstone},
   primitives::OneOrMany,
   unparsed::Unparsed,
@@ -13,6 +14,7 @@ use anyhow::anyhow;
 use chrono::{DateTime, FixedOffset};
 use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
+  traits::{ApubObject, FromApub, ToApub},
   values::{MediaTypeHtml, MediaTypeMarkdown},
   verify::verify_domains_match,
 };
@@ -28,6 +30,7 @@ use lemmy_utils::{utils::convert_datetime, LemmyError};
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
+use std::ops::Deref;
 use url::Url;
 
 #[skip_serializing_none]
@@ -38,8 +41,8 @@ pub struct Note {
   context: OneOrMany<AnyBase>,
   r#type: NoteType,
   id: Url,
-  pub(crate) attributed_to: ObjectId<Person>,
-  to: ObjectId<Person>,
+  pub(crate) attributed_to: ObjectId<ApubPerson>,
+  to: ObjectId<ApubPerson>,
   content: String,
   media_type: MediaTypeHtml,
   source: Source,
@@ -75,9 +78,54 @@ impl Note {
   }
 }
 
+#[derive(Clone, Debug)]
+pub struct ApubPrivateMessage(PrivateMessage);
+
+impl Deref for ApubPrivateMessage {
+  type Target = PrivateMessage;
+  fn deref(&self) -> &Self::Target {
+    &self.0
+  }
+}
+
+impl From<PrivateMessage> for ApubPrivateMessage {
+  fn from(pm: PrivateMessage) -> Self {
+    ApubPrivateMessage { 0: pm }
+  }
+}
+
 #[async_trait::async_trait(?Send)]
-impl ToApub for PrivateMessage {
+impl ApubObject for ApubPrivateMessage {
+  type DataType = LemmyContext;
+
+  fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
+    None
+  }
+
+  async fn read_from_apub_id(
+    object_id: Url,
+    context: &LemmyContext,
+  ) -> Result<Option<Self>, LemmyError> {
+    Ok(
+      blocking(context.pool(), move |conn| {
+        PrivateMessage::read_from_apub_id(conn, object_id)
+      })
+      .await??
+      .map(Into::into),
+    )
+  }
+
+  async fn delete(self, _context: &LemmyContext) -> Result<(), LemmyError> {
+    // do nothing, because pm can't be fetched over http
+    unimplemented!()
+  }
+}
+
+#[async_trait::async_trait(?Send)]
+impl ToApub for ApubPrivateMessage {
   type ApubType = Note;
+  type TombstoneType = Tombstone;
+  type DataType = DbPool;
 
   async fn to_apub(&self, pool: &DbPool) -> Result<Note, LemmyError> {
     let creator_id = self.creator_id;
@@ -116,15 +164,16 @@ impl ToApub for PrivateMessage {
 }
 
 #[async_trait::async_trait(?Send)]
-impl FromApub for PrivateMessage {
+impl FromApub for ApubPrivateMessage {
   type ApubType = Note;
+  type DataType = LemmyContext;
 
   async fn from_apub(
     note: &Note,
     context: &LemmyContext,
     expected_domain: &Url,
     request_counter: &mut i32,
-  ) -> Result<PrivateMessage, LemmyError> {
+  ) -> Result<ApubPrivateMessage, LemmyError> {
     let ap_id = Some(note.id(expected_domain)?.clone().into());
     let creator = note
       .attributed_to
@@ -143,11 +192,10 @@ impl FromApub for PrivateMessage {
       ap_id,
       local: Some(false),
     };
-    Ok(
-      blocking(context.pool(), move |conn| {
-        PrivateMessage::upsert(conn, &form)
-      })
-      .await??,
-    )
+    let pm = blocking(context.pool(), move |conn| {
+      PrivateMessage::upsert(conn, &form)
+    })
+    .await??;
+    Ok(pm.into())
   }
 }
index 16fb3f8e3c9c890bac7117a33422d0be0dde576a..c2c1d02a3f50142c2de5a6f8a415e8fa825a86af 100644 (file)
@@ -27,17 +27,21 @@ pub trait ActivityHandler {
   ) -> Result<(), LemmyError>;
 }
 
+#[async_trait::async_trait(?Send)]
 pub trait ApubObject {
   type DataType;
   /// If this object should be refetched after a certain interval, it should return the last refresh
   /// time here. This is mainly used to update remote actors.
   fn last_refreshed_at(&self) -> Option<NaiveDateTime>;
   /// Try to read the object with given ID from local database. Returns Ok(None) if it doesn't exist.
-  fn read_from_apub_id(data: &Self::DataType, object_id: Url) -> Result<Option<Self>, LemmyError>
+  async fn read_from_apub_id(
+    object_id: Url,
+    data: &Self::DataType,
+  ) -> Result<Option<Self>, LemmyError>
   where
     Self: Sized;
   /// Marks the object as deleted in local db. Called when a tombstone is received.
-  fn delete(self, data: &Self::DataType) -> Result<(), LemmyError>;
+  async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError>;
 }
 
 /// Common methods provided by ActivityPub actors (community and person). Not all methods are
@@ -67,3 +71,35 @@ pub trait ActorType {
     })
   }
 }
+
+/// Trait for converting an object or actor into the respective ActivityPub type.
+#[async_trait::async_trait(?Send)]
+pub trait ToApub {
+  type ApubType;
+  type TombstoneType;
+  type DataType;
+
+  async fn to_apub(&self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError>;
+  fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError>;
+}
+
+#[async_trait::async_trait(?Send)]
+pub trait FromApub {
+  type ApubType;
+  type DataType;
+
+  /// Converts an object from ActivityPub type to Lemmy internal type.
+  ///
+  /// * `apub` The object to read from
+  /// * `context` LemmyContext which holds DB pool, HTTP client etc
+  /// * `expected_domain` Domain where the object was received from. None in case of mod action.
+  /// * `mod_action_allowed` True if the object can be a mod activity, ignore `expected_domain` in this case
+  async fn from_apub(
+    apub: &Self::ApubType,
+    data: &Self::DataType,
+    expected_domain: &Url,
+    request_counter: &mut i32,
+  ) -> Result<Self, LemmyError>
+  where
+    Self: Sized;
+}
index a05aed47df15d3baf87396ec870e7ea877bbd185..dc53d82bda79a4bb66a46c3e75ca2da7050ceac1 100644 (file)
@@ -12,7 +12,6 @@ doctest = false
 
 [dependencies]
 lemmy_utils = { version = "=0.13.0", path = "../utils" }
-lemmy_apub_lib = { version = "=0.13.0", path = "../apub_lib" }
 diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"] }
 diesel_migrations = "1.4.0"
 chrono = { version = "0.4.19", features = ["serde"] }
index aa7e25b28bfa07cf56ad2b978c134fad39f32ce2..09389aad81f4c909ec84d96e4917e31d933704fe 100644 (file)
@@ -11,10 +11,7 @@ use crate::{
   },
   traits::{Crud, DeleteableOrRemoveable, Likeable, Saveable},
 };
-use chrono::NaiveDateTime;
 use diesel::{dsl::*, result::Error, *};
-use lemmy_apub_lib::traits::ApubObject;
-use lemmy_utils::LemmyError;
 use url::Url;
 
 impl Comment {
@@ -108,6 +105,17 @@ impl Comment {
       .set(comment_form)
       .get_result::<Self>(conn)
   }
+  pub fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
+    use crate::schema::comment::dsl::*;
+    let object_id: DbUrl = object_id.into();
+    Ok(
+      comment
+        .filter(ap_id.eq(object_id))
+        .first::<Comment>(conn)
+        .ok()
+        .map(Into::into),
+    )
+  }
 }
 
 impl Crud for Comment {
@@ -198,25 +206,6 @@ impl DeleteableOrRemoveable for Comment {
   }
 }
 
-impl ApubObject for Comment {
-  type DataType = PgConnection;
-
-  fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
-    None
-  }
-
-  fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, LemmyError> {
-    use crate::schema::comment::dsl::*;
-    let object_id: DbUrl = object_id.into();
-    Ok(comment.filter(ap_id.eq(object_id)).first::<Self>(conn).ok())
-  }
-
-  fn delete(self, conn: &PgConnection) -> Result<(), LemmyError> {
-    Comment::update_deleted(conn, self.id, true)?;
-    Ok(())
-  }
-}
-
 #[cfg(test)]
 mod tests {
   use crate::{
index 8acce790cd3f7ff50efab572aeea70c03d01c441..b2ebb3a0a2294386306a0eeaccbf5afa2f5d55e0 100644 (file)
@@ -14,10 +14,7 @@ use crate::{
   },
   traits::{Bannable, Crud, DeleteableOrRemoveable, Followable, Joinable},
 };
-use chrono::NaiveDateTime;
 use diesel::{dsl::*, result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
-use lemmy_apub_lib::traits::{ActorType, ApubObject};
-use lemmy_utils::LemmyError;
 use url::Url;
 
 mod safe_type {
@@ -148,6 +145,17 @@ impl Community {
       .set(community_form)
       .get_result::<Self>(conn)
   }
+  pub fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
+    use crate::schema::community::dsl::*;
+    let object_id: DbUrl = object_id.into();
+    Ok(
+      community
+        .filter(actor_id.eq(object_id))
+        .first::<Community>(conn)
+        .ok()
+        .map(Into::into),
+    )
+  }
 }
 
 impl Joinable for CommunityModerator {
@@ -297,59 +305,6 @@ impl Followable for CommunityFollower {
   }
 }
 
-impl ApubObject for Community {
-  type DataType = PgConnection;
-
-  fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
-    Some(self.last_refreshed_at)
-  }
-
-  fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, LemmyError> {
-    use crate::schema::community::dsl::*;
-    let object_id: DbUrl = object_id.into();
-    Ok(
-      community
-        .filter(actor_id.eq(object_id))
-        .first::<Self>(conn)
-        .ok(),
-    )
-  }
-
-  fn delete(self, conn: &PgConnection) -> Result<(), LemmyError> {
-    use crate::schema::community::dsl::*;
-    diesel::update(community.find(self.id))
-      .set((deleted.eq(true), updated.eq(naive_now())))
-      .get_result::<Self>(conn)?;
-    Ok(())
-  }
-}
-
-impl ActorType for Community {
-  fn is_local(&self) -> bool {
-    self.local
-  }
-  fn actor_id(&self) -> Url {
-    self.actor_id.to_owned().into()
-  }
-  fn name(&self) -> String {
-    self.name.clone()
-  }
-  fn public_key(&self) -> Option<String> {
-    self.public_key.to_owned()
-  }
-  fn private_key(&self) -> Option<String> {
-    self.private_key.to_owned()
-  }
-
-  fn inbox_url(&self) -> Url {
-    self.inbox_url.clone().into()
-  }
-
-  fn shared_inbox_url(&self) -> Option<Url> {
-    self.shared_inbox_url.clone().map(|s| s.into_inner())
-  }
-}
-
 #[cfg(test)]
 mod tests {
   use crate::{
index 5b7cb941687d788ea1295fd7402ed1b11a6c7c9c..a9ba1d2e960a47e784a4831becf030723ff76740 100644 (file)
@@ -5,10 +5,7 @@ use crate::{
   source::person::{Person, PersonForm},
   traits::Crud,
 };
-use chrono::NaiveDateTime;
 use diesel::{dsl::*, result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl, *};
-use lemmy_apub_lib::traits::{ActorType, ApubObject};
-use lemmy_utils::LemmyError;
 use url::Url;
 
 mod safe_type {
@@ -237,61 +234,29 @@ impl Person {
       .set(person_form)
       .get_result::<Self>(conn)
   }
-}
-
-impl ApubObject for Person {
-  type DataType = PgConnection;
 
-  fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
-    Some(self.last_refreshed_at)
-  }
-
-  fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, LemmyError> {
+  pub fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
     use crate::schema::person::dsl::*;
     let object_id: DbUrl = object_id.into();
     Ok(
       person
         .filter(deleted.eq(false))
         .filter(actor_id.eq(object_id))
-        .first::<Self>(conn)
-        .ok(),
+        .first::<Person>(conn)
+        .ok()
+        .map(Into::into),
     )
   }
 
-  fn delete(self, conn: &PgConnection) -> Result<(), LemmyError> {
+  pub fn update_deleted(
+    conn: &PgConnection,
+    person_id: PersonId,
+    new_deleted: bool,
+  ) -> Result<Person, Error> {
     use crate::schema::person::dsl::*;
-    diesel::update(person.find(self.id))
-      .set((deleted.eq(true), updated.eq(naive_now())))
-      .get_result::<Self>(conn)?;
-    Ok(())
-  }
-}
-
-impl ActorType for Person {
-  fn is_local(&self) -> bool {
-    self.local
-  }
-  fn actor_id(&self) -> Url {
-    self.actor_id.to_owned().into_inner()
-  }
-  fn name(&self) -> String {
-    self.name.clone()
-  }
-
-  fn public_key(&self) -> Option<String> {
-    self.public_key.to_owned()
-  }
-
-  fn private_key(&self) -> Option<String> {
-    self.private_key.to_owned()
-  }
-
-  fn inbox_url(&self) -> Url {
-    self.inbox_url.clone().into()
-  }
-
-  fn shared_inbox_url(&self) -> Option<Url> {
-    self.shared_inbox_url.clone().map(|s| s.into_inner())
+    diesel::update(person.find(person_id))
+      .set(deleted.eq(new_deleted))
+      .get_result::<Self>(conn)
   }
 }
 
index 2b71c663f4bb500c5e4a662e30b3b812521f4b15..c1f0fcbf231279abf6bb607e5a4b2f72fbbe6844 100644 (file)
@@ -13,10 +13,7 @@ use crate::{
   },
   traits::{Crud, DeleteableOrRemoveable, Likeable, Readable, Saveable},
 };
-use chrono::NaiveDateTime;
 use diesel::{dsl::*, result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
-use lemmy_apub_lib::traits::ApubObject;
-use lemmy_utils::LemmyError;
 use url::Url;
 
 impl Crud for Post {
@@ -164,6 +161,17 @@ impl Post {
       .set(post_form)
       .get_result::<Self>(conn)
   }
+  pub fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
+    use crate::schema::post::dsl::*;
+    let object_id: DbUrl = object_id.into();
+    Ok(
+      post
+        .filter(ap_id.eq(object_id))
+        .first::<Post>(conn)
+        .ok()
+        .map(Into::into),
+    )
+  }
 }
 
 impl Likeable for PostLike {
@@ -248,28 +256,6 @@ impl DeleteableOrRemoveable for Post {
   }
 }
 
-impl ApubObject for Post {
-  type DataType = PgConnection;
-
-  fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
-    None
-  }
-
-  fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, LemmyError> {
-    use crate::schema::post::dsl::*;
-    let object_id: DbUrl = object_id.into();
-    Ok(post.filter(ap_id.eq(object_id)).first::<Self>(conn).ok())
-  }
-
-  fn delete(self, conn: &PgConnection) -> Result<(), LemmyError> {
-    use crate::schema::post::dsl::*;
-    diesel::update(post.find(self.id))
-      .set((deleted.eq(true), updated.eq(naive_now())))
-      .get_result::<Self>(conn)?;
-    Ok(())
-  }
-}
-
 #[cfg(test)]
 mod tests {
   use crate::{
index f252a0c031ccbb8342595722db0d6bb5fc44cc68..735c775e00fe3fe55457e52329e8319fded12555 100644 (file)
@@ -4,9 +4,7 @@ use crate::{
   source::private_message::*,
   traits::{Crud, DeleteableOrRemoveable},
 };
-use chrono::NaiveDateTime;
 use diesel::{dsl::*, result::Error, *};
-use lemmy_apub_lib::traits::ApubObject;
 use lemmy_utils::LemmyError;
 use url::Url;
 
@@ -109,36 +107,27 @@ impl PrivateMessage {
       .set(private_message_form)
       .get_result::<Self>(conn)
   }
-}
-
-impl DeleteableOrRemoveable for PrivateMessage {
-  fn blank_out_deleted_or_removed_info(mut self) -> Self {
-    self.content = "".into();
-    self
-  }
-}
-
-impl ApubObject for PrivateMessage {
-  type DataType = PgConnection;
 
-  fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
-    None
-  }
-
-  fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, LemmyError> {
+  pub fn read_from_apub_id(
+    conn: &PgConnection,
+    object_id: Url,
+  ) -> Result<Option<Self>, LemmyError> {
     use crate::schema::private_message::dsl::*;
     let object_id: DbUrl = object_id.into();
     Ok(
       private_message
         .filter(ap_id.eq(object_id))
-        .first::<Self>(conn)
-        .ok(),
+        .first::<PrivateMessage>(conn)
+        .ok()
+        .map(Into::into),
     )
   }
+}
 
-  fn delete(self, _conn: &PgConnection) -> Result<(), LemmyError> {
-    // do nothing, because pm can't be fetched over http
-    unimplemented!()
+impl DeleteableOrRemoveable for PrivateMessage {
+  fn blank_out_deleted_or_removed_info(mut self) -> Self {
+    self.content = "".into();
+    self
   }
 }
 
index 5982e24cea50308249b94271051219159ef8f9ba..95780c3299c96beab9764e9be808d3c1a08fb409 100644 (file)
@@ -12,7 +12,13 @@ use lemmy_api_common::{
 };
 use lemmy_db_schema::{
   newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId, PrivateMessageId},
-  traits::DeleteableOrRemoveable,
+  source::{
+    comment::Comment,
+    person::Person,
+    person_mention::{PersonMention, PersonMentionForm},
+    post::Post,
+  },
+  traits::{Crud, DeleteableOrRemoveable},
 };
 use lemmy_db_views::{
   comment_view::CommentView,
@@ -21,7 +27,14 @@ use lemmy_db_views::{
   private_message_view::PrivateMessageView,
 };
 use lemmy_db_views_actor::community_view::CommunityView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{
+  email::send_email,
+  settings::structs::Settings,
+  utils::MentionData,
+  ConnectionId,
+  LemmyError,
+};
+use log::error;
 
 pub async fn send_post_ws_message<OP: ToString + Send + OperationType + 'static>(
   post_id: PostId,
@@ -167,3 +180,149 @@ pub async fn send_pm_ws_message<OP: ToString + Send + OperationType + 'static>(
 
   Ok(res)
 }
+
+pub async fn send_local_notifs(
+  mentions: Vec<MentionData>,
+  comment: &Comment,
+  person: &Person,
+  post: &Post,
+  do_send_email: bool,
+  context: &LemmyContext,
+) -> Result<Vec<LocalUserId>, LemmyError> {
+  let mut recipient_ids = Vec::new();
+
+  // Send the local mentions
+  for mention in mentions
+    .iter()
+    .filter(|m| m.is_local(&context.settings().hostname) && m.name.ne(&person.name))
+    .collect::<Vec<&MentionData>>()
+  {
+    let mention_name = mention.name.clone();
+    let user_view = blocking(context.pool(), move |conn| {
+      LocalUserView::read_from_name(conn, &mention_name)
+    })
+    .await?;
+    if let Ok(mention_user_view) = user_view {
+      // TODO
+      // At some point, make it so you can't tag the parent creator either
+      // This can cause two notifications, one for reply and the other for mention
+      recipient_ids.push(mention_user_view.local_user.id);
+
+      let user_mention_form = PersonMentionForm {
+        recipient_id: mention_user_view.person.id,
+        comment_id: comment.id,
+        read: None,
+      };
+
+      // Allow this to fail softly, since comment edits might re-update or replace it
+      // Let the uniqueness handle this fail
+      blocking(context.pool(), move |conn| {
+        PersonMention::create(conn, &user_mention_form)
+      })
+      .await?
+      .ok();
+
+      // Send an email to those local users that have notifications on
+      if do_send_email {
+        send_email_to_user(
+          &mention_user_view,
+          "Mentioned by",
+          "Person Mention",
+          &comment.content,
+          &context.settings(),
+        )
+      }
+    }
+  }
+
+  // Send notifs to the parent commenter / poster
+  match comment.parent_id {
+    Some(parent_id) => {
+      let parent_comment =
+        blocking(context.pool(), move |conn| Comment::read(conn, parent_id)).await?;
+      if let Ok(parent_comment) = parent_comment {
+        // Don't send a notif to yourself
+        if parent_comment.creator_id != person.id {
+          // Get the parent commenter local_user
+          let user_view = blocking(context.pool(), move |conn| {
+            LocalUserView::read_person(conn, parent_comment.creator_id)
+          })
+          .await?;
+          if let Ok(parent_user_view) = user_view {
+            recipient_ids.push(parent_user_view.local_user.id);
+
+            if do_send_email {
+              send_email_to_user(
+                &parent_user_view,
+                "Reply from",
+                "Comment Reply",
+                &comment.content,
+                &context.settings(),
+              )
+            }
+          }
+        }
+      }
+    }
+    // Its a post
+    None => {
+      if post.creator_id != person.id {
+        let creator_id = post.creator_id;
+        let parent_user = blocking(context.pool(), move |conn| {
+          LocalUserView::read_person(conn, creator_id)
+        })
+        .await?;
+        if let Ok(parent_user_view) = parent_user {
+          recipient_ids.push(parent_user_view.local_user.id);
+
+          if do_send_email {
+            send_email_to_user(
+              &parent_user_view,
+              "Reply from",
+              "Post Reply",
+              &comment.content,
+              &context.settings(),
+            )
+          }
+        }
+      }
+    }
+  };
+  Ok(recipient_ids)
+}
+
+pub fn send_email_to_user(
+  local_user_view: &LocalUserView,
+  subject_text: &str,
+  body_text: &str,
+  comment_content: &str,
+  settings: &Settings,
+) {
+  if local_user_view.person.banned || !local_user_view.local_user.send_notifications_to_email {
+    return;
+  }
+
+  if let Some(user_email) = &local_user_view.local_user.email {
+    let subject = &format!(
+      "{} - {} {}",
+      subject_text, settings.hostname, local_user_view.person.name,
+    );
+    let html = &format!(
+      "<h1>{}</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
+      body_text,
+      local_user_view.person.name,
+      comment_content,
+      settings.get_protocol_and_hostname()
+    );
+    match send_email(
+      subject,
+      user_email,
+      &local_user_view.person.name,
+      html,
+      settings,
+    ) {
+      Ok(_o) => _o,
+      Err(e) => error!("{}", e),
+    };
+  }
+}