Refactoring apub code
authorFelix Ableitner <me@nutomic.com>
Wed, 3 Nov 2021 16:26:09 +0000 (17:26 +0100)
committerFelix Ableitner <me@nutomic.com>
Fri, 5 Nov 2021 20:12:10 +0000 (21:12 +0100)
13 files changed:
crates/apub/src/activities/comment/create_or_update.rs
crates/apub/src/activities/post/create_or_update.rs
crates/apub/src/activities/private_message/create_or_update.rs
crates/apub/src/objects/comment.rs
crates/apub/src/objects/community.rs
crates/apub/src/objects/person.rs
crates/apub/src/objects/post.rs
crates/apub/src/objects/private_message.rs
crates/apub/src/protocol/objects/chat_message.rs
crates/apub/src/protocol/objects/group.rs
crates/apub/src/protocol/objects/note.rs
crates/apub/src/protocol/objects/page.rs
crates/apub/src/protocol/objects/person.rs

index a9c1a9ee8a5bb63c707071962624709c0fc38039..10666932e942bd4cad7cd8b8eff4f1a4c19a8e97 100644 (file)
@@ -83,7 +83,7 @@ impl ActivityHandler for CreateOrUpdateComment {
 
     verify_activity(self, &context.settings())?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
-    verify_domains_match(self.actor.inner(), self.object.id_unchecked())?;
+    verify_domains_match(self.actor.inner(), self.object.id.inner())?;
     check_community_deleted_or_removed(&community)?;
     check_post_deleted_or_removed(&post)?;
 
index 41590493c6bc0d4c37fb43f106051d1e2ab74ddd..677ce2dc14ee25c1cb4a5518320af17ec884e13f 100644 (file)
@@ -84,7 +84,7 @@ impl ActivityHandler for CreateOrUpdatePost {
 
     match self.kind {
       CreateOrUpdateType::Create => {
-        verify_domains_match(self.actor.inner(), self.object.id_unchecked())?;
+        verify_domains_match(self.actor.inner(), self.object.id.inner())?;
         verify_urls_match(self.actor(), self.object.attributed_to.inner())?;
         // Check that the post isnt locked or stickied, as that isnt possible for newly created posts.
         // However, when fetching a remote post we generate a new create activity with the current
@@ -101,7 +101,7 @@ impl ActivityHandler for CreateOrUpdatePost {
         if is_mod_action {
           verify_mod_action(&self.actor, &community, context, request_counter).await?;
         } else {
-          verify_domains_match(self.actor.inner(), self.object.id_unchecked())?;
+          verify_domains_match(self.actor.inner(), self.object.id.inner())?;
           verify_urls_match(self.actor(), self.object.attributed_to.inner())?;
         }
       }
index cfd7c8bcfb7f3b2545cce9413bc9da253b5fcfe1..e441718ab47ff871ef8030b37d042a566a1890ec 100644 (file)
@@ -56,7 +56,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage {
   ) -> Result<(), LemmyError> {
     verify_activity(self, &context.settings())?;
     verify_person(&self.actor, context, request_counter).await?;
-    verify_domains_match(self.actor.inner(), self.object.id_unchecked())?;
+    verify_domains_match(self.actor.inner(), self.object.id.inner())?;
     self.object.verify(context, request_counter).await?;
     Ok(())
   }
index 08a55bf9cd8bdbd603bcaa89be4b41f0f578ca16..68240728a670712c2523749c39a63fffda9aa395 100644 (file)
@@ -39,6 +39,7 @@ use crate::{
   },
   PostOrComment,
 };
+use lemmy_apub_lib::verify::verify_domains_match;
 use lemmy_utils::utils::markdown_to_html;
 
 #[derive(Clone, Debug)]
@@ -107,7 +108,7 @@ impl ApubObject for ApubComment {
 
     let note = Note {
       r#type: NoteType::Note,
-      id: self.ap_id.to_owned().into_inner(),
+      id: ObjectId::new(self.ap_id.to_owned()),
       attributed_to: ObjectId::new(creator.actor_id),
       to: vec![public()],
       content: markdown_to_html(&self.content),
@@ -141,7 +142,8 @@ impl ApubObject for ApubComment {
     expected_domain: &Url,
     request_counter: &mut i32,
   ) -> Result<ApubComment, LemmyError> {
-    let ap_id = Some(note.id(expected_domain)?.clone().into());
+    verify_domains_match(note.id.inner(), expected_domain)?;
+    let ap_id = Some(note.id.clone().into());
     let creator = note
       .attributed_to
       .dereference(context, request_counter)
@@ -152,7 +154,7 @@ impl ApubObject for ApubComment {
       Community::read(conn, community_id)
     })
     .await??;
-    check_is_apub_id_valid(&note.id, community.local, &context.settings())?;
+    check_is_apub_id_valid(note.id.inner(), community.local, &context.settings())?;
     verify_person_in_community(
       &note.attributed_to,
       &community.into(),
index 0947ebf371a8afd017fefbfd7780e3e2e0700b5b..8fd245dc231a271c512ce1b075b528e499d38f85 100644 (file)
@@ -96,7 +96,7 @@ impl ApubObject for ApubCommunity {
 
     let group = Group {
       kind: GroupType::Group,
-      id: self.actor_id(),
+      id: ObjectId::new(self.actor_id()),
       preferred_username: self.name.clone(),
       name: self.title.clone(),
       summary: self.description.as_ref().map(|b| markdown_to_html(b)),
index 18522e569b792c6c53835322d30a31af1d97218d..652ef62205469717785850940225c93abf0ed755 100644 (file)
@@ -1,5 +1,6 @@
 use crate::{
   check_is_apub_id_valid,
+  fetcher::object_id::ObjectId,
   generate_outbox_url,
   objects::get_summary_from_string_or_source,
   protocol::{
@@ -96,7 +97,7 @@ impl ApubObject for ApubPerson {
 
     let person = Person {
       kind,
-      id: self.actor_id.to_owned().into_inner(),
+      id: ObjectId::new(self.actor_id.clone()),
       preferred_username: self.name.clone(),
       name: self.display_name.clone(),
       summary: self.bio.as_ref().map(|b| markdown_to_html(b)),
@@ -128,7 +129,7 @@ impl ApubObject for ApubPerson {
     expected_domain: &Url,
     _request_counter: &mut i32,
   ) -> Result<ApubPerson, LemmyError> {
-    verify_domains_match(&person.id, expected_domain)?;
+    verify_domains_match(person.id.inner(), expected_domain)?;
     let actor_id = Some(person.id.clone().into());
     let name = person.preferred_username.clone();
     let display_name: Option<String> = person.name.clone();
@@ -144,7 +145,7 @@ impl ApubObject for ApubPerson {
     check_slurs_opt(&display_name, slur_regex)?;
     check_slurs_opt(&bio, slur_regex)?;
 
-    check_is_apub_id_valid(&person.id, false, &context.settings())?;
+    check_is_apub_id_valid(person.id.inner(), false, &context.settings())?;
 
     let person_form = PersonForm {
       name,
index b835f812eaecdb9aa1b1fc789e82a3e1c42f3724..b29bdb8017516b88727c4534a594d928b0cbe8ab 100644 (file)
@@ -17,6 +17,7 @@ use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
   traits::ApubObject,
   values::{MediaTypeHtml, MediaTypeMarkdown},
+  verify::verify_domains_match,
 };
 use lemmy_db_schema::{
   self,
@@ -106,7 +107,7 @@ impl ApubObject for ApubPost {
 
     let page = Page {
       r#type: PageType::Page,
-      id: self.ap_id.clone().into(),
+      id: ObjectId::new(self.ap_id.clone()),
       attributed_to: ObjectId::new(creator.actor_id),
       to: vec![community.actor_id.into(), public()],
       name: self.name.clone(),
@@ -140,18 +141,16 @@ impl ApubObject for ApubPost {
   ) -> 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? {
-      page.id_unchecked()
-    } else {
-      page.id(expected_domain)?
+    if !page.is_mod_action(context).await? {
+      verify_domains_match(page.id.inner(), expected_domain)?;
     };
-    let ap_id = Some(ap_id.clone().into());
+    let ap_id = Some(page.id.clone().into());
     let creator = page
       .attributed_to
       .dereference(context, request_counter)
       .await?;
     let community = page.extract_community(context, request_counter).await?;
-    check_is_apub_id_valid(&page.id, community.local, &context.settings())?;
+    check_is_apub_id_valid(page.id.inner(), community.local, &context.settings())?;
     verify_person_in_community(&page.attributed_to, &community, context, request_counter).await?;
 
     let thumbnail_url: Option<Url> = page.image.clone().map(|i| i.url);
index 81615fdc9708fb918c102d8bc7321028bf550d01..5c4befb05c480778428686be50180b0bc03b73cf 100644 (file)
@@ -11,6 +11,7 @@ use lemmy_api_common::blocking;
 use lemmy_apub_lib::{
   traits::ApubObject,
   values::{MediaTypeHtml, MediaTypeMarkdown},
+  verify::verify_domains_match,
 };
 use lemmy_db_schema::{
   source::{
@@ -81,7 +82,7 @@ impl ApubObject for ApubPrivateMessage {
 
     let note = ChatMessage {
       r#type: ChatMessageType::ChatMessage,
-      id: self.ap_id.clone().into(),
+      id: ObjectId::new(self.ap_id.clone()),
       attributed_to: ObjectId::new(creator.actor_id),
       to: [ObjectId::new(recipient.actor_id)],
       content: markdown_to_html(&self.content),
@@ -107,7 +108,8 @@ impl ApubObject for ApubPrivateMessage {
     expected_domain: &Url,
     request_counter: &mut i32,
   ) -> Result<ApubPrivateMessage, LemmyError> {
-    let ap_id = Some(note.id(expected_domain)?.clone().into());
+    verify_domains_match(note.id.inner(), expected_domain)?;
+    let ap_id = Some(note.id.clone().into());
     let creator = note
       .attributed_to
       .dereference(context, request_counter)
index 038af4edf1919976d030a171181bfa6c51a314d1..e9677758cbae55bedfc38f17553ae805d49eb11f 100644 (file)
@@ -1,4 +1,8 @@
-use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson, protocol::Source};
+use crate::{
+  fetcher::object_id::ObjectId,
+  objects::{person::ApubPerson, private_message::ApubPrivateMessage},
+  protocol::Source,
+};
 use activitystreams::{
   chrono::{DateTime, FixedOffset},
   unparsed::Unparsed,
@@ -9,14 +13,13 @@ use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
-use url::Url;
 
 #[skip_serializing_none]
 #[derive(Clone, Debug, Deserialize, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct ChatMessage {
   pub(crate) r#type: ChatMessageType,
-  pub(crate) id: Url,
+  pub(crate) id: ObjectId<ApubPrivateMessage>,
   pub(crate) attributed_to: ObjectId<ApubPerson>,
   pub(crate) to: [ObjectId<ApubPerson>; 1],
   pub(crate) content: String,
@@ -35,20 +38,12 @@ pub enum ChatMessageType {
 }
 
 impl ChatMessage {
-  pub(crate) fn id_unchecked(&self) -> &Url {
-    &self.id
-  }
-  pub(crate) fn id(&self, expected_domain: &Url) -> Result<&Url, LemmyError> {
-    verify_domains_match(&self.id, expected_domain)?;
-    Ok(&self.id)
-  }
-
   pub(crate) async fn verify(
     &self,
     context: &LemmyContext,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    verify_domains_match(self.attributed_to.inner(), &self.id)?;
+    verify_domains_match(self.attributed_to.inner(), self.id.inner())?;
     let person = self
       .attributed_to
       .dereference(context, request_counter)
index 4da987a25a3aa617514966a3f009390edd9254cc..921a5dc8d48222c99284388dc1f16b9404f78934 100644 (file)
@@ -5,7 +5,7 @@ use crate::{
     community_outbox::ApubCommunityOutbox,
   },
   fetcher::object_id::ObjectId,
-  objects::get_summary_from_string_or_source,
+  objects::{community::ApubCommunity, get_summary_from_string_or_source},
   protocol::{ImageObject, Source},
 };
 use activitystreams::{
@@ -30,7 +30,7 @@ use url::Url;
 pub struct Group {
   #[serde(rename = "type")]
   pub(crate) kind: GroupType,
-  pub(crate) id: Url,
+  pub(crate) id: ObjectId<ApubCommunity>,
   /// username, set at account creation and can never be changed
   pub(crate) preferred_username: String,
   /// title (can be changed at any time)
@@ -61,8 +61,8 @@ impl Group {
     expected_domain: &Url,
     settings: &Settings,
   ) -> Result<CommunityForm, LemmyError> {
-    check_is_apub_id_valid(&group.id, true, settings)?;
-    verify_domains_match(expected_domain, &group.id)?;
+    check_is_apub_id_valid(group.id.inner(), true, settings)?;
+    verify_domains_match(expected_domain, group.id.inner())?;
     let name = group.preferred_username.clone();
     let title = group.name.clone();
     let description = get_summary_from_string_or_source(&group.summary, &group.source);
index bdc4da66b6834d422494496877f7ad093282e10d..58b164a7da9be845a4dd95870d734a5f55a086c9 100644 (file)
@@ -1,7 +1,7 @@
 use crate::{
   activities::{verify_is_public, verify_person_in_community},
   fetcher::{object_id::ObjectId, post_or_comment::PostOrComment},
-  objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost},
+  objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
   protocol::Source,
 };
 use activitystreams::{object::kind::NoteType, unparsed::Unparsed};
@@ -26,11 +26,8 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct Note {
   pub(crate) r#type: NoteType,
-  pub(crate) id: Url,
+  pub(crate) id: ObjectId<ApubComment>,
   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`]).
   pub(crate) to: Vec<Url>,
   pub(crate) content: String,
   pub(crate) media_type: Option<MediaTypeHtml>,
@@ -52,14 +49,6 @@ pub(crate) enum SourceCompat {
 }
 
 impl Note {
-  pub(crate) fn id_unchecked(&self) -> &Url {
-    &self.id
-  }
-  pub(crate) fn id(&self, expected_domain: &Url) -> Result<&Url, LemmyError> {
-    verify_domains_match(&self.id, expected_domain)?;
-    Ok(&self.id)
-  }
-
   pub(crate) async fn get_parents(
     &self,
     context: &LemmyContext,
@@ -104,7 +93,7 @@ impl Note {
     if post.locked {
       return Err(anyhow!("Post is locked").into());
     }
-    verify_domains_match(self.attributed_to.inner(), &self.id)?;
+    verify_domains_match(self.attributed_to.inner(), self.id.inner())?;
     verify_person_in_community(&self.attributed_to, &community, context, request_counter).await?;
     verify_is_public(&self.to)?;
     Ok(())
index 7887f19c1b171b2287daec8978d42c2a542cedb7..0cd004799b2701a689ec0bcbae6c494d558bc1ac 100644 (file)
@@ -19,7 +19,7 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct Page {
   pub(crate) r#type: PageType,
-  pub(crate) id: Url,
+  pub(crate) id: ObjectId<ApubPost>,
   pub(crate) attributed_to: ObjectId<ApubPerson>,
   pub(crate) to: Vec<Url>,
   pub(crate) name: String,
@@ -38,14 +38,6 @@ pub struct Page {
 }
 
 impl Page {
-  pub(crate) fn id_unchecked(&self) -> &Url {
-    &self.id
-  }
-  pub(crate) fn id(&self, expected_domain: &Url) -> Result<&Url, LemmyError> {
-    verify_domains_match(&self.id, expected_domain)?;
-    Ok(&self.id)
-  }
-
   /// Only mods can change the post's stickied/locked status. So if either of these is changed from
   /// the current value, it is a mod action and needs to be verified as such.
   ///
@@ -71,7 +63,7 @@ impl Page {
     let community = self.extract_community(context, request_counter).await?;
 
     check_slurs(&self.name, &context.settings().slur_regex())?;
-    verify_domains_match(self.attributed_to.inner(), &self.id.clone())?;
+    verify_domains_match(self.attributed_to.inner(), self.id.inner())?;
     verify_person_in_community(&self.attributed_to, &community, context, request_counter).await?;
     verify_is_public(&self.to.clone())?;
     Ok(())
index 2aecf945eb7ebabc630507b22ff6d85e4b9bf9a9..720e7de00383b072e95719d7ae6bfe19adca2dd5 100644 (file)
@@ -1,4 +1,8 @@
-use crate::protocol::{ImageObject, Source};
+use crate::{
+  fetcher::object_id::ObjectId,
+  objects::person::ApubPerson,
+  protocol::{ImageObject, Source},
+};
 use activitystreams::{actor::Endpoints, unparsed::Unparsed, url::Url};
 use chrono::{DateTime, FixedOffset};
 use lemmy_apub_lib::signatures::PublicKey;
@@ -17,7 +21,7 @@ pub enum UserTypes {
 pub struct Person {
   #[serde(rename = "type")]
   pub(crate) kind: UserTypes,
-  pub(crate) id: Url,
+  pub(crate) id: ObjectId<ApubPerson>,
   /// username, set at account creation and can never be changed
   pub(crate) preferred_username: String,
   /// displayname (can be changed at any time)