diff --git a/server/Cargo.lock b/server/Cargo.lock index faad80f3..1e0e04f8 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -1,35 +1,9 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "activitystreams" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464cb473bfb402b857cc15b1153974c203a43f1485da4dda15cd17a738548958" -dependencies = [ - "activitystreams-derive", - "chrono", - "mime", - "serde 1.0.114", - "serde_json", - "thiserror", - "url", -] - -[[package]] -name = "activitystreams-derive" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39ba5929399e9f921055bac76dd8f47419fa5b6b6da1ac4c1e82b94ed0ac7b4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "activitystreams-ext" version = "0.1.0" -source = "git+https://git.asonix.dog/asonix/activitystreams-ext#e5c97f4ea9f60e49bc7ff27fb0fb515d3190fd25" +source = "git+https://git.asonix.dog/asonix/activitystreams-ext?branch=main#9acc466c7cb550ada31b669a1c47ea088f1c8471" dependencies = [ "activitystreams-new", "serde 1.0.114", @@ -39,12 +13,14 @@ dependencies = [ [[package]] name = "activitystreams-new" version = "0.1.0" -source = "git+https://git.asonix.dog/asonix/activitystreams-sketch#99c7e9aa5596eda846a1ebd5978ca72d11d4c08a" +source = "git+https://git.asonix.dog/asonix/activitystreams-sketch?branch=main#857d5167dfa13054dd0d21d3d54f8147eea0d546" dependencies = [ - "activitystreams", + "chrono", + "mime", "serde 1.0.114", "serde_json", - "typed-builder", + "thiserror", + "url", ] [[package]] @@ -1579,6 +1555,7 @@ dependencies = [ "sha2", "strum", "strum_macros", + "url", ] [[package]] @@ -3138,17 +3115,6 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" -[[package]] -name = "typed-builder" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fc4459191c621a53ef6c6ca5642e6e0e5ccc61f3e5b8ad6b6ab5317f0200fb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "typenum" version = "1.12.0" diff --git a/server/Cargo.toml b/server/Cargo.toml index 2b785ec1..06078ba5 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -18,8 +18,8 @@ lemmy_db = { path = "./lemmy_db" } diesel = "1.4.4" diesel_migrations = "1.4.0" dotenv = "0.15.0" -activitystreams-new = { git = "https://git.asonix.dog/asonix/activitystreams-sketch" } -activitystreams-ext = { git = "https://git.asonix.dog/asonix/activitystreams-ext" } +activitystreams-new = { git = "https://git.asonix.dog/asonix/activitystreams-sketch", branch = "main" } +activitystreams-ext = { git = "https://git.asonix.dog/asonix/activitystreams-ext", branch = "main" } bcrypt = "0.8.0" chrono = { version = "0.4.7", features = ["serde"] } serde_json = { version = "1.0.52", features = ["preserve_order"]} diff --git a/server/lemmy_db/Cargo.toml b/server/lemmy_db/Cargo.toml index d94cf5fc..f10f217e 100644 --- a/server/lemmy_db/Cargo.toml +++ b/server/lemmy_db/Cargo.toml @@ -12,4 +12,5 @@ strum = "0.18.0" strum_macros = "0.18.0" log = "0.4.0" sha2 = "0.9" -bcrypt = "0.8.0" \ No newline at end of file +bcrypt = "0.8.0" +url = { version = "2.1.1", features = ["serde"] } \ No newline at end of file diff --git a/server/lemmy_db/src/comment.rs b/server/lemmy_db/src/comment.rs index 602070d5..acdddcc3 100644 --- a/server/lemmy_db/src/comment.rs +++ b/server/lemmy_db/src/comment.rs @@ -1,5 +1,6 @@ use super::{post::Post, *}; use crate::schema::{comment, comment_like, comment_saved}; +use url::{ParseError, Url}; // WITH RECURSIVE MyTree AS ( // SELECT * FROM comment WHERE parent_id IS NULL @@ -42,6 +43,12 @@ pub struct CommentForm { pub local: bool, } +impl CommentForm { + pub fn get_ap_id(&self) -> Result { + Url::parse(&self.ap_id) + } +} + impl Crud for Comment { fn read(conn: &PgConnection, comment_id: i32) -> Result { use crate::schema::comment::dsl::*; diff --git a/server/lemmy_db/src/post.rs b/server/lemmy_db/src/post.rs index 1525a675..12cf927e 100644 --- a/server/lemmy_db/src/post.rs +++ b/server/lemmy_db/src/post.rs @@ -8,6 +8,7 @@ use crate::{ }; use diesel::{dsl::*, result::Error, *}; use serde::{Deserialize, Serialize}; +use url::{ParseError, Url}; #[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)] #[table_name = "post"] @@ -56,6 +57,12 @@ pub struct PostForm { pub local: bool, } +impl PostForm { + pub fn get_ap_id(&self) -> Result { + Url::parse(&self.ap_id) + } +} + impl Post { pub fn read(conn: &PgConnection, post_id: i32) -> Result { use crate::schema::post::dsl::*; diff --git a/server/src/apub/activities.rs b/server/src/apub/activities.rs index a14e6ec3..a436d30f 100644 --- a/server/src/apub/activities.rs +++ b/server/src/apub/activities.rs @@ -1,14 +1,10 @@ use crate::{ apub::{ - community::do_announce, - extensions::signatures::sign, - insert_activity, - is_apub_id_valid, + community::do_announce, extensions::signatures::sign, insert_activity, is_apub_id_valid, ActorType, }, request::retry_custom, - DbPool, - LemmyError, + DbPool, LemmyError, }; use activitystreams_new::base::AnyBase; use actix_web::client::Client; diff --git a/server/src/apub/comment.rs b/server/src/apub/comment.rs index 2f21ce8d..2a084015 100644 --- a/server/src/apub/comment.rs +++ b/server/src/apub/comment.rs @@ -1,25 +1,16 @@ use crate::{ apub::{ activities::send_activity_to_community, - create_apub_response, - create_apub_tombstone_response, - create_tombstone, - fetch_webfinger_url, + create_apub_response, create_apub_tombstone_response, create_tombstone, fetch_webfinger_url, fetcher::{ - get_or_fetch_and_insert_remote_comment, - get_or_fetch_and_insert_remote_post, + get_or_fetch_and_insert_remote_comment, get_or_fetch_and_insert_remote_post, get_or_fetch_and_upsert_remote_user, }, - ActorType, - ApubLikeableType, - ApubObjectType, - FromApub, - ToApub, + ActorType, ApubLikeableType, ApubObjectType, FromApub, ToApub, }, blocking, routes::DbPoolParam, - DbPool, - LemmyError, + DbPool, LemmyError, }; use activitystreams_new::{ activity::{Create, Delete, Dislike, Like, Remove, Undo, Update}, @@ -28,7 +19,6 @@ use activitystreams_new::{ link::Mention, object::{kind::NoteType, Note, Tombstone}, prelude::*, - primitives::XsdAnyUri, public, }; use actix_web::{body::Body, client::Client, web::Path, HttpResponse}; @@ -44,7 +34,7 @@ use lemmy_utils::{convert_datetime, scrape_text_for_mentions, MentionData}; use log::debug; use serde::Deserialize; use serde_json::Error; -use std::str::FromStr; +use url::Url; #[derive(Deserialize)] pub struct CommentQuery { @@ -95,15 +85,15 @@ impl ToApub for Comment { comment // Not needed when the Post is embedded in a collection (like for community outbox) .set_context(context()) - .set_id(self.ap_id.parse::()?) - .set_published(convert_datetime(self.published).into()) + .set_id(Url::parse(&self.ap_id)?) + .set_published(convert_datetime(self.published)) .set_to(community.actor_id) .set_many_in_reply_tos(in_reply_to_vec) .set_content(self.content.to_owned()) .set_attributed_to(creator.actor_id); if let Some(u) = self.updated { - comment.set_updated(convert_datetime(u).into()); + comment.set_updated(convert_datetime(u)); } Ok(comment) @@ -114,7 +104,7 @@ impl ToApub for Comment { self.deleted, &self.ap_id, self.updated, - NoteType.to_string(), + NoteType::Note.to_string(), ) } } @@ -128,6 +118,7 @@ impl FromApub for CommentForm { note: &Note, client: &Client, pool: &DbPool, + actor_id: &Url, ) -> Result { let creator_actor_id = ¬e .attributed_to() @@ -138,14 +129,14 @@ impl FromApub for CommentForm { let creator = get_or_fetch_and_upsert_remote_user(creator_actor_id, client, pool).await?; let mut in_reply_tos = note - .in_reply_to + .in_reply_to() .as_ref() .unwrap() .as_many() .unwrap() .iter() .map(|i| i.as_xsd_any_uri().unwrap()); - let post_ap_id = in_reply_tos.next().unwrap().to_string(); + let post_ap_id = in_reply_tos.next().unwrap(); // This post, or the parent comment might not yet exist on this server yet, fetch them. let post = get_or_fetch_and_insert_remote_post(&post_ap_id, client, pool).await?; @@ -154,7 +145,7 @@ impl FromApub for CommentForm { // For deeply nested comments, FromApub automatically gets called recursively let parent_id: Option = match in_reply_tos.next() { Some(parent_comment_uri) => { - let parent_comment_ap_id = &parent_comment_uri.to_string(); + let parent_comment_ap_id = &parent_comment_uri; let parent_comment = get_or_fetch_and_insert_remote_comment(&parent_comment_ap_id, client, pool).await?; @@ -175,12 +166,10 @@ impl FromApub for CommentForm { .to_string(), removed: None, read: None, - published: note - .published() - .map(|u| u.as_ref().to_owned().naive_local()), - updated: note.updated().map(|u| u.as_ref().to_owned().naive_local()), + published: note.published().map(|u| u.to_owned().naive_local()), + updated: note.updated().map(|u| u.to_owned().naive_local()), deleted: None, - ap_id: note.id().unwrap().to_string(), + ap_id: note.id(actor_id.domain().unwrap())?.unwrap().to_string(), local: false, }) } @@ -210,7 +199,7 @@ impl ApubObjectType for Comment { let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?); create .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(maa.addressed_ccs.to_owned()) // Set the mention tags @@ -250,7 +239,7 @@ impl ApubObjectType for Comment { let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?); update .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(maa.addressed_ccs.to_owned()) // Set the mention tags @@ -286,7 +275,7 @@ impl ApubObjectType for Comment { let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); delete .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -321,7 +310,7 @@ impl ApubObjectType for Comment { let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); delete .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -331,7 +320,7 @@ impl ApubObjectType for Comment { let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); undo .set_context(context()) - .set_id(XsdAnyUri::from_str(&undo_id)?) + .set_id(Url::parse(&undo_id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -365,7 +354,7 @@ impl ApubObjectType for Comment { let mut remove = Remove::new(mod_.actor_id.to_owned(), note.into_any_base()?); remove .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -400,7 +389,7 @@ impl ApubObjectType for Comment { let mut remove = Remove::new(mod_.actor_id.to_owned(), note.into_any_base()?); remove .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -409,7 +398,7 @@ impl ApubObjectType for Comment { let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?); undo .set_context(context()) - .set_id(XsdAnyUri::from_str(&undo_id)?) + .set_id(Url::parse(&undo_id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -447,7 +436,7 @@ impl ApubLikeableType for Comment { let mut like = Like::new(creator.actor_id.to_owned(), note.into_any_base()?); like .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -482,7 +471,7 @@ impl ApubLikeableType for Comment { let mut dislike = Dislike::new(creator.actor_id.to_owned(), note.into_any_base()?); dislike .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -517,7 +506,7 @@ impl ApubLikeableType for Comment { let mut like = Like::new(creator.actor_id.to_owned(), note.into_any_base()?); like .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -527,7 +516,7 @@ impl ApubLikeableType for Comment { let mut undo = Undo::new(creator.actor_id.to_owned(), like.into_any_base()?); undo .set_context(context()) - .set_id(XsdAnyUri::from_str(&undo_id)?) + .set_id(Url::parse(&undo_id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); diff --git a/server/src/apub/community.rs b/server/src/apub/community.rs index 28c7fc88..0df2f3fd 100644 --- a/server/src/apub/community.rs +++ b/server/src/apub/community.rs @@ -1,22 +1,13 @@ use crate::{ apub::{ - activities::send_activity, - create_apub_response, - create_apub_tombstone_response, - create_tombstone, - extensions::group_extensions::GroupExtension, - fetcher::get_or_fetch_and_upsert_remote_user, - get_shared_inbox, - insert_activity, - ActorType, - FromApub, - GroupExt, - ToApub, + activities::send_activity, create_apub_response, create_apub_tombstone_response, + create_tombstone, extensions::group_extensions::GroupExtension, + fetcher::get_or_fetch_and_upsert_remote_user, get_shared_inbox, insert_activity, ActorType, + FromApub, GroupExt, ToApub, }, blocking, routes::DbPoolParam, - DbPool, - LemmyError, + DbPool, LemmyError, }; use activitystreams_ext::Ext2; use activitystreams_new::{ @@ -27,7 +18,6 @@ use activitystreams_new::{ context, object::Tombstone, prelude::*, - primitives::{XsdAnyUri, XsdDateTime}, public, }; use actix_web::{body::Body, client::Client, web, HttpResponse}; @@ -40,7 +30,7 @@ use lemmy_db::{ }; use lemmy_utils::convert_datetime; use serde::Deserialize; -use std::str::FromStr; +use url::Url; #[derive(Deserialize)] pub struct CommunityQuery { @@ -67,13 +57,13 @@ impl ToApub for Community { let mut group = Group::new(); group .set_context(context()) - .set_id(XsdAnyUri::from_str(&self.actor_id)?) + .set_id(Url::parse(&self.actor_id)?) .set_name(self.name.to_owned()) - .set_published(XsdDateTime::from(convert_datetime(self.published))) + .set_published(convert_datetime(self.published)) .set_many_attributed_tos(moderators); if let Some(u) = self.updated.to_owned() { - group.set_updated(XsdDateTime::from(convert_datetime(u))); + group.set_updated(convert_datetime(u)); } if let Some(d) = self.description.to_owned() { // TODO: this should be html, also add source field with raw markdown @@ -112,14 +102,14 @@ impl ToApub for Community { self.deleted, &self.actor_id, self.updated, - GroupType.to_string(), + GroupType::Group.to_string(), ) } } #[async_trait::async_trait(?Send)] impl ActorType for Community { - fn actor_id(&self) -> String { + fn actor_id_str(&self) -> String { self.actor_id.to_owned() } @@ -137,14 +127,14 @@ impl ActorType for Community { client: &Client, pool: &DbPool, ) -> Result<(), LemmyError> { - let actor_uri = follow.actor.as_single_xsd_any_uri().unwrap().to_string(); + let actor_uri = follow.actor()?.as_single_xsd_any_uri().unwrap().to_string(); let id = format!("{}/accept/{}", self.actor_id, uuid::Uuid::new_v4()); let mut accept = Accept::new(self.actor_id.to_owned(), follow.into_any_base()?); let to = format!("{}/inbox", actor_uri); accept .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(to.clone()); insert_activity(self.creator_id, accept.clone(), true, pool).await?; @@ -166,7 +156,7 @@ impl ActorType for Community { let mut delete = Delete::new(creator.actor_id.to_owned(), group.into_any_base()?); delete .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()]); @@ -194,7 +184,7 @@ impl ActorType for Community { let mut delete = Delete::new(creator.actor_id.to_owned(), group.into_any_base()?); delete .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()]); @@ -204,7 +194,7 @@ impl ActorType for Community { let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); undo .set_context(context()) - .set_id(XsdAnyUri::from_str(&undo_id)?) + .set_id(Url::parse(&undo_id)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()]); @@ -232,7 +222,7 @@ impl ActorType for Community { let mut remove = Remove::new(mod_.actor_id.to_owned(), group.into_any_base()?); remove .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()]); @@ -260,7 +250,7 @@ impl ActorType for Community { let mut remove = Remove::new(mod_.actor_id.to_owned(), group.into_any_base()?); remove .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()]); @@ -269,7 +259,7 @@ impl ActorType for Community { let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?); undo .set_context(context()) - .set_id(XsdAnyUri::from_str(&undo_id)?) + .set_id(Url::parse(&undo_id)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()]); @@ -294,7 +284,7 @@ impl ActorType for Community { .await??; let inboxes = inboxes .into_iter() - .map(|c| get_shared_inbox(&c.user_actor_id)) + .map(|c| get_shared_inbox(&Url::parse(&c.user_actor_id).unwrap())) .filter(|s| !s.is_empty()) .unique() .collect(); @@ -326,7 +316,12 @@ impl FromApub for CommunityForm { type ApubType = GroupExt; /// Parse an ActivityPub group received from another instance into a Lemmy community. - async fn from_apub(group: &GroupExt, client: &Client, pool: &DbPool) -> Result { + async fn from_apub( + group: &GroupExt, + client: &Client, + pool: &DbPool, + actor_id: &Url, + ) -> Result { let creator_and_moderator_uris = group.inner.attributed_to().unwrap(); let creator_uri = creator_and_moderator_uris .as_many() @@ -344,7 +339,9 @@ impl FromApub for CommunityForm { .inner .name() .unwrap() - .as_single_xsd_string() + .as_one() + .unwrap() + .as_xsd_string() .unwrap() .into(), title: group.inner.preferred_username().unwrap().to_string(), @@ -357,17 +354,15 @@ impl FromApub for CommunityForm { category_id: group.ext_one.category.identifier.parse::()?, creator_id: creator.id, removed: None, - published: group - .inner - .published() - .map(|u| u.as_ref().to_owned().naive_local()), - updated: group - .inner - .updated() - .map(|u| u.as_ref().to_owned().naive_local()), + published: group.inner.published().map(|u| u.to_owned().naive_local()), + updated: group.inner.updated().map(|u| u.to_owned().naive_local()), deleted: None, nsfw: group.ext_one.sensitive, - actor_id: group.inner.id().unwrap().to_string(), + actor_id: group + .inner + .id(actor_id.domain().unwrap())? + .unwrap() + .to_string(), local: false, private_key: None, public_key: Some(group.ext_two.to_owned().public_key.public_key_pem), @@ -431,7 +426,7 @@ pub async fn do_announce( let mut announce = Announce::new(community.actor_id.to_owned(), activity); announce .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); diff --git a/server/src/apub/community_inbox.rs b/server/src/apub/community_inbox.rs index 352bfd72..44a1c949 100644 --- a/server/src/apub/community_inbox.rs +++ b/server/src/apub/community_inbox.rs @@ -2,8 +2,7 @@ use crate::{ apub::{ extensions::signatures::verify, fetcher::{get_or_fetch_and_upsert_remote_community, get_or_fetch_and_upsert_remote_user}, - insert_activity, - ActorType, + insert_activity, ActorType, }, blocking, routes::{ChatServerParam, DbPoolParam}, @@ -35,7 +34,7 @@ impl CommunityAcceptedObjects { match self { CommunityAcceptedObjects::Follow(f) => Ok(f.to_owned()), CommunityAcceptedObjects::Undo(u) => { - Ok(Follow::from_any_base(u.object.as_one().unwrap().to_owned())?.unwrap()) + Ok(Follow::from_any_base(u.object().as_one().unwrap().to_owned())?.unwrap()) } } } @@ -69,11 +68,11 @@ pub async fn community_inbox( &community.name, &input ); let follow = input.follow()?; - let user_uri = follow.actor.as_single_xsd_any_uri().unwrap(); - let community_uri = follow.object.as_single_xsd_any_uri().unwrap().to_string(); + let user_uri = follow.actor()?.as_single_xsd_any_uri().unwrap(); + let community_uri = follow.object().as_single_xsd_any_uri().unwrap(); let user = get_or_fetch_and_upsert_remote_user(&user_uri, &client, &db).await?; - let community = get_or_fetch_and_upsert_remote_community(&community_uri, &client, &db).await?; + let community = get_or_fetch_and_upsert_remote_community(community_uri, &client, &db).await?; verify(&request, &user)?; diff --git a/server/src/apub/extensions/signatures.rs b/server/src/apub/extensions/signatures.rs index 468e820e..5a1cdeb8 100644 --- a/server/src/apub/extensions/signatures.rs +++ b/server/src/apub/extensions/signatures.rs @@ -25,7 +25,7 @@ pub async fn sign( actor: &dyn ActorType, activity: String, ) -> Result, LemmyError> { - let signing_key_id = format!("{}#main-key", actor.actor_id()); + let signing_key_id = format!("{}#main-key", actor.actor_id()?); let private_key = actor.private_key(); let digest_client = request diff --git a/server/src/apub/fetcher.rs b/server/src/apub/fetcher.rs index 93b25800..8779486b 100644 --- a/server/src/apub/fetcher.rs +++ b/server/src/apub/fetcher.rs @@ -4,10 +4,9 @@ use crate::{ blocking, request::{retry, RecvError}, routes::nodeinfo::{NodeInfo, NodeInfoWellKnown}, - DbPool, - LemmyError, + DbPool, LemmyError, }; -use activitystreams_new::{base::BaseExt, object::Note, prelude::*, primitives::XsdAnyUri}; +use activitystreams_new::{base::BaseExt, object::Note, prelude::*}; use actix_web::client::Client; use chrono::NaiveDateTime; use diesel::{result::Error::NotFound, PgConnection}; @@ -21,9 +20,7 @@ use lemmy_db::{ post_view::PostView, user::{UserForm, User_}, user_view::UserView, - Crud, - Joinable, - SearchType, + Crud, Joinable, SearchType, }; use lemmy_utils::get_apub_protocol_string; use log::debug; @@ -136,9 +133,10 @@ pub async fn search_by_apub_id( users: vec![], }; + let domain = query_url.domain().unwrap(); let response = match fetch_remote_object::(client, &query_url).await? { SearchAcceptedObjects::Person(p) => { - let user_uri = p.inner.id().unwrap(); + let user_uri = p.inner.id(domain)?.unwrap(); let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; @@ -147,10 +145,9 @@ pub async fn search_by_apub_id( response } SearchAcceptedObjects::Group(g) => { - let community_uri = g.inner.id().unwrap().to_string(); + let community_uri = g.inner.id(domain)?.unwrap(); - let community = - get_or_fetch_and_upsert_remote_community(&community_uri, client, pool).await?; + let community = get_or_fetch_and_upsert_remote_community(community_uri, client, pool).await?; // TODO Maybe at some point in the future, fetch all the history of a community // fetch_community_outbox(&c, conn)?; @@ -164,7 +161,7 @@ pub async fn search_by_apub_id( response } SearchAcceptedObjects::Page(p) => { - let post_form = PostForm::from_apub(&p, client, pool).await?; + let post_form = PostForm::from_apub(&p, client, pool, &query_url).await?; let p = blocking(pool, move |conn| upsert_post(&post_form, conn)).await??; response.posts = vec![blocking(pool, move |conn| PostView::read(conn, p.id, None)).await??]; @@ -172,13 +169,13 @@ pub async fn search_by_apub_id( response } SearchAcceptedObjects::Comment(c) => { - let post_url = c.in_reply_to.as_ref().unwrap().as_many().unwrap(); + let post_url = c.in_reply_to().as_ref().unwrap().as_many().unwrap(); // TODO: also fetch parent comments if any let x = post_url.first().unwrap().as_xsd_any_uri().unwrap(); - let post = fetch_remote_object(client, x.as_url()).await?; - let post_form = PostForm::from_apub(&post, client, pool).await?; - let comment_form = CommentForm::from_apub(&c, client, pool).await?; + let post = fetch_remote_object(client, x).await?; + let post_form = PostForm::from_apub(&post, client, pool, &query_url).await?; + let comment_form = CommentForm::from_apub(&c, client, pool, &query_url).await?; blocking(pool, move |conn| upsert_post(&post_form, conn)).await??; let c = blocking(pool, move |conn| upsert_comment(&comment_form, conn)).await??; @@ -194,7 +191,7 @@ pub async fn search_by_apub_id( /// Check if a remote user exists, create if not found, if its too old update it.Fetch a user, insert/update it in the database and return the user. pub async fn get_or_fetch_and_upsert_remote_user( - apub_id: &XsdAnyUri, + apub_id: &Url, client: &Client, pool: &DbPool, ) -> Result { @@ -208,9 +205,9 @@ pub async fn get_or_fetch_and_upsert_remote_user( // If its older than a day, re-fetch it Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => { debug!("Fetching and updating from remote user: {}", apub_id); - let person = fetch_remote_object::(client, apub_id.as_url()).await?; + let person = fetch_remote_object::(client, apub_id).await?; - let mut uf = UserForm::from_apub(&person, client, pool).await?; + let mut uf = UserForm::from_apub(&person, client, pool, apub_id).await?; uf.last_refreshed_at = Some(naive_now()); let user = blocking(pool, move |conn| User_::update(conn, u.id, &uf)).await??; @@ -219,9 +216,9 @@ pub async fn get_or_fetch_and_upsert_remote_user( Ok(u) => Ok(u), Err(NotFound {}) => { debug!("Fetching and creating remote user: {}", apub_id); - let person = fetch_remote_object::(client, apub_id.as_url()).await?; + let person = fetch_remote_object::(client, apub_id).await?; - let uf = UserForm::from_apub(&person, client, pool).await?; + let uf = UserForm::from_apub(&person, client, pool, apub_id).await?; let user = blocking(pool, move |conn| User_::create(conn, &uf)).await??; Ok(user) @@ -246,22 +243,22 @@ fn should_refetch_actor(last_refreshed: NaiveDateTime) -> bool { /// Check if a remote community exists, create if not found, if its too old update it.Fetch a community, insert/update it in the database and return the community. pub async fn get_or_fetch_and_upsert_remote_community( - apub_id: &str, + apub_id: &Url, client: &Client, pool: &DbPool, ) -> Result { let apub_id_owned = apub_id.to_owned(); let community = blocking(pool, move |conn| { - Community::read_from_actor_id(conn, &apub_id_owned) + Community::read_from_actor_id(conn, apub_id_owned.as_str()) }) .await?; match community { Ok(c) if !c.local && should_refetch_actor(c.last_refreshed_at) => { debug!("Fetching and updating from remote community: {}", apub_id); - let group = fetch_remote_object::(client, &Url::parse(apub_id)?).await?; + let group = fetch_remote_object::(client, apub_id).await?; - let mut cf = CommunityForm::from_apub(&group, client, pool).await?; + let mut cf = CommunityForm::from_apub(&group, client, pool, apub_id).await?; cf.last_refreshed_at = Some(naive_now()); let community = blocking(pool, move |conn| Community::update(conn, c.id, &cf)).await??; @@ -270,14 +267,14 @@ pub async fn get_or_fetch_and_upsert_remote_community( Ok(c) => Ok(c), Err(NotFound {}) => { debug!("Fetching and creating remote community: {}", apub_id); - let group = fetch_remote_object::(client, &Url::parse(apub_id)?).await?; + let group = fetch_remote_object::(client, apub_id).await?; - let cf = CommunityForm::from_apub(&group, client, pool).await?; + let cf = CommunityForm::from_apub(&group, client, pool, apub_id).await?; let community = blocking(pool, move |conn| Community::create(conn, &cf)).await??; // Also add the community moderators too let attributed_to = group.inner.attributed_to().unwrap(); - let creator_and_moderator_uris: Vec<&XsdAnyUri> = attributed_to + let creator_and_moderator_uris: Vec<&Url> = attributed_to .as_many() .unwrap() .iter() @@ -322,13 +319,13 @@ fn upsert_post(post_form: &PostForm, conn: &PgConnection) -> Result Result { let post_ap_id_owned = post_ap_id.to_owned(); let post = blocking(pool, move |conn| { - Post::read_from_apub_id(conn, &post_ap_id_owned) + Post::read_from_apub_id(conn, post_ap_id_owned.as_str()) }) .await?; @@ -336,8 +333,8 @@ pub async fn get_or_fetch_and_insert_remote_post( Ok(p) => Ok(p), Err(NotFound {}) => { debug!("Fetching and creating remote post: {}", post_ap_id); - let post = fetch_remote_object::(client, &Url::parse(post_ap_id)?).await?; - let post_form = PostForm::from_apub(&post, client, pool).await?; + let post = fetch_remote_object::(client, post_ap_id).await?; + let post_form = PostForm::from_apub(&post, client, pool, post_ap_id).await?; let post = blocking(pool, move |conn| Post::create(conn, &post_form)).await??; @@ -357,13 +354,13 @@ fn upsert_comment(comment_form: &CommentForm, conn: &PgConnection) -> Result Result { let comment_ap_id_owned = comment_ap_id.to_owned(); let comment = blocking(pool, move |conn| { - Comment::read_from_apub_id(conn, &comment_ap_id_owned) + Comment::read_from_apub_id(conn, comment_ap_id_owned.as_str()) }) .await?; @@ -374,8 +371,8 @@ pub async fn get_or_fetch_and_insert_remote_comment( "Fetching and creating remote comment and its parents: {}", comment_ap_id ); - let comment = fetch_remote_object::(client, &Url::parse(comment_ap_id)?).await?; - let comment_form = CommentForm::from_apub(&comment, client, pool).await?; + let comment = fetch_remote_object::(client, comment_ap_id).await?; + let comment_form = CommentForm::from_apub(&comment, client, pool, comment_ap_id).await?; let comment = blocking(pool, move |conn| Comment::create(conn, &comment_form)).await??; diff --git a/server/src/apub/mod.rs b/server/src/apub/mod.rs index 413ca862..3f61dc92 100644 --- a/server/src/apub/mod.rs +++ b/server/src/apub/mod.rs @@ -19,8 +19,7 @@ use crate::{ blocking, request::{retry, RecvError}, routes::webfinger::WebFingerResponse, - DbPool, - LemmyError, + DbPool, LemmyError, }; use activitystreams_ext::{Ext1, Ext2}; use activitystreams_new::{ @@ -28,7 +27,6 @@ use activitystreams_new::{ actor::{ApActor, Group, Person}, object::{Page, Tombstone}, prelude::*, - primitives::XsdAnyUri, }; use actix_web::{body::Body, client::Client, HttpResponse}; use chrono::NaiveDateTime; @@ -37,8 +35,7 @@ use lemmy_db::{activity::do_insert_activity, user::User_}; use lemmy_utils::{convert_datetime, get_apub_protocol_string, settings::Settings, MentionData}; use log::debug; use serde::Serialize; -use std::str::FromStr; -use url::Url; +use url::{ParseError, Url}; type GroupExt = Ext2, GroupExtension, PublicKeyExtension>; type PersonExt = Ext1, PublicKeyExtension>; @@ -116,7 +113,7 @@ fn create_tombstone( let mut tombstone = Tombstone::new(); tombstone.set_id(object_id.parse()?); tombstone.set_former_type(former_type); - tombstone.set_deleted(convert_datetime(updated).into()); + tombstone.set_deleted(convert_datetime(updated)); Ok(tombstone) } else { Err(format_err!("Cant convert to tombstone because updated time was None.").into()) @@ -133,6 +130,7 @@ pub trait FromApub { apub: &Self::ApubType, client: &Client, pool: &DbPool, + actor_id: &Url, ) -> Result where Self: Sized; @@ -200,13 +198,12 @@ pub trait ApubLikeableType { ) -> Result<(), LemmyError>; } -pub fn get_shared_inbox(actor_id: &str) -> String { - let url = Url::parse(actor_id).unwrap(); +pub fn get_shared_inbox(actor_id: &Url) -> String { format!( "{}://{}{}/inbox", - &url.scheme(), - &url.host_str().unwrap(), - if let Some(port) = url.port() { + &actor_id.scheme(), + &actor_id.host_str().unwrap(), + if let Some(port) = actor_id.port() { format!(":{}", port) } else { "".to_string() @@ -216,7 +213,7 @@ pub fn get_shared_inbox(actor_id: &str) -> String { #[async_trait::async_trait(?Send)] pub trait ActorType { - fn actor_id(&self) -> String; + fn actor_id_str(&self) -> String; fn public_key(&self) -> String; fn private_key(&self) -> String; @@ -274,35 +271,40 @@ pub trait ActorType { /// For a given community, returns the inboxes of all followers. async fn get_follower_inboxes(&self, pool: &DbPool) -> Result, LemmyError>; - // TODO move these to the db rows - fn get_inbox_url(&self) -> String { - format!("{}/inbox", &self.actor_id()) + fn actor_id(&self) -> Result { + Url::parse(&self.actor_id_str()) } + // TODO move these to the db rows + fn get_inbox_url(&self) -> String { + format!("{}/inbox", &self.actor_id_str()) + } + + // TODO: make this return `Result fn get_shared_inbox_url(&self) -> String { - get_shared_inbox(&self.actor_id()) + get_shared_inbox(&self.actor_id().unwrap()) } fn get_outbox_url(&self) -> String { - format!("{}/outbox", &self.actor_id()) + format!("{}/outbox", &self.actor_id_str()) } fn get_followers_url(&self) -> String { - format!("{}/followers", &self.actor_id()) + format!("{}/followers", &self.actor_id_str()) } fn get_following_url(&self) -> String { - format!("{}/following", &self.actor_id()) + format!("{}/following", &self.actor_id_str()) } fn get_liked_url(&self) -> String { - format!("{}/liked", &self.actor_id()) + format!("{}/liked", &self.actor_id_str()) } fn get_public_key_ext(&self) -> PublicKeyExtension { PublicKey { - id: format!("{}#main-key", self.actor_id()), - owner: self.actor_id(), + id: format!("{}#main-key", self.actor_id_str()), + owner: self.actor_id_str(), public_key_pem: self.public_key(), } .to_ext() @@ -312,7 +314,7 @@ pub trait ActorType { pub async fn fetch_webfinger_url( mention: &MentionData, client: &Client, -) -> Result { +) -> Result { let fetch_url = format!( "{}://{}/.well-known/webfinger?resource=acct:{}@{}", get_apub_protocol_string(), @@ -337,7 +339,7 @@ pub async fn fetch_webfinger_url( link .href .to_owned() - .map(|u| XsdAnyUri::from_str(&u)) + .map(|u| Url::parse(&u)) .transpose()? .ok_or_else(|| format_err!("No href found.").into()) } diff --git a/server/src/apub/post.rs b/server/src/apub/post.rs index e7736605..039afe86 100644 --- a/server/src/apub/post.rs +++ b/server/src/apub/post.rs @@ -1,22 +1,14 @@ use crate::{ apub::{ activities::send_activity_to_community, - create_apub_response, - create_apub_tombstone_response, - create_tombstone, + create_apub_response, create_apub_tombstone_response, create_tombstone, extensions::page_extension::PageExtension, fetcher::{get_or_fetch_and_upsert_remote_community, get_or_fetch_and_upsert_remote_user}, - ActorType, - ApubLikeableType, - ApubObjectType, - FromApub, - PageExt, - ToApub, + ActorType, ApubLikeableType, ApubObjectType, FromApub, PageExt, ToApub, }, blocking, routes::DbPoolParam, - DbPool, - LemmyError, + DbPool, LemmyError, }; use activitystreams_ext::Ext1; use activitystreams_new::{ @@ -24,7 +16,6 @@ use activitystreams_new::{ context, object::{kind::PageType, Image, Page, Tombstone}, prelude::*, - primitives::{XsdAnyUri, XsdDateTime}, public, }; use actix_web::{body::Body, client::Client, web, HttpResponse}; @@ -36,7 +27,7 @@ use lemmy_db::{ }; use lemmy_utils::{convert_datetime, get_apub_protocol_string, settings::Settings}; use serde::Deserialize; -use std::str::FromStr; +use url::Url; #[derive(Deserialize)] pub struct PostQuery { @@ -77,11 +68,11 @@ impl ToApub for Post { // TODO: need to set proper context defining sensitive/commentsEnabled fields // https://git.asonix.dog/Aardwolf/activitystreams/issues/5 .set_context(context()) - .set_id(self.ap_id.parse::()?) + .set_id(self.ap_id.parse::()?) // Use summary field to be consistent with mastodon content warning. // https://mastodon.xyz/@Louisa/103987265222901387.json .set_summary(self.name.to_owned()) - .set_published(convert_datetime(self.published).into()) + .set_published(convert_datetime(self.published)) .set_to(community.actor_id) .set_attributed_to(creator.actor_id); @@ -128,7 +119,7 @@ impl ToApub for Post { } if let Some(u) = self.updated { - page.set_updated(XsdDateTime::from(convert_datetime(u))); + page.set_updated(convert_datetime(u)); } let ext = PageExtension { @@ -143,7 +134,7 @@ impl ToApub for Post { self.deleted, &self.ap_id, self.updated, - PageType.to_string(), + PageType::Page.to_string(), ) } } @@ -157,11 +148,12 @@ impl FromApub for PostForm { page: &PageExt, client: &Client, pool: &DbPool, + actor_id: &Url, ) -> Result { let ext = &page.ext_one; let creator_actor_id = page .inner - .attributed_to + .attributed_to() .as_ref() .unwrap() .as_single_xsd_any_uri() @@ -171,20 +163,19 @@ impl FromApub for PostForm { let community_actor_id = page .inner - .to + .to() .as_ref() .unwrap() .as_single_xsd_any_uri() - .unwrap() - .as_str(); + .unwrap(); let community = get_or_fetch_and_upsert_remote_community(community_actor_id, client, pool).await?; - let thumbnail_url = match &page.inner.image { + let thumbnail_url = match &page.inner.image() { Some(any_image) => Image::from_any_base(any_image.to_owned().as_one().unwrap().to_owned())? .unwrap() - .url + .url() .unwrap() .as_single_xsd_any_uri() .map(|u| u.to_string()), @@ -193,10 +184,10 @@ impl FromApub for PostForm { let (embed_title, embed_description, embed_html) = match page.inner.preview() { Some(preview) => { - let preview_page = Page::from_any_base(preview.as_one().unwrap().to_owned())?.unwrap(); + let preview_page = Page::from_any_base(preview.one().unwrap().to_owned())?.unwrap(); let name = preview_page .name() - .map(|n| n.as_single_xsd_string().unwrap().to_string()); + .map(|n| n.as_one().unwrap().as_xsd_string().unwrap().to_string()); let summary = preview_page .summary() .map(|s| s.as_single_xsd_string().unwrap().to_string()); @@ -210,18 +201,18 @@ impl FromApub for PostForm { let url = page .inner - .url + .url() .as_ref() .map(|u| u.as_single_xsd_string().unwrap().to_string()); let body = page .inner - .content + .content() .as_ref() .map(|c| c.as_single_xsd_string().unwrap().to_string()); Ok(PostForm { name: page .inner - .summary + .summary() .as_ref() .unwrap() .as_single_xsd_string() @@ -235,14 +226,14 @@ impl FromApub for PostForm { locked: Some(!ext.comments_enabled), published: page .inner - .published + .published() .as_ref() - .map(|u| u.as_ref().to_owned().naive_local()), + .map(|u| u.to_owned().naive_local()), updated: page .inner - .updated + .updated() .as_ref() - .map(|u| u.as_ref().to_owned().naive_local()), + .map(|u| u.to_owned().naive_local()), deleted: None, nsfw: ext.sensitive, stickied: None, // -> put it in "featured" collection of the community @@ -250,7 +241,11 @@ impl FromApub for PostForm { embed_description, embed_html, thumbnail_url, - ap_id: page.inner.id().unwrap().to_string(), + ap_id: page + .inner + .id(actor_id.domain().unwrap())? + .unwrap() + .to_string(), local: false, }) } @@ -275,7 +270,7 @@ impl ApubObjectType for Post { let mut create = Create::new(creator.actor_id.to_owned(), page.into_any_base()?); create .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -308,7 +303,7 @@ impl ApubObjectType for Post { let mut update = Update::new(creator.actor_id.to_owned(), page.into_any_base()?); update .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -339,7 +334,7 @@ impl ApubObjectType for Post { let mut delete = Delete::new(creator.actor_id.to_owned(), page.into_any_base()?); delete .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -370,7 +365,7 @@ impl ApubObjectType for Post { let mut delete = Delete::new(creator.actor_id.to_owned(), page.into_any_base()?); delete .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -380,7 +375,7 @@ impl ApubObjectType for Post { let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); undo .set_context(context()) - .set_id(XsdAnyUri::from_str(&undo_id)?) + .set_id(Url::parse(&undo_id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -411,7 +406,7 @@ impl ApubObjectType for Post { let mut remove = Remove::new(mod_.actor_id.to_owned(), page.into_any_base()?); remove .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -442,7 +437,7 @@ impl ApubObjectType for Post { let mut remove = Remove::new(mod_.actor_id.to_owned(), page.into_any_base()?); remove .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -451,7 +446,7 @@ impl ApubObjectType for Post { let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?); undo .set_context(context()) - .set_id(XsdAnyUri::from_str(&undo_id)?) + .set_id(Url::parse(&undo_id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -486,7 +481,7 @@ impl ApubLikeableType for Post { let mut like = Like::new(creator.actor_id.to_owned(), page.into_any_base()?); like .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -518,7 +513,7 @@ impl ApubLikeableType for Post { let mut dislike = Dislike::new(creator.actor_id.to_owned(), page.into_any_base()?); dislike .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -550,7 +545,7 @@ impl ApubLikeableType for Post { let mut like = Like::new(creator.actor_id.to_owned(), page.into_any_base()?); like .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); @@ -560,7 +555,7 @@ impl ApubLikeableType for Post { let mut undo = Undo::new(creator.actor_id.to_owned(), like.into_any_base()?); undo .set_context(context()) - .set_id(XsdAnyUri::from_str(&undo_id)?) + .set_id(Url::parse(&undo_id)?) .set_to(public()) .set_many_ccs(vec![community.get_followers_url()]); diff --git a/server/src/apub/private_message.rs b/server/src/apub/private_message.rs index 5fb00be9..17d5c09c 100644 --- a/server/src/apub/private_message.rs +++ b/server/src/apub/private_message.rs @@ -1,23 +1,15 @@ use crate::{ apub::{ - activities::send_activity, - create_tombstone, - fetcher::get_or_fetch_and_upsert_remote_user, - insert_activity, - ApubObjectType, - FromApub, - ToApub, + activities::send_activity, create_tombstone, fetcher::get_or_fetch_and_upsert_remote_user, + insert_activity, ApubObjectType, FromApub, ToApub, }, - blocking, - DbPool, - LemmyError, + blocking, DbPool, LemmyError, }; use activitystreams_new::{ activity::{Create, Delete, Undo, Update}, context, object::{kind::NoteType, Note, Tombstone}, prelude::*, - primitives::{XsdAnyUri, XsdDateTime}, }; use actix_web::client::Client; use lemmy_db::{ @@ -26,7 +18,7 @@ use lemmy_db::{ Crud, }; use lemmy_utils::convert_datetime; -use std::str::FromStr; +use url::Url; #[async_trait::async_trait(?Send)] impl ToApub for PrivateMessage { @@ -43,14 +35,14 @@ impl ToApub for PrivateMessage { private_message .set_context(context()) - .set_id(XsdAnyUri::from_str(&self.ap_id.to_owned())?) - .set_published(XsdDateTime::from(convert_datetime(self.published))) + .set_id(Url::parse(&self.ap_id.to_owned())?) + .set_published(convert_datetime(self.published)) .set_content(self.content.to_owned()) .set_to(recipient.actor_id) .set_attributed_to(creator.actor_id); if let Some(u) = self.updated { - private_message.set_updated(XsdDateTime::from(convert_datetime(u))); + private_message.set_updated(convert_datetime(u)); } Ok(private_message) @@ -61,7 +53,7 @@ impl ToApub for PrivateMessage { self.deleted, &self.ap_id, self.updated, - NoteType.to_string(), + NoteType::Note.to_string(), ) } } @@ -75,6 +67,7 @@ impl FromApub for PrivateMessageForm { note: &Note, client: &Client, pool: &DbPool, + actor_id: &Url, ) -> Result { let creator_actor_id = note .attributed_to() @@ -98,13 +91,11 @@ impl FromApub for PrivateMessageForm { .as_single_xsd_string() .unwrap() .to_string(), - published: note - .published() - .map(|u| u.as_ref().to_owned().naive_local()), - updated: note.updated().map(|u| u.as_ref().to_owned().naive_local()), + published: note.published().map(|u| u.to_owned().naive_local()), + updated: note.updated().map(|u| u.to_owned().naive_local()), deleted: None, read: None, - ap_id: note.id().unwrap().to_string(), + ap_id: note.id(actor_id.domain().unwrap())?.unwrap().to_string(), local: false, }) } @@ -129,7 +120,7 @@ impl ApubObjectType for PrivateMessage { let to = format!("{}/inbox", recipient.actor_id); create .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(to.clone()); insert_activity(creator.id, create.clone(), true, pool).await?; @@ -155,7 +146,7 @@ impl ApubObjectType for PrivateMessage { let to = format!("{}/inbox", recipient.actor_id); update .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(to.clone()); insert_activity(creator.id, update.clone(), true, pool).await?; @@ -180,7 +171,7 @@ impl ApubObjectType for PrivateMessage { let to = format!("{}/inbox", recipient.actor_id); delete .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(to.clone()); insert_activity(creator.id, delete.clone(), true, pool).await?; @@ -205,7 +196,7 @@ impl ApubObjectType for PrivateMessage { let to = format!("{}/inbox", recipient.actor_id); delete .set_context(context()) - .set_id(XsdAnyUri::from_str(&id)?) + .set_id(Url::parse(&id)?) .set_to(to.clone()); // TODO @@ -214,7 +205,7 @@ impl ApubObjectType for PrivateMessage { let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); undo .set_context(context()) - .set_id(XsdAnyUri::from_str(&undo_id)?) + .set_id(Url::parse(&undo_id)?) .set_to(to.clone()); insert_activity(creator.id, undo.clone(), true, pool).await?; diff --git a/server/src/apub/shared_inbox.rs b/server/src/apub/shared_inbox.rs index d030d57b..708cc0b2 100644 --- a/server/src/apub/shared_inbox.rs +++ b/server/src/apub/shared_inbox.rs @@ -8,15 +8,10 @@ use crate::{ community::do_announce, extensions::signatures::verify, fetcher::{ - get_or_fetch_and_insert_remote_comment, - get_or_fetch_and_insert_remote_post, - get_or_fetch_and_upsert_remote_community, - get_or_fetch_and_upsert_remote_user, + get_or_fetch_and_insert_remote_comment, get_or_fetch_and_insert_remote_post, + get_or_fetch_and_upsert_remote_community, get_or_fetch_and_upsert_remote_user, }, - insert_activity, - FromApub, - GroupExt, - PageExt, + insert_activity, ActorType, FromApub, GroupExt, PageExt, }, blocking, routes::{ChatServerParam, DbPoolParam}, @@ -24,15 +19,14 @@ use crate::{ server::{SendComment, SendCommunityRoomMessage, SendPost}, UserOperation, }, - DbPool, - LemmyError, + DbPool, LemmyError, }; use activitystreams_new::{ - activity::{Announce, Create, Delete, Dislike, Like, Remove, Undo, Update}, - base::AnyBase, + activity::{ActorAndObjectRef, Announce, Create, Delete, Dislike, Like, Remove, Undo, Update}, + base::{AnyBase, AsBase}, + error::DomainError, object::Note, prelude::{ExtendsExt, *}, - primitives::XsdAnyUri, }; use actix_web::{client::Client, web, HttpRequest, HttpResponse}; use lemmy_db::{ @@ -43,13 +37,14 @@ use lemmy_db::{ naive_now, post::{Post, PostForm, PostLike, PostLikeForm}, post_view::PostView, - Crud, - Likeable, + user::User_, + Crud, Likeable, }; use lemmy_utils::scrape_text_for_mentions; use log::debug; use serde::{Deserialize, Serialize}; use std::fmt::Debug; +use url::Url; #[serde(untagged)] #[derive(Serialize, Deserialize, Debug, Clone)] @@ -66,6 +61,7 @@ pub enum SharedAcceptedObjects { impl SharedAcceptedObjects { // TODO: these shouldnt be necessary anymore + // https://git.asonix.dog/asonix/ap-relay/src/branch/main/src/apub.rs fn object(&self) -> Option { match self { SharedAcceptedObjects::Create(c) => c.object().to_owned().one(), @@ -78,18 +74,18 @@ impl SharedAcceptedObjects { SharedAcceptedObjects::Announce(a) => a.object().to_owned().one(), } } - fn sender(&self) -> XsdAnyUri { + fn sender(&self) -> Result<&Url, DomainError> { let uri = match self { - SharedAcceptedObjects::Create(c) => c.actor.to_owned().single_xsd_any_uri(), - SharedAcceptedObjects::Update(u) => u.actor.to_owned().single_xsd_any_uri(), - SharedAcceptedObjects::Like(l) => l.actor.to_owned().single_xsd_any_uri(), - SharedAcceptedObjects::Dislike(d) => d.actor.to_owned().single_xsd_any_uri(), - SharedAcceptedObjects::Delete(d) => d.actor.to_owned().single_xsd_any_uri(), - SharedAcceptedObjects::Undo(d) => d.actor.to_owned().single_xsd_any_uri(), - SharedAcceptedObjects::Remove(r) => r.actor.to_owned().single_xsd_any_uri(), - SharedAcceptedObjects::Announce(a) => a.actor.to_owned().single_xsd_any_uri(), + SharedAcceptedObjects::Create(c) => c.actor()?.as_single_xsd_any_uri(), + SharedAcceptedObjects::Update(u) => u.actor()?.as_single_xsd_any_uri(), + SharedAcceptedObjects::Like(l) => l.actor()?.as_single_xsd_any_uri(), + SharedAcceptedObjects::Dislike(d) => d.actor()?.as_single_xsd_any_uri(), + SharedAcceptedObjects::Delete(d) => d.actor()?.as_single_xsd_any_uri(), + SharedAcceptedObjects::Undo(d) => d.actor()?.as_single_xsd_any_uri(), + SharedAcceptedObjects::Remove(r) => r.actor()?.as_single_xsd_any_uri(), + SharedAcceptedObjects::Announce(a) => a.actor()?.as_single_xsd_any_uri(), }; - uri.unwrap() + Ok(uri.unwrap()) } fn cc(&self) -> String { let cc = match self { @@ -129,7 +125,7 @@ pub async fn shared_inbox( let json = serde_json::to_string(&activity)?; debug!("Shared inbox received activity: {}", json); - let sender = &activity.to_owned().sender(); + let sender = &activity.sender()?.clone(); let cc = activity.to_owned().cc(); // TODO: this is hacky, we should probably send the community id directly somehow let to = cc.replace("/followers", ""); @@ -138,7 +134,7 @@ pub async fn shared_inbox( match get_or_fetch_and_upsert_remote_user(sender, &client, pool).await { Ok(u) => verify(&request, &u)?, Err(_) => { - let c = get_or_fetch_and_upsert_remote_community(&sender.to_string(), &client, pool).await?; + let c = get_or_fetch_and_upsert_remote_community(sender, &client, pool).await?; verify(&request, &c)?; } } @@ -222,7 +218,7 @@ pub async fn shared_inbox( async fn announce_activity_if_valid( activity: AnyBase, community_uri: &str, - sender: &XsdAnyUri, + sender: &Url, client: &Client, pool: &DbPool, ) -> Result { @@ -247,12 +243,12 @@ async fn receive_announce( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let object = announce.to_owned().object.one().unwrap(); + let object = announce.to_owned().object().clone().one().unwrap(); // TODO: too much copy paste match object.kind_str() { Some("Create") => { let create = Create::from_any_base(object)?.unwrap(); - match create.object.as_single_kind_str() { + match create.object().as_single_kind_str() { Some("Page") => receive_create_post(create, client, pool, chat_server).await, Some("Note") => receive_create_comment(create, client, pool, chat_server).await, _ => receive_unhandled_activity(announce), @@ -260,7 +256,7 @@ async fn receive_announce( } Some("Update") => { let update = Update::from_any_base(object)?.unwrap(); - match update.object.as_single_kind_str() { + match update.object().as_single_kind_str() { Some("Page") => receive_update_post(update, client, pool, chat_server).await, Some("Note") => receive_update_comment(update, client, pool, chat_server).await, _ => receive_unhandled_activity(announce), @@ -268,7 +264,7 @@ async fn receive_announce( } Some("Like") => { let like = Like::from_any_base(object)?.unwrap(); - match like.object.as_single_kind_str() { + match like.object().as_single_kind_str() { Some("Page") => receive_like_post(like, client, pool, chat_server).await, Some("Note") => receive_like_comment(like, client, pool, chat_server).await, _ => receive_unhandled_activity(announce), @@ -276,7 +272,7 @@ async fn receive_announce( } Some("Dislike") => { let dislike = Dislike::from_any_base(object)?.unwrap(); - match dislike.object.as_single_kind_str() { + match dislike.object().as_single_kind_str() { Some("Page") => receive_dislike_post(dislike, client, pool, chat_server).await, Some("Note") => receive_dislike_comment(dislike, client, pool, chat_server).await, _ => receive_unhandled_activity(announce), @@ -284,7 +280,7 @@ async fn receive_announce( } Some("Delete") => { let delete = Delete::from_any_base(object)?.unwrap(); - match delete.object.as_single_kind_str() { + match delete.object().as_single_kind_str() { Some("Page") => receive_delete_post(delete, client, pool, chat_server).await, Some("Note") => receive_delete_comment(delete, client, pool, chat_server).await, _ => receive_unhandled_activity(announce), @@ -292,7 +288,7 @@ async fn receive_announce( } Some("Remove") => { let remove = Remove::from_any_base(object)?.unwrap(); - match remove.object.as_single_kind_str() { + match remove.object().as_single_kind_str() { Some("Page") => receive_remove_post(remove, client, pool, chat_server).await, Some("Note") => receive_remove_comment(remove, client, pool, chat_server).await, _ => receive_unhandled_activity(announce), @@ -300,7 +296,7 @@ async fn receive_announce( } Some("Undo") => { let undo = Undo::from_any_base(object)?.unwrap(); - match undo.object.as_single_kind_str() { + match undo.object().as_single_kind_str() { Some("Delete") => receive_undo_delete(undo, client, pool, chat_server).await, Some("Remove") => receive_undo_remove(undo, client, pool, chat_server).await, Some("Like") => receive_undo_like(undo, client, pool, chat_server).await, @@ -319,21 +315,31 @@ where Ok(HttpResponse::NotImplemented().finish()) } +async fn get_user_from_activity( + activity: &T, + client: &Client, + pool: &DbPool, +) -> Result +where + T: AsBase + ActorAndObjectRef, +{ + let actor = activity.actor()?; + let user_uri = actor.as_single_xsd_any_uri().unwrap(); + get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await +} + async fn receive_create_post( create: Create, client: &Client, pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let page = PageExt::from_any_base(create.object.to_owned().one().unwrap())?.unwrap(); - - let user_uri = create.actor.to_owned().single_xsd_any_uri().unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&create, client, pool).await?; + let page = PageExt::from_any_base(create.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, create, false, pool).await?; - let post = PostForm::from_apub(&page, client, pool).await?; + let post = PostForm::from_apub(&page, client, pool, &user.actor_id()?).await?; let inserted_post = blocking(pool, move |conn| Post::create(conn, &post)).await??; @@ -361,15 +367,12 @@ async fn receive_create_comment( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let note = Note::from_any_base(create.object.to_owned().one().unwrap())?.unwrap(); - - let user_uri = create.actor.to_owned().single_xsd_any_uri().unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&create, client, pool).await?; + let note = Note::from_any_base(create.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, create, false, pool).await?; - let comment = CommentForm::from_apub(¬e, client, pool).await?; + let comment = CommentForm::from_apub(¬e, client, pool, &user.actor_id()?).await?; let inserted_comment = blocking(pool, move |conn| Comment::create(conn, &comment)).await??; @@ -410,17 +413,14 @@ async fn receive_update_post( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let page = PageExt::from_any_base(update.object.to_owned().one().unwrap())?.unwrap(); - - let user_uri = update.actor.to_owned().single_xsd_any_uri().unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&update, client, pool).await?; + let page = PageExt::from_any_base(update.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, update, false, pool).await?; - let post = PostForm::from_apub(&page, client, pool).await?; + let post = PostForm::from_apub(&page, client, pool, &user.actor_id()?).await?; - let post_id = get_or_fetch_and_insert_remote_post(&post.ap_id, client, pool) + let post_id = get_or_fetch_and_insert_remote_post(&post.get_ap_id()?, client, pool) .await? .id; @@ -446,17 +446,14 @@ async fn receive_like_post( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let page = PageExt::from_any_base(like.object.to_owned().one().unwrap())?.unwrap(); - - let user_uri = like.actor.to_owned().single_xsd_any_uri().unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&like, client, pool).await?; + let page = PageExt::from_any_base(like.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, like, false, pool).await?; - let post = PostForm::from_apub(&page, client, pool).await?; + let post = PostForm::from_apub(&page, client, pool, &user.actor_id()?).await?; - let post_id = get_or_fetch_and_insert_remote_post(&post.ap_id, client, pool) + let post_id = get_or_fetch_and_insert_remote_post(&post.get_ap_id()?, client, pool) .await? .id; @@ -491,17 +488,14 @@ async fn receive_dislike_post( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let page = PageExt::from_any_base(dislike.object.to_owned().one().unwrap())?.unwrap(); - - let user_uri = dislike.actor.to_owned().single_xsd_any_uri().unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&dislike, client, pool).await?; + let page = PageExt::from_any_base(dislike.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, dislike, false, pool).await?; - let post = PostForm::from_apub(&page, client, pool).await?; + let post = PostForm::from_apub(&page, client, pool, &user.actor_id()?).await?; - let post_id = get_or_fetch_and_insert_remote_post(&post.ap_id, client, pool) + let post_id = get_or_fetch_and_insert_remote_post(&post.get_ap_id()?, client, pool) .await? .id; @@ -536,17 +530,14 @@ async fn receive_update_comment( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let note = Note::from_any_base(update.object.to_owned().one().unwrap())?.unwrap(); - - let user_uri = update.actor.to_owned().single_xsd_any_uri().unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let note = Note::from_any_base(update.object().to_owned().one().unwrap())?.unwrap(); + let user = get_user_from_activity(&update, client, pool).await?; insert_activity(user.id, update, false, pool).await?; - let comment = CommentForm::from_apub(¬e, client, pool).await?; + let comment = CommentForm::from_apub(¬e, client, pool, &user.actor_id()?).await?; - let comment_id = get_or_fetch_and_insert_remote_comment(&comment.ap_id, client, pool) + let comment_id = get_or_fetch_and_insert_remote_comment(&comment.get_ap_id()?, client, pool) .await? .id; @@ -585,17 +576,14 @@ async fn receive_like_comment( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let note = Note::from_any_base(like.object.to_owned().one().unwrap())?.unwrap(); - - let user_uri = like.actor.to_owned().single_xsd_any_uri().unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let note = Note::from_any_base(like.object().to_owned().one().unwrap())?.unwrap(); + let user = get_user_from_activity(&like, client, pool).await?; insert_activity(user.id, like, false, pool).await?; - let comment = CommentForm::from_apub(¬e, client, pool).await?; + let comment = CommentForm::from_apub(¬e, client, pool, &user.actor_id()?).await?; - let comment_id = get_or_fetch_and_insert_remote_comment(&comment.ap_id, client, pool) + let comment_id = get_or_fetch_and_insert_remote_comment(&comment.get_ap_id()?, client, pool) .await? .id; @@ -637,17 +625,14 @@ async fn receive_dislike_comment( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let note = Note::from_any_base(dislike.object.to_owned().one().unwrap())?.unwrap(); - - let user_uri = dislike.actor.to_owned().single_xsd_any_uri().unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let note = Note::from_any_base(dislike.object().to_owned().one().unwrap())?.unwrap(); + let user = get_user_from_activity(&dislike, client, pool).await?; insert_activity(user.id, dislike, false, pool).await?; - let comment = CommentForm::from_apub(¬e, client, pool).await?; + let comment = CommentForm::from_apub(¬e, client, pool, &user.actor_id()?).await?; - let comment_id = get_or_fetch_and_insert_remote_comment(&comment.ap_id, client, pool) + let comment_id = get_or_fetch_and_insert_remote_comment(&comment.get_ap_id()?, client, pool) .await? .id; @@ -689,15 +674,12 @@ async fn receive_delete_community( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let user_uri = delete.actor.to_owned().single_xsd_any_uri().unwrap(); - - let group = GroupExt::from_any_base(delete.object.to_owned().one().unwrap())?.unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let group = GroupExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); + let user = get_user_from_activity(&delete, client, pool).await?; insert_activity(user.id, delete, false, pool).await?; - let community_actor_id = CommunityForm::from_apub(&group, client, pool) + let community_actor_id = CommunityForm::from_apub(&group, client, pool, &user.actor_id()?) .await? .actor_id; @@ -756,15 +738,12 @@ async fn receive_remove_community( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let mod_uri = remove.actor.to_owned().single_xsd_any_uri().unwrap(); - - let group = GroupExt::from_any_base(remove.object.to_owned().one().unwrap())?.unwrap(); - - let mod_ = get_or_fetch_and_upsert_remote_user(&mod_uri, client, pool).await?; + let mod_ = get_user_from_activity(&remove, client, pool).await?; + let group = GroupExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); insert_activity(mod_.id, remove, false, pool).await?; - let community_actor_id = CommunityForm::from_apub(&group, client, pool) + let community_actor_id = CommunityForm::from_apub(&group, client, pool, &mod_.actor_id()?) .await? .actor_id; @@ -823,15 +802,14 @@ async fn receive_delete_post( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let user_uri = delete.actor.to_owned().single_xsd_any_uri().unwrap(); - - let page = PageExt::from_any_base(delete.object.to_owned().one().unwrap())?.unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&delete, client, pool).await?; + let page = PageExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, delete, false, pool).await?; - let post_ap_id = PostForm::from_apub(&page, client, pool).await?.ap_id; + let post_ap_id = PostForm::from_apub(&page, client, pool, &user.actor_id()?) + .await? + .get_ap_id()?; let post = get_or_fetch_and_insert_remote_post(&post_ap_id, client, pool).await?; @@ -879,15 +857,14 @@ async fn receive_remove_post( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let mod_uri = remove.actor.to_owned().single_xsd_any_uri().unwrap(); - - let page = PageExt::from_any_base(remove.object.to_owned().one().unwrap())?.unwrap(); - - let mod_ = get_or_fetch_and_upsert_remote_user(&mod_uri, client, pool).await?; + let mod_ = get_user_from_activity(&remove, client, pool).await?; + let page = PageExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); insert_activity(mod_.id, remove, false, pool).await?; - let post_ap_id = PostForm::from_apub(&page, client, pool).await?.ap_id; + let post_ap_id = PostForm::from_apub(&page, client, pool, &mod_.actor_id()?) + .await? + .get_ap_id()?; let post = get_or_fetch_and_insert_remote_post(&post_ap_id, client, pool).await?; @@ -935,15 +912,14 @@ async fn receive_delete_comment( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let user_uri = delete.actor.to_owned().single_xsd_any_uri().unwrap(); - - let note = Note::from_any_base(delete.object.to_owned().one().unwrap())?.unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&delete, client, pool).await?; + let note = Note::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, delete, false, pool).await?; - let comment_ap_id = CommentForm::from_apub(¬e, client, pool).await?.ap_id; + let comment_ap_id = CommentForm::from_apub(¬e, client, pool, &user.actor_id()?) + .await? + .get_ap_id()?; let comment = get_or_fetch_and_insert_remote_comment(&comment_ap_id, client, pool).await?; @@ -993,15 +969,14 @@ async fn receive_remove_comment( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let mod_uri = remove.actor.to_owned().single_xsd_any_uri().unwrap(); - - let note = Note::from_any_base(remove.object.to_owned().one().unwrap())?.unwrap(); - - let mod_ = get_or_fetch_and_upsert_remote_user(&mod_uri, client, pool).await?; + let mod_ = get_user_from_activity(&remove, client, pool).await?; + let note = Note::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); insert_activity(mod_.id, remove, false, pool).await?; - let comment_ap_id = CommentForm::from_apub(¬e, client, pool).await?.ap_id; + let comment_ap_id = CommentForm::from_apub(¬e, client, pool, &mod_.actor_id()?) + .await? + .get_ap_id()?; let comment = get_or_fetch_and_insert_remote_comment(&comment_ap_id, client, pool).await?; @@ -1051,9 +1026,9 @@ async fn receive_undo_delete( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let delete = Delete::from_any_base(undo.object.to_owned().one().unwrap())?.unwrap(); + let delete = Delete::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap(); - let type_ = delete.object.as_single_kind_str().unwrap(); + let type_ = delete.object().as_single_kind_str().unwrap(); match type_ { "Note" => receive_undo_delete_comment(delete, client, pool, chat_server).await, "Page" => receive_undo_delete_post(delete, client, pool, chat_server).await, @@ -1068,9 +1043,9 @@ async fn receive_undo_remove( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let remove = Remove::from_any_base(undo.object.to_owned().one().unwrap())?.unwrap(); + let remove = Remove::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap(); - let type_ = remove.object.as_single_kind_str().unwrap(); + let type_ = remove.object().as_single_kind_str().unwrap(); match type_ { "Note" => receive_undo_remove_comment(remove, client, pool, chat_server).await, "Page" => receive_undo_remove_post(remove, client, pool, chat_server).await, @@ -1085,15 +1060,14 @@ async fn receive_undo_delete_comment( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let user_uri = delete.actor.to_owned().single_xsd_any_uri().unwrap(); - - let note = Note::from_any_base(delete.object.to_owned().one().unwrap())?.unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&delete, client, pool).await?; + let note = Note::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, delete, false, pool).await?; - let comment_ap_id = CommentForm::from_apub(¬e, client, pool).await?.ap_id; + let comment_ap_id = CommentForm::from_apub(¬e, client, pool, &user.actor_id()?) + .await? + .get_ap_id()?; let comment = get_or_fetch_and_insert_remote_comment(&comment_ap_id, client, pool).await?; @@ -1143,15 +1117,14 @@ async fn receive_undo_remove_comment( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let mod_uri = remove.actor.to_owned().single_xsd_any_uri().unwrap(); - - let note = Note::from_any_base(remove.object.to_owned().one().unwrap())?.unwrap(); - - let mod_ = get_or_fetch_and_upsert_remote_user(&mod_uri, client, pool).await?; + let mod_ = get_user_from_activity(&remove, client, pool).await?; + let note = Note::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); insert_activity(mod_.id, remove, false, pool).await?; - let comment_ap_id = CommentForm::from_apub(¬e, client, pool).await?.ap_id; + let comment_ap_id = CommentForm::from_apub(¬e, client, pool, &mod_.actor_id()?) + .await? + .get_ap_id()?; let comment = get_or_fetch_and_insert_remote_comment(&comment_ap_id, client, pool).await?; @@ -1201,15 +1174,14 @@ async fn receive_undo_delete_post( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let user_uri = delete.actor.to_owned().single_xsd_any_uri().unwrap(); - - let page = PageExt::from_any_base(delete.object.to_owned().one().unwrap())?.unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&delete, client, pool).await?; + let page = PageExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, delete, false, pool).await?; - let post_ap_id = PostForm::from_apub(&page, client, pool).await?.ap_id; + let post_ap_id = PostForm::from_apub(&page, client, pool, &user.actor_id()?) + .await? + .get_ap_id()?; let post = get_or_fetch_and_insert_remote_post(&post_ap_id, client, pool).await?; @@ -1257,15 +1229,14 @@ async fn receive_undo_remove_post( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let mod_uri = remove.actor.to_owned().single_xsd_any_uri().unwrap(); - - let page = PageExt::from_any_base(remove.object.to_owned().one().unwrap())?.unwrap(); - - let mod_ = get_or_fetch_and_upsert_remote_user(&mod_uri, client, pool).await?; + let mod_ = get_user_from_activity(&remove, client, pool).await?; + let page = PageExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); insert_activity(mod_.id, remove, false, pool).await?; - let post_ap_id = PostForm::from_apub(&page, client, pool).await?.ap_id; + let post_ap_id = PostForm::from_apub(&page, client, pool, &mod_.actor_id()?) + .await? + .get_ap_id()?; let post = get_or_fetch_and_insert_remote_post(&post_ap_id, client, pool).await?; @@ -1313,15 +1284,12 @@ async fn receive_undo_delete_community( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let user_uri = delete.actor.to_owned().single_xsd_any_uri().unwrap(); - - let group = GroupExt::from_any_base(delete.object.to_owned().one().unwrap())?.unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&delete, client, pool).await?; + let group = GroupExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, delete, false, pool).await?; - let community_actor_id = CommunityForm::from_apub(&group, client, pool) + let community_actor_id = CommunityForm::from_apub(&group, client, pool, &user.actor_id()?) .await? .actor_id; @@ -1380,15 +1348,12 @@ async fn receive_undo_remove_community( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let mod_uri = remove.actor.to_owned().single_xsd_any_uri().unwrap(); - - let group = GroupExt::from_any_base(remove.object.to_owned().one().unwrap())?.unwrap(); - - let mod_ = get_or_fetch_and_upsert_remote_user(&mod_uri, client, pool).await?; + let mod_ = get_user_from_activity(&remove, client, pool).await?; + let group = GroupExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap(); insert_activity(mod_.id, remove, false, pool).await?; - let community_actor_id = CommunityForm::from_apub(&group, client, pool) + let community_actor_id = CommunityForm::from_apub(&group, client, pool, &mod_.actor_id()?) .await? .actor_id; @@ -1447,9 +1412,9 @@ async fn receive_undo_like( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let like = Like::from_any_base(undo.object.to_owned().one().unwrap())?.unwrap(); + let like = Like::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap(); - let type_ = like.object.as_single_kind_str().unwrap(); + let type_ = like.object().as_single_kind_str().unwrap(); match type_ { "Note" => receive_undo_like_comment(like, client, pool, chat_server).await, "Page" => receive_undo_like_post(like, client, pool, chat_server).await, @@ -1463,17 +1428,14 @@ async fn receive_undo_like_comment( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let note = Note::from_any_base(like.object.to_owned().one().unwrap())?.unwrap(); - - let user_uri = like.actor.to_owned().single_xsd_any_uri().unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&like, client, pool).await?; + let note = Note::from_any_base(like.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, like, false, pool).await?; - let comment = CommentForm::from_apub(¬e, client, pool).await?; + let comment = CommentForm::from_apub(¬e, client, pool, &user.actor_id()?).await?; - let comment_id = get_or_fetch_and_insert_remote_comment(&comment.ap_id, client, pool) + let comment_id = get_or_fetch_and_insert_remote_comment(&comment.get_ap_id()?, client, pool) .await? .id; @@ -1511,17 +1473,14 @@ async fn receive_undo_like_post( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let page = PageExt::from_any_base(like.object.to_owned().one().unwrap())?.unwrap(); - - let user_uri = like.actor.to_owned().single_xsd_any_uri().unwrap(); - - let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; + let user = get_user_from_activity(&like, client, pool).await?; + let page = PageExt::from_any_base(like.object().to_owned().one().unwrap())?.unwrap(); insert_activity(user.id, like, false, pool).await?; - let post = PostForm::from_apub(&page, client, pool).await?; + let post = PostForm::from_apub(&page, client, pool, &user.actor_id()?).await?; - let post_id = get_or_fetch_and_insert_remote_post(&post.ap_id, client, pool) + let post_id = get_or_fetch_and_insert_remote_post(&post.get_ap_id()?, client, pool) .await? .id; diff --git a/server/src/apub/user.rs b/server/src/apub/user.rs index 425a1248..4ebfe77b 100644 --- a/server/src/apub/user.rs +++ b/server/src/apub/user.rs @@ -1,18 +1,12 @@ use crate::{ api::claims::Claims, apub::{ - activities::send_activity, - create_apub_response, - insert_activity, - ActorType, - FromApub, - PersonExt, - ToApub, + activities::send_activity, create_apub_response, insert_activity, ActorType, FromApub, + PersonExt, ToApub, }, blocking, routes::DbPoolParam, - DbPool, - LemmyError, + DbPool, LemmyError, }; use activitystreams_ext::Ext1; use activitystreams_new::{ @@ -21,16 +15,15 @@ use activitystreams_new::{ context, object::{Image, Tombstone}, prelude::*, - primitives::{XsdAnyUri, XsdDateTime}, }; use actix_web::{body::Body, client::Client, web, HttpResponse}; -use failure::_core::str::FromStr; use lemmy_db::{ naive_now, user::{UserForm, User_}, }; use lemmy_utils::convert_datetime; use serde::Deserialize; +use url::Url; #[derive(Deserialize)] pub struct UserQuery { @@ -47,12 +40,12 @@ impl ToApub for User_ { let mut person = Person::new(); person .set_context(context()) - .set_id(XsdAnyUri::from_str(&self.actor_id)?) + .set_id(Url::parse(&self.actor_id)?) .set_name(self.name.to_owned()) - .set_published(XsdDateTime::from(convert_datetime(self.published))); + .set_published(convert_datetime(self.published)); if let Some(u) = self.updated { - person.set_updated(XsdDateTime::from(convert_datetime(u))); + person.set_updated(convert_datetime(u)); } if let Some(avatar_url) = &self.avatar { @@ -85,7 +78,7 @@ impl ToApub for User_ { #[async_trait::async_trait(?Send)] impl ActorType for User_ { - fn actor_id(&self) -> String { + fn actor_id_str(&self) -> String { self.actor_id.to_owned() } @@ -130,7 +123,7 @@ impl ActorType for User_ { // TODO // Undo that fake activity let undo_id = format!("{}/undo/follow/{}", self.actor_id, uuid::Uuid::new_v4()); - let mut undo = Undo::new(self.actor_id.parse::()?, follow.into_any_base()?); + let mut undo = Undo::new(Url::parse(&self.actor_id)?, follow.into_any_base()?); undo.set_context(context()).set_id(undo_id.parse()?); insert_activity(self.id, undo.clone(), true, pool).await?; @@ -193,12 +186,17 @@ impl ActorType for User_ { impl FromApub for UserForm { type ApubType = PersonExt; /// Parse an ActivityPub person received from another instance into a Lemmy user. - async fn from_apub(person: &PersonExt, _: &Client, _: &DbPool) -> Result { + async fn from_apub( + person: &PersonExt, + _: &Client, + _: &DbPool, + actor_id: &Url, + ) -> Result { let avatar = match person.icon() { Some(any_image) => Image::from_any_base(any_image.as_one().unwrap().clone()) .unwrap() .unwrap() - .url + .url() .unwrap() .as_single_xsd_any_uri() .map(|u| u.to_string()), @@ -209,18 +207,18 @@ impl FromApub for UserForm { name: person .name() .unwrap() - .as_single_xsd_string() + .one() .unwrap() - .into(), + .as_xsd_string() + .unwrap() + .to_string(), preferred_username: person.inner.preferred_username().map(|u| u.to_string()), password_encrypted: "".to_string(), admin: false, banned: false, email: None, avatar, - updated: person - .updated() - .map(|u| u.as_ref().to_owned().naive_local()), + updated: person.updated().map(|u| u.to_owned().naive_local()), show_nsfw: false, theme: "".to_string(), default_sort_type: 0, @@ -229,7 +227,7 @@ impl FromApub for UserForm { show_avatars: false, send_notifications_to_email: false, matrix_user_id: None, - actor_id: person.id().unwrap().to_string(), + actor_id: person.id(actor_id.domain().unwrap())?.unwrap().to_string(), bio: person .inner .summary() diff --git a/server/src/apub/user_inbox.rs b/server/src/apub/user_inbox.rs index 405dd3dd..73916ee2 100644 --- a/server/src/apub/user_inbox.rs +++ b/server/src/apub/user_inbox.rs @@ -3,14 +3,12 @@ use crate::{ apub::{ extensions::signatures::verify, fetcher::{get_or_fetch_and_upsert_remote_community, get_or_fetch_and_upsert_remote_user}, - insert_activity, - FromApub, + insert_activity, FromApub, }, blocking, routes::{ChatServerParam, DbPoolParam}, websocket::{server::SendUserRoomMessage, UserOperation}, - DbPool, - LemmyError, + DbPool, LemmyError, }; use activitystreams_new::{ activity::{Accept, Create, Delete, Undo, Update}, @@ -24,8 +22,7 @@ use lemmy_db::{ private_message::{PrivateMessage, PrivateMessageForm}, private_message_view::PrivateMessageView, user::User_, - Crud, - Followable, + Crud, Followable, }; use log::debug; use serde::Deserialize; @@ -80,12 +77,7 @@ async fn receive_accept( client: &Client, pool: &DbPool, ) -> Result { - let community_uri = accept - .actor() - .to_owned() - .single_xsd_any_uri() - .unwrap() - .to_string(); + let community_uri = accept.actor()?.to_owned().single_xsd_any_uri().unwrap(); let community = get_or_fetch_and_upsert_remote_community(&community_uri, client, pool).await?; verify(request, &community)?; @@ -118,15 +110,15 @@ async fn receive_create_private_message( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let user_uri = &create.actor().to_owned().single_xsd_any_uri().unwrap(); - let note = Note::from_any_base(create.object.as_one().unwrap().to_owned())?.unwrap(); + let user_uri = &create.actor()?.to_owned().single_xsd_any_uri().unwrap(); + let note = Note::from_any_base(create.object().as_one().unwrap().to_owned())?.unwrap(); let user = get_or_fetch_and_upsert_remote_user(user_uri, client, pool).await?; verify(request, &user)?; insert_activity(user.id, create, false, pool).await?; - let private_message = PrivateMessageForm::from_apub(¬e, client, pool).await?; + let private_message = PrivateMessageForm::from_apub(¬e, client, pool, user_uri).await?; let inserted_private_message = blocking(pool, move |conn| { PrivateMessage::create(conn, &private_message) @@ -159,15 +151,15 @@ async fn receive_update_private_message( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let user_uri = update.actor().to_owned().single_xsd_any_uri().unwrap(); - let note = Note::from_any_base(update.object.as_one().unwrap().to_owned())?.unwrap(); + let user_uri = &update.actor()?.to_owned().single_xsd_any_uri().unwrap(); + let note = Note::from_any_base(update.object().as_one().unwrap().to_owned())?.unwrap(); let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; verify(request, &user)?; insert_activity(user.id, update, false, pool).await?; - let private_message_form = PrivateMessageForm::from_apub(¬e, client, pool).await?; + let private_message_form = PrivateMessageForm::from_apub(¬e, client, pool, user_uri).await?; let private_message_ap_id = private_message_form.ap_id.clone(); let private_message = blocking(pool, move |conn| { @@ -208,15 +200,15 @@ async fn receive_delete_private_message( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let user_uri = delete.actor().to_owned().single_xsd_any_uri().unwrap(); - let note = Note::from_any_base(delete.object.as_one().unwrap().to_owned())?.unwrap(); + let user_uri = &delete.actor()?.to_owned().single_xsd_any_uri().unwrap(); + let note = Note::from_any_base(delete.object().as_one().unwrap().to_owned())?.unwrap(); let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; verify(request, &user)?; insert_activity(user.id, delete, false, pool).await?; - let private_message_form = PrivateMessageForm::from_apub(¬e, client, pool).await?; + let private_message_form = PrivateMessageForm::from_apub(¬e, client, pool, user_uri).await?; let private_message_ap_id = private_message_form.ap_id; let private_message = blocking(pool, move |conn| { @@ -269,16 +261,16 @@ async fn receive_undo_delete_private_message( pool: &DbPool, chat_server: ChatServerParam, ) -> Result { - let delete = Delete::from_any_base(undo.object.as_one().unwrap().to_owned())?.unwrap(); - let note = Note::from_any_base(delete.object.as_one().unwrap().to_owned())?.unwrap(); - let user_uri = delete.actor().to_owned().single_xsd_any_uri().unwrap(); + let delete = Delete::from_any_base(undo.object().as_one().unwrap().to_owned())?.unwrap(); + let note = Note::from_any_base(delete.object().as_one().unwrap().to_owned())?.unwrap(); + let user_uri = &delete.actor()?.to_owned().single_xsd_any_uri().unwrap(); let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; verify(request, &user)?; insert_activity(user.id, delete, false, pool).await?; - let private_message = PrivateMessageForm::from_apub(¬e, client, pool).await?; + let private_message = PrivateMessageForm::from_apub(¬e, client, pool, user_uri).await?; let private_message_ap_id = private_message.ap_id.clone(); let private_message_id = blocking(pool, move |conn| {