diff --git a/crates/apub/src/extensions/context.rs b/crates/apub/src/extensions/context.rs index a36b84899..041ca4bf0 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, 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 4b4c08664..2f7df8211 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 000000000..248adcc43 --- /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, +} + +impl PersonExtension { + pub fn new(matrix_user_id: Option) -> Result { + Ok(PersonExtension { matrix_user_id }) + } +} + +impl UnparsedExtension for PersonExtension +where + U: UnparsedMutExt, +{ + type Error = serde_json::Error; + + fn try_from_unparsed(unparsed_mut: &mut U) -> Result { + 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 74d4cbef3..0e2c826ad 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>, GroupExtension, PublicKeyExtension>; /// Activitystreams type for person -type PersonExt = Ext1>, PublicKeyExtension>; +type PersonExt = Ext2>, PersonExtension, PublicKeyExtension>; /// Activitystreams type for post type PageExt = Ext1, PageExtension>; type NoteExt = ApObject; diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index a73febceb..9667031c7 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 cc45fd7ed..662871dc1 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 { unimplemented!() @@ -192,11 +193,11 @@ impl FromApubToForm 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()), }) } }