From: Felix Ableitner <me@nutomic.com>
Date: Wed, 24 Mar 2021 16:43:18 +0000 (+0100)
Subject: Federate Matrix ID (fixes #1438)
X-Git-Url: http://these/git/%22https:/image.com/%24%7Bargs.pageFn.prev%7D?a=commitdiff_plain;h=34bdf4c7c5267d7756de5d769c84eb1d28b5de32;p=lemmy.git

Federate Matrix ID (fixes #1438)
---

diff --git a/crates/apub/src/extensions/context.rs b/crates/apub/src/extensions/context.rs
index a36b8489..041ca4bf 100644
--- a/crates/apub/src/extensions/context.rs
+++ b/crates/apub/src/extensions/context.rs
@@ -14,7 +14,11 @@ pub(crate) fn lemmy_context() -> Result<Vec<AnyBase>, LemmyError> {
       "type": "sc:Boolean",
       "id": "pt:commentsEnabled"
     },
-    "moderators": "as:moderators"
+    "moderators": "as:moderators",
+    "matrixUserId": {
+      "type": "sc:Text",
+      "id": "as:alsoKnownAs"
+    },
   }))?;
   Ok(vec![
     AnyBase::from(context()),
diff --git a/crates/apub/src/extensions/group_extensions.rs b/crates/apub/src/extensions/group_extension.rs
similarity index 100%
rename from crates/apub/src/extensions/group_extensions.rs
rename to crates/apub/src/extensions/group_extension.rs
diff --git a/crates/apub/src/extensions/mod.rs b/crates/apub/src/extensions/mod.rs
index 4b4c0866..2f7df821 100644
--- a/crates/apub/src/extensions/mod.rs
+++ b/crates/apub/src/extensions/mod.rs
@@ -1,4 +1,5 @@
 pub(crate) mod context;
-pub(crate) mod group_extensions;
+pub(crate) mod group_extension;
 pub(crate) mod page_extension;
+pub(crate) mod person_extension;
 pub(crate) mod signatures;
diff --git a/crates/apub/src/extensions/person_extension.rs b/crates/apub/src/extensions/person_extension.rs
new file mode 100644
index 00000000..248adcc4
--- /dev/null
+++ b/crates/apub/src/extensions/person_extension.rs
@@ -0,0 +1,36 @@
+use activitystreams::unparsed::UnparsedMutExt;
+use activitystreams_ext::UnparsedExtension;
+use lemmy_utils::LemmyError;
+use serde::{Deserialize, Serialize};
+
+/// Activitystreams extension to allow (de)serializing additional Person field
+/// `also_known_as` (used for Matrix profile link).
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct PersonExtension {
+  pub matrix_user_id: Option<String>,
+}
+
+impl PersonExtension {
+  pub fn new(matrix_user_id: Option<String>) -> Result<PersonExtension, LemmyError> {
+    Ok(PersonExtension { matrix_user_id })
+  }
+}
+
+impl<U> UnparsedExtension<U> for PersonExtension
+where
+  U: UnparsedMutExt,
+{
+  type Error = serde_json::Error;
+
+  fn try_from_unparsed(unparsed_mut: &mut U) -> Result<Self, Self::Error> {
+    Ok(PersonExtension {
+      matrix_user_id: unparsed_mut.remove("matrix_user_id")?,
+    })
+  }
+
+  fn try_into_unparsed(self, unparsed_mut: &mut U) -> Result<(), Self::Error> {
+    unparsed_mut.insert("matrix_user_id", self.matrix_user_id)?;
+    Ok(())
+  }
+}
diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs
index 74d4cbef..0e2c826a 100644
--- a/crates/apub/src/lib.rs
+++ b/crates/apub/src/lib.rs
@@ -11,8 +11,9 @@ pub mod objects;
 pub mod routes;
 
 use crate::extensions::{
-  group_extensions::GroupExtension,
+  group_extension::GroupExtension,
   page_extension::PageExtension,
+  person_extension::PersonExtension,
   signatures::{PublicKey, PublicKeyExtension},
 };
 use activitystreams::{
@@ -46,7 +47,7 @@ use url::{ParseError, Url};
 /// Activitystreams type for community
 type GroupExt = Ext2<actor::ApActor<ApObject<actor::Group>>, GroupExtension, PublicKeyExtension>;
 /// Activitystreams type for person
-type PersonExt = Ext1<actor::ApActor<ApObject<actor::Person>>, PublicKeyExtension>;
+type PersonExt = Ext2<actor::ApActor<ApObject<actor::Person>>, PersonExtension, PublicKeyExtension>;
 /// Activitystreams type for post
 type PageExt = Ext1<ApObject<Page>, PageExtension>;
 type NoteExt = ApObject<Note>;
diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs
index a73febce..9667031c 100644
--- a/crates/apub/src/objects/community.rs
+++ b/crates/apub/src/objects/community.rs
@@ -1,5 +1,5 @@
 use crate::{
-  extensions::{context::lemmy_context, group_extensions::GroupExtension},
+  extensions::{context::lemmy_context, group_extension::GroupExtension},
   fetcher::{community::fetch_community_mods, person::get_or_fetch_and_upsert_person},
   generate_moderators_url,
   objects::{
diff --git a/crates/apub/src/objects/person.rs b/crates/apub/src/objects/person.rs
index cc45fd7e..662871dc 100644
--- a/crates/apub/src/objects/person.rs
+++ b/crates/apub/src/objects/person.rs
@@ -1,5 +1,5 @@
 use crate::{
-  extensions::context::lemmy_context,
+  extensions::{context::lemmy_context, person_extension::PersonExtension},
   objects::{
     check_object_domain,
     get_source_markdown_value,
@@ -16,7 +16,7 @@ use activitystreams::{
   object::{ApObject, Image, Tombstone},
   prelude::*,
 };
-use activitystreams_ext::Ext1;
+use activitystreams_ext::Ext2;
 use anyhow::Context;
 use lemmy_api_structs::blocking;
 use lemmy_db_queries::{ApubObject, DbPool};
@@ -77,7 +77,8 @@ impl ToApub for DbPerson {
         ..Default::default()
       });
 
-    Ok(Ext1::new(ap_actor, self.get_public_key_ext()?))
+    let person_ext = PersonExtension::new(self.matrix_user_id.to_owned())?;
+    Ok(Ext2::new(ap_actor, person_ext, self.get_public_key_ext()?))
   }
   fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
     unimplemented!()
@@ -192,11 +193,11 @@ impl FromApubToForm<PersonExt> for PersonForm {
       local: Some(false),
       admin: Some(false),
       private_key: None,
-      public_key: Some(Some(person.ext_one.public_key.to_owned().public_key_pem)),
+      public_key: Some(Some(person.ext_two.public_key.to_owned().public_key_pem)),
       last_refreshed_at: Some(naive_now()),
       inbox_url: Some(person.inner.inbox()?.to_owned().into()),
       shared_inbox_url: Some(shared_inbox),
-      matrix_user_id: None, // TODO
+      matrix_user_id: Some(person.ext_one.matrix_user_id.to_owned()),
     })
   }
 }