From 3d578f9df2ff3d3bfb084658e79219850ec6c10c Mon Sep 17 00:00:00 2001 From: Nutomic Date: Wed, 27 Jan 2021 16:42:23 +0000 Subject: [PATCH] Use Url type for ap_id fields in database (fixes #1364) (#1371) --- Cargo.lock | 1 + crates/api/src/community.rs | 10 +-- crates/api/src/user.rs | 4 +- crates/apub/src/activities/receive/comment.rs | 4 +- .../apub/src/activities/receive/community.rs | 4 +- crates/apub/src/activities/receive/post.rs | 4 +- crates/apub/src/activities/send/comment.rs | 84 ++++++++++++------ crates/apub/src/activities/send/community.rs | 27 +++--- crates/apub/src/activities/send/post.rs | 85 +++++++++++++------ .../src/activities/send/private_message.rs | 36 +++++--- crates/apub/src/activities/send/user.rs | 27 +++--- crates/apub/src/activity_queue.rs | 2 +- crates/apub/src/extensions/signatures.rs | 6 +- crates/apub/src/fetcher/community.rs | 2 +- crates/apub/src/fetcher/objects.rs | 4 +- crates/apub/src/fetcher/user.rs | 2 +- crates/apub/src/http/user.rs | 2 +- crates/apub/src/inbox/community_inbox.rs | 16 ++-- crates/apub/src/inbox/mod.rs | 11 ++- crates/apub/src/inbox/shared_inbox.rs | 9 +- crates/apub/src/inbox/user_inbox.rs | 22 ++--- crates/apub/src/lib.rs | 40 ++++----- crates/apub/src/objects/comment.rs | 17 ++-- crates/apub/src/objects/community.rs | 13 ++- crates/apub/src/objects/mod.rs | 12 +-- crates/apub/src/objects/post.rs | 13 ++- crates/apub/src/objects/private_message.rs | 13 ++- crates/apub/src/objects/user.rs | 4 +- crates/db_queries/src/lib.rs | 3 +- crates/db_queries/src/source/comment.rs | 3 +- crates/db_queries/src/source/community.rs | 3 +- crates/db_queries/src/source/post.rs | 3 +- .../db_queries/src/source/private_message.rs | 4 +- crates/db_queries/src/source/user.rs | 3 +- crates/db_schema/src/lib.rs | 59 +++++++++++++ crates/db_schema/src/source/comment.rs | 14 +-- crates/db_schema/src/source/community.rs | 11 ++- crates/db_schema/src/source/post.rs | 16 ++-- .../db_schema/src/source/private_message.rs | 6 +- crates/db_schema/src/source/user.rs | 21 +++-- crates/structs/Cargo.toml | 1 + crates/structs/src/lib.rs | 5 +- .../down.sql | 6 ++ .../2021-01-26-173850_default_actor_id/up.sql | 6 ++ src/code_migrations.rs | 14 +-- src/routes/feeds.rs | 4 +- src/routes/webfinger.rs | 6 +- tests/integration_test.rs | 14 +-- 48 files changed, 433 insertions(+), 243 deletions(-) create mode 100644 migrations/2021-01-26-173850_default_actor_id/down.sql create mode 100644 migrations/2021-01-26-173850_default_actor_id/up.sql diff --git a/Cargo.lock b/Cargo.lock index 70f9ec5b6..e43b9219c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1908,6 +1908,7 @@ dependencies = [ "log", "serde 1.0.118", "serde_json", + "url", ] [[package]] diff --git a/crates/api/src/community.rs b/crates/api/src/community.rs index 055f9bfd5..26687b98b 100644 --- a/crates/api/src/community.rs +++ b/crates/api/src/community.rs @@ -136,10 +136,10 @@ impl Perform for CreateCommunity { } // Double check for duplicate community actor_ids - let actor_id = make_apub_endpoint(EndpointType::Community, &data.name).to_string(); + let actor_id = make_apub_endpoint(EndpointType::Community, &data.name); let actor_id_cloned = actor_id.to_owned(); let community_dupe = blocking(context.pool(), move |conn| { - Community::read_from_apub_id(conn, &actor_id_cloned) + Community::read_from_apub_id(conn, &actor_id_cloned.into()) }) .await?; if community_dupe.is_ok() { @@ -168,7 +168,7 @@ impl Perform for CreateCommunity { deleted: None, nsfw: data.nsfw, updated: None, - actor_id: Some(actor_id), + actor_id: Some(actor_id.into()), local: true, private_key: Some(keypair.private_key), public_key: Some(keypair.public_key), @@ -509,9 +509,9 @@ impl Perform for FollowCommunity { } else if data.follow { // Dont actually add to the community followers here, because you need // to wait for the accept - user.send_follow(&community.actor_id()?, context).await?; + user.send_follow(&community.actor_id(), context).await?; } else { - user.send_unfollow(&community.actor_id()?, context).await?; + user.send_unfollow(&community.actor_id(), context).await?; let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form); if blocking(context.pool(), unfollow).await?.is_err() { return Err(APIError::err("community_follower_already_exists").into()); diff --git a/crates/api/src/user.rs b/crates/api/src/user.rs index 16d390c59..4ec930542 100644 --- a/crates/api/src/user.rs +++ b/crates/api/src/user.rs @@ -200,7 +200,7 @@ impl Perform for Register { lang: "browser".into(), show_avatars: true, send_notifications_to_email: false, - actor_id: Some(make_apub_endpoint(EndpointType::User, &data.username).to_string()), + actor_id: Some(make_apub_endpoint(EndpointType::User, &data.username).into()), bio: None, local: true, private_key: Some(user_keypair.private_key), @@ -247,7 +247,7 @@ impl Perform for Register { deleted: None, updated: None, actor_id: Some( - make_apub_endpoint(EndpointType::Community, default_community_name).to_string(), + make_apub_endpoint(EndpointType::Community, default_community_name).into(), ), local: true, private_key: Some(main_community_keypair.private_key), diff --git a/crates/apub/src/activities/receive/comment.rs b/crates/apub/src/activities/receive/comment.rs index 7ba3a05ca..6136f63bb 100644 --- a/crates/apub/src/activities/receive/comment.rs +++ b/crates/apub/src/activities/receive/comment.rs @@ -23,7 +23,7 @@ pub(crate) async fn receive_create_comment( let note = NoteExt::from_any_base(create.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let comment = Comment::from_apub(¬e, context, user.actor_id()?, request_counter).await?; + let comment = Comment::from_apub(¬e, context, user.actor_id(), request_counter).await?; let post_id = comment.post_id; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; @@ -66,7 +66,7 @@ pub(crate) async fn receive_update_comment( .context(location_info!())?; let user = get_actor_as_user(&update, context, request_counter).await?; - let comment = Comment::from_apub(¬e, context, user.actor_id()?, request_counter).await?; + let comment = Comment::from_apub(¬e, context, user.actor_id(), request_counter).await?; let comment_id = comment.id; let post_id = comment.post_id; diff --git a/crates/apub/src/activities/receive/community.rs b/crates/apub/src/activities/receive/community.rs index 7f5523773..54a8cdb7a 100644 --- a/crates/apub/src/activities/receive/community.rs +++ b/crates/apub/src/activities/receive/community.rs @@ -55,7 +55,7 @@ pub(crate) async fn receive_remove_community( .single_xsd_any_uri() .context(location_info!())?; let community = blocking(context.pool(), move |conn| { - Community::read_from_apub_id(conn, community_uri.as_str()) + Community::read_from_apub_id(conn, &community_uri.into()) }) .await??; @@ -137,7 +137,7 @@ pub(crate) async fn receive_undo_remove_community( .single_xsd_any_uri() .context(location_info!())?; let community = blocking(context.pool(), move |conn| { - Community::read_from_apub_id(conn, community_uri.as_str()) + Community::read_from_apub_id(conn, &community_uri.into()) }) .await??; diff --git a/crates/apub/src/activities/receive/post.rs b/crates/apub/src/activities/receive/post.rs index c35a02818..426358646 100644 --- a/crates/apub/src/activities/receive/post.rs +++ b/crates/apub/src/activities/receive/post.rs @@ -20,7 +20,7 @@ pub(crate) async fn receive_create_post( let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let post = Post::from_apub(&page, context, user.actor_id()?, request_counter).await?; + let post = Post::from_apub(&page, context, user.actor_id(), request_counter).await?; // Refetch the view let post_id = post.id; @@ -49,7 +49,7 @@ pub(crate) async fn receive_update_post( let page = PageExt::from_any_base(update.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; - let post = Post::from_apub(&page, context, user.actor_id()?, request_counter).await?; + let post = Post::from_apub(&page, context, user.actor_id(), request_counter).await?; let post_id = post.id; // Refetch the view diff --git a/crates/apub/src/activities/send/comment.rs b/crates/apub/src/activities/send/comment.rs index e3c622edb..323b851f5 100644 --- a/crates/apub/src/activities/send/comment.rs +++ b/crates/apub/src/activities/send/comment.rs @@ -59,7 +59,10 @@ impl ApubObjectType for Comment { let maa = collect_non_local_mentions(&self, &community, context).await?; - let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?); + let mut create = Create::new( + creator.actor_id.to_owned().into_inner(), + note.into_any_base()?, + ); create .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(CreateType::Create)?) @@ -89,7 +92,10 @@ impl ApubObjectType for Comment { let maa = collect_non_local_mentions(&self, &community, context).await?; - let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?); + let mut update = Update::new( + creator.actor_id.to_owned().into_inner(), + note.into_any_base()?, + ); update .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UpdateType::Update)?) @@ -113,12 +119,15 @@ impl ApubObjectType for Comment { }) .await??; - let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut delete = Delete::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); delete .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(delete, &creator, &community, context).await?; Ok(()) @@ -139,20 +148,26 @@ impl ApubObjectType for Comment { .await??; // Generate a fake delete activity, with the correct object - let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut delete = Delete::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); delete .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); // Undo that fake activity - let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); + let mut undo = Undo::new( + creator.actor_id.to_owned().into_inner(), + delete.into_any_base()?, + ); undo .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(undo, &creator, &community, context).await?; Ok(()) @@ -168,12 +183,15 @@ impl ApubObjectType for Comment { }) .await??; - let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut remove = Remove::new( + mod_.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); remove .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(RemoveType::Remove)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(remove, &mod_, &community, context).await?; Ok(()) @@ -190,20 +208,26 @@ impl ApubObjectType for Comment { .await??; // Generate a fake delete activity, with the correct object - let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut remove = Remove::new( + mod_.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); remove .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(RemoveType::Remove)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); // Undo that fake activity - let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?); + let mut undo = Undo::new( + mod_.actor_id.to_owned().into_inner(), + remove.into_any_base()?, + ); undo .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(undo, &mod_, &community, context).await?; Ok(()) @@ -222,12 +246,15 @@ impl ApubLikeableType for Comment { }) .await??; - let mut like = Like::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut like = Like::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); like .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(LikeType::Like)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(like, &creator, &community, context).await?; Ok(()) @@ -243,12 +270,15 @@ impl ApubLikeableType for Comment { }) .await??; - let mut dislike = Dislike::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut dislike = Dislike::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); dislike .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(DislikeType::Dislike)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(dislike, &creator, &community, context).await?; Ok(()) @@ -268,20 +298,26 @@ impl ApubLikeableType for Comment { }) .await??; - let mut like = Like::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut like = Like::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); like .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(DislikeType::Dislike)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); // Undo that fake activity - let mut undo = Undo::new(creator.actor_id.to_owned(), like.into_any_base()?); + let mut undo = Undo::new( + creator.actor_id.to_owned().into_inner(), + like.into_any_base()?, + ); undo .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(undo, &creator, &community, context).await?; Ok(()) @@ -313,7 +349,7 @@ async fn collect_non_local_mentions( context: &LemmyContext, ) -> Result { let parent_creator = get_comment_parent_creator(context.pool(), comment).await?; - let mut addressed_ccs = vec![community.actor_id()?, parent_creator.actor_id()?]; + let mut addressed_ccs = vec![community.actor_id(), parent_creator.actor_id()]; // Note: dont include community inbox here, as we send to it separately with `send_to_community()` let mut inboxes = vec![parent_creator.get_shared_inbox_url()?]; @@ -393,7 +429,5 @@ async fn fetch_webfinger_url(mention: &MentionData, client: &Client) -> Result String { - self.actor_id.to_owned() + fn actor_id(&self) -> Url { + self.actor_id.to_owned().into_inner() } fn public_key(&self) -> Option { @@ -72,11 +72,14 @@ impl ActorType for Community { .context(location_info!())?; let user = get_or_fetch_and_upsert_user(actor_uri, context, &mut 0).await?; - let mut accept = Accept::new(self.actor_id.to_owned(), follow.into_any_base()?); + let mut accept = Accept::new( + self.actor_id.to_owned().into_inner(), + follow.into_any_base()?, + ); accept .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(AcceptType::Accept)?) - .set_to(user.actor_id()?); + .set_to(user.actor_id()); send_activity_single_dest(accept, self, user.get_inbox_url()?, context).await?; Ok(()) @@ -84,7 +87,7 @@ impl ActorType for Community { /// If the creator of a community deletes the community, send this to all followers. async fn send_delete(&self, context: &LemmyContext) -> Result<(), LemmyError> { - let mut delete = Delete::new(self.actor_id()?, self.actor_id()?); + let mut delete = Delete::new(self.actor_id(), self.actor_id()); delete .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(DeleteType::Delete)?) @@ -97,14 +100,14 @@ impl ActorType for Community { /// If the creator of a community reverts the deletion of a community, send this to all followers. async fn send_undo_delete(&self, context: &LemmyContext) -> Result<(), LemmyError> { - let mut delete = Delete::new(self.actor_id()?, self.actor_id()?); + let mut delete = Delete::new(self.actor_id(), self.actor_id()); delete .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(public()) .set_many_ccs(vec![self.get_followers_url()?]); - let mut undo = Undo::new(self.actor_id()?, delete.into_any_base()?); + let mut undo = Undo::new(self.actor_id(), delete.into_any_base()?); undo .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UndoType::Undo)?) @@ -117,7 +120,7 @@ impl ActorType for Community { /// If an admin removes a community, send this to all followers. async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> { - let mut remove = Remove::new(self.actor_id()?, self.actor_id()?); + let mut remove = Remove::new(self.actor_id(), self.actor_id()); remove .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(RemoveType::Remove)?) @@ -130,7 +133,7 @@ impl ActorType for Community { /// If an admin reverts the removal of a community, send this to all followers. async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> { - let mut remove = Remove::new(self.actor_id()?, self.actor_id()?); + let mut remove = Remove::new(self.actor_id(), self.actor_id()); remove .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(RemoveType::Remove)?) @@ -138,7 +141,7 @@ impl ActorType for Community { .set_many_ccs(vec![self.get_followers_url()?]); // Undo that fake activity - let mut undo = Undo::new(self.actor_id()?, remove.into_any_base()?); + let mut undo = Undo::new(self.actor_id(), remove.into_any_base()?); undo .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(LikeType::Like)?) @@ -156,7 +159,7 @@ impl ActorType for Community { activity: AnyBase, context: &LemmyContext, ) -> Result<(), LemmyError> { - let mut announce = Announce::new(self.actor_id.to_owned(), activity); + let mut announce = Announce::new(self.actor_id.to_owned().into_inner(), activity); announce .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(AnnounceType::Announce)?) @@ -183,7 +186,7 @@ impl ActorType for Community { .into_iter() .filter(|i| !i.follower.local) .map(|u| -> Result { - let url = Url::parse(&u.follower.actor_id)?; + let url = u.follower.actor_id.into_inner(); let domain = url.domain().context(location_info!())?; let port = if let Some(port) = url.port() { format!(":{}", port) diff --git a/crates/apub/src/activities/send/post.rs b/crates/apub/src/activities/send/post.rs index 4af40de28..ce74d20a5 100644 --- a/crates/apub/src/activities/send/post.rs +++ b/crates/apub/src/activities/send/post.rs @@ -26,7 +26,6 @@ use lemmy_db_schema::source::{community::Community, post::Post, user::User_}; use lemmy_structs::blocking; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; -use url::Url; #[async_trait::async_trait(?Send)] impl ApubObjectType for Post { @@ -40,12 +39,15 @@ impl ApubObjectType for Post { }) .await??; - let mut create = Create::new(creator.actor_id.to_owned(), page.into_any_base()?); + let mut create = Create::new( + creator.actor_id.to_owned().into_inner(), + page.into_any_base()?, + ); create .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(CreateType::Create)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(create, creator, &community, context).await?; Ok(()) @@ -61,12 +63,15 @@ impl ApubObjectType for Post { }) .await??; - let mut update = Update::new(creator.actor_id.to_owned(), page.into_any_base()?); + let mut update = Update::new( + creator.actor_id.to_owned().into_inner(), + page.into_any_base()?, + ); update .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UpdateType::Update)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(update, creator, &community, context).await?; Ok(()) @@ -79,12 +84,15 @@ impl ApubObjectType for Post { }) .await??; - let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut delete = Delete::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); delete .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(delete, creator, &community, context).await?; Ok(()) @@ -101,20 +109,26 @@ impl ApubObjectType for Post { }) .await??; - let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut delete = Delete::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); delete .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(DeleteType::Delete)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); // Undo that fake activity - let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); + let mut undo = Undo::new( + creator.actor_id.to_owned().into_inner(), + delete.into_any_base()?, + ); undo .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(undo, creator, &community, context).await?; Ok(()) @@ -127,12 +141,15 @@ impl ApubObjectType for Post { }) .await??; - let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut remove = Remove::new( + mod_.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); remove .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(RemoveType::Remove)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(remove, mod_, &community, context).await?; Ok(()) @@ -145,20 +162,26 @@ impl ApubObjectType for Post { }) .await??; - let mut remove = Remove::new(mod_.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut remove = Remove::new( + mod_.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); remove .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(RemoveType::Remove)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); // Undo that fake activity - let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?); + let mut undo = Undo::new( + mod_.actor_id.to_owned().into_inner(), + remove.into_any_base()?, + ); undo .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(undo, mod_, &community, context).await?; Ok(()) @@ -174,12 +197,15 @@ impl ApubLikeableType for Post { }) .await??; - let mut like = Like::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut like = Like::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); like .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(LikeType::Like)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(like, &creator, &community, context).await?; Ok(()) @@ -192,12 +218,15 @@ impl ApubLikeableType for Post { }) .await??; - let mut dislike = Dislike::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut dislike = Dislike::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); dislike .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(DislikeType::Dislike)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(dislike, &creator, &community, context).await?; Ok(()) @@ -214,20 +243,26 @@ impl ApubLikeableType for Post { }) .await??; - let mut like = Like::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut like = Like::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); like .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(LikeType::Like)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); // Undo that fake activity - let mut undo = Undo::new(creator.actor_id.to_owned(), like.into_any_base()?); + let mut undo = Undo::new( + creator.actor_id.to_owned().into_inner(), + like.into_any_base()?, + ); undo .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UndoType::Undo)?) .set_to(public()) - .set_many_ccs(vec![community.actor_id()?]); + .set_many_ccs(vec![community.actor_id()]); send_to_community(undo, &creator, &community, context).await?; Ok(()) diff --git a/crates/apub/src/activities/send/private_message.rs b/crates/apub/src/activities/send/private_message.rs index d920f3dec..6bff815a4 100644 --- a/crates/apub/src/activities/send/private_message.rs +++ b/crates/apub/src/activities/send/private_message.rs @@ -21,7 +21,6 @@ use lemmy_db_schema::source::{private_message::PrivateMessage, user::User_}; use lemmy_structs::blocking; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; -use url::Url; #[async_trait::async_trait(?Send)] impl ApubObjectType for PrivateMessage { @@ -32,12 +31,15 @@ impl ApubObjectType for PrivateMessage { let recipient_id = self.recipient_id; let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; - let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?); + let mut create = Create::new( + creator.actor_id.to_owned().into_inner(), + note.into_any_base()?, + ); create .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(CreateType::Create)?) - .set_to(recipient.actor_id()?); + .set_to(recipient.actor_id()); send_activity_single_dest(create, creator, recipient.get_inbox_url()?, context).await?; Ok(()) @@ -50,11 +52,14 @@ impl ApubObjectType for PrivateMessage { let recipient_id = self.recipient_id; let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; - let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?); + let mut update = Update::new( + creator.actor_id.to_owned().into_inner(), + note.into_any_base()?, + ); update .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UpdateType::Update)?) - .set_to(recipient.actor_id()?); + .set_to(recipient.actor_id()); send_activity_single_dest(update, creator, recipient.get_inbox_url()?, context).await?; Ok(()) @@ -64,11 +69,14 @@ impl ApubObjectType for PrivateMessage { let recipient_id = self.recipient_id; let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; - let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut delete = Delete::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); delete .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(DeleteType::Delete)?) - .set_to(recipient.actor_id()?); + .set_to(recipient.actor_id()); send_activity_single_dest(delete, creator, recipient.get_inbox_url()?, context).await?; Ok(()) @@ -82,18 +90,24 @@ impl ApubObjectType for PrivateMessage { let recipient_id = self.recipient_id; let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; - let mut delete = Delete::new(creator.actor_id.to_owned(), Url::parse(&self.ap_id)?); + let mut delete = Delete::new( + creator.actor_id.to_owned().into_inner(), + self.ap_id.to_owned().into_inner(), + ); delete .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(DeleteType::Delete)?) - .set_to(recipient.actor_id()?); + .set_to(recipient.actor_id()); // Undo that fake activity - let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); + let mut undo = Undo::new( + creator.actor_id.to_owned().into_inner(), + delete.into_any_base()?, + ); undo .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UndoType::Undo)?) - .set_to(recipient.actor_id()?); + .set_to(recipient.actor_id()); send_activity_single_dest(undo, creator, recipient.get_inbox_url()?, context).await?; Ok(()) diff --git a/crates/apub/src/activities/send/user.rs b/crates/apub/src/activities/send/user.rs index 049496f73..3eac6f2df 100644 --- a/crates/apub/src/activities/send/user.rs +++ b/crates/apub/src/activities/send/user.rs @@ -25,8 +25,8 @@ use url::Url; #[async_trait::async_trait(?Send)] impl ActorType for User_ { - fn actor_id_str(&self) -> String { - self.actor_id.to_owned() + fn actor_id(&self) -> Url { + self.actor_id.to_owned().into_inner() } fn public_key(&self) -> Option { @@ -43,9 +43,9 @@ impl ActorType for User_ { follow_actor_id: &Url, context: &LemmyContext, ) -> Result<(), LemmyError> { - let follow_actor_id = follow_actor_id.to_string(); + let follow_actor_id = follow_actor_id.to_owned(); let community = blocking(context.pool(), move |conn| { - Community::read_from_apub_id(conn, &follow_actor_id) + Community::read_from_apub_id(conn, &follow_actor_id.into()) }) .await??; @@ -59,11 +59,11 @@ impl ActorType for User_ { }) .await?; - let mut follow = Follow::new(self.actor_id.to_owned(), community.actor_id()?); + let mut follow = Follow::new(self.actor_id.to_owned().into_inner(), community.actor_id()); follow .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(FollowType::Follow)?) - .set_to(community.actor_id()?); + .set_to(community.actor_id()); send_activity_single_dest(follow, self, community.get_inbox_url()?, context).await?; Ok(()) @@ -74,24 +74,27 @@ impl ActorType for User_ { follow_actor_id: &Url, context: &LemmyContext, ) -> Result<(), LemmyError> { - let follow_actor_id = follow_actor_id.to_string(); + let follow_actor_id = follow_actor_id.to_owned(); let community = blocking(context.pool(), move |conn| { - Community::read_from_apub_id(conn, &follow_actor_id) + Community::read_from_apub_id(conn, &follow_actor_id.into()) }) .await??; - let mut follow = Follow::new(self.actor_id.to_owned(), community.actor_id()?); + let mut follow = Follow::new(self.actor_id.to_owned().into_inner(), community.actor_id()); follow .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(FollowType::Follow)?) - .set_to(community.actor_id()?); + .set_to(community.actor_id()); // Undo that fake activity - let mut undo = Undo::new(Url::parse(&self.actor_id)?, follow.into_any_base()?); + let mut undo = Undo::new( + self.actor_id.to_owned().into_inner(), + follow.into_any_base()?, + ); undo .set_many_contexts(lemmy_context()?) .set_id(generate_activity_id(UndoType::Undo)?) - .set_to(community.actor_id()?); + .set_to(community.actor_id()); send_activity_single_dest(undo, self, community.get_inbox_url()?, context).await?; Ok(()) diff --git a/crates/apub/src/activity_queue.rs b/crates/apub/src/activity_queue.rs index ff792c4da..d7246384a 100644 --- a/crates/apub/src/activity_queue.rs +++ b/crates/apub/src/activity_queue.rs @@ -240,7 +240,7 @@ where let message = SendActivityTask { activity: serialised_activity.to_owned(), inbox: i.to_owned(), - actor_id: actor.actor_id()?, + actor_id: actor.actor_id(), private_key: actor.private_key().context(location_info!())?, }; if env::var("LEMMY_TEST_SEND_SYNC").is_ok() { diff --git a/crates/apub/src/extensions/signatures.rs b/crates/apub/src/extensions/signatures.rs index 67fe4b1cd..ebbf9a0a4 100644 --- a/crates/apub/src/extensions/signatures.rs +++ b/crates/apub/src/extensions/signatures.rs @@ -98,17 +98,17 @@ pub(crate) fn verify_signature( /// Extension for actor public key, which is needed on user and community for HTTP signatures. /// /// Taken from: https://docs.rs/activitystreams/0.5.0-alpha.17/activitystreams/ext/index.html -#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct PublicKeyExtension { pub public_key: PublicKey, } -#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct PublicKey { pub id: String, - pub owner: String, + pub owner: Url, pub public_key_pem: String, } diff --git a/crates/apub/src/fetcher/community.rs b/crates/apub/src/fetcher/community.rs index 2a2564122..0249dee1e 100644 --- a/crates/apub/src/fetcher/community.rs +++ b/crates/apub/src/fetcher/community.rs @@ -40,7 +40,7 @@ pub(crate) async fn get_or_fetch_and_upsert_community( ) -> Result { let apub_id_owned = apub_id.to_owned(); let community = blocking(context.pool(), move |conn| { - Community::read_from_apub_id(conn, apub_id_owned.as_str()) + Community::read_from_apub_id(conn, &apub_id_owned.into()) }) .await?; diff --git a/crates/apub/src/fetcher/objects.rs b/crates/apub/src/fetcher/objects.rs index 269b27ef8..df33bf740 100644 --- a/crates/apub/src/fetcher/objects.rs +++ b/crates/apub/src/fetcher/objects.rs @@ -20,7 +20,7 @@ pub(crate) async fn get_or_fetch_and_insert_post( ) -> Result { let post_ap_id_owned = post_ap_id.to_owned(); let post = blocking(context.pool(), move |conn| { - Post::read_from_apub_id(conn, post_ap_id_owned.as_str()) + Post::read_from_apub_id(conn, &post_ap_id_owned.into()) }) .await?; @@ -49,7 +49,7 @@ pub(crate) async fn get_or_fetch_and_insert_comment( ) -> Result { let comment_ap_id_owned = comment_ap_id.to_owned(); let comment = blocking(context.pool(), move |conn| { - Comment::read_from_apub_id(conn, comment_ap_id_owned.as_str()) + Comment::read_from_apub_id(conn, &comment_ap_id_owned.into()) }) .await?; diff --git a/crates/apub/src/fetcher/user.rs b/crates/apub/src/fetcher/user.rs index 8442519f7..21cdfb348 100644 --- a/crates/apub/src/fetcher/user.rs +++ b/crates/apub/src/fetcher/user.rs @@ -24,7 +24,7 @@ pub(crate) async fn get_or_fetch_and_upsert_user( ) -> Result { let apub_id_owned = apub_id.to_owned(); let user = blocking(context.pool(), move |conn| { - User_::read_from_apub_id(conn, apub_id_owned.as_ref()) + User_::read_from_apub_id(conn, &apub_id_owned.into()) }) .await?; diff --git a/crates/apub/src/http/user.rs b/crates/apub/src/http/user.rs index 3005b8b59..7c7653e57 100644 --- a/crates/apub/src/http/user.rs +++ b/crates/apub/src/http/user.rs @@ -72,7 +72,7 @@ pub async fn get_apub_user_inbox( let mut collection = OrderedCollection::new(); collection - .set_id(format!("{}/inbox", user.actor_id).parse()?) + .set_id(format!("{}/inbox", user.actor_id.into_inner()).parse()?) .set_many_contexts(lemmy_context()?); Ok(create_apub_response(&collection)) } diff --git a/crates/apub/src/inbox/community_inbox.rs b/crates/apub/src/inbox/community_inbox.rs index 1e44254c2..45e7ab43c 100644 --- a/crates/apub/src/inbox/community_inbox.rs +++ b/crates/apub/src/inbox/community_inbox.rs @@ -69,7 +69,7 @@ pub async fn community_inbox( let actor = inbox_verify_http_signature(&activity, &context, request, request_counter).await?; // Do nothing if we received the same activity before - let activity_id = get_activity_id(&activity, &actor.actor_id()?)?; + let activity_id = get_activity_id(&activity, &actor.actor_id())?; if is_activity_already_known(context.pool(), &activity_id).await? { return Ok(HttpResponse::Ok().finish()); } @@ -81,7 +81,7 @@ pub async fn community_inbox( }) .await??; let to_and_cc = get_activity_to_and_cc(&activity); - if !to_and_cc.contains(&&community.actor_id()?) { + if !to_and_cc.contains(&&community.actor_id()) { return Err(anyhow!("Activity delivered to wrong community").into()); } @@ -92,7 +92,7 @@ pub async fn community_inbox( "Community {} received activity {:?} from {}", community.name, &activity.id_unchecked(), - &actor.actor_id_str() + &actor.actor_id() ); community_receive_message( @@ -115,15 +115,15 @@ pub(crate) async fn community_receive_message( ) -> Result { // Only users can send activities to the community, so we can get the actor as user // unconditionally. - let actor_id = actor.actor_id_str(); + let actor_id = actor.actor_id(); let user = blocking(&context.pool(), move |conn| { - User_::read_from_apub_id(&conn, &actor_id) + User_::read_from_apub_id(&conn, &actor_id.into()) }) .await??; check_community_or_site_ban(&user, &to_community, context.pool()).await?; let any_base = activity.clone().into_any_base()?; - let actor_url = actor.actor_id()?; + let actor_url = actor.actor_id(); let activity_kind = activity.kind().context(location_info!())?; let do_announce = match activity_kind { CommunityValidTypes::Follow => { @@ -187,7 +187,7 @@ async fn handle_follow( context: &LemmyContext, ) -> Result { let follow = Follow::from_any_base(activity)?.context(location_info!())?; - verify_activity_domains_valid(&follow, &user.actor_id()?, false)?; + verify_activity_domains_valid(&follow, &user.actor_id(), false)?; let community_follower_form = CommunityFollowerForm { community_id: community.id, @@ -241,7 +241,7 @@ async fn handle_undo_follow( verify_activity_domains_valid(&follow, &user_url, false)?; let user = blocking(&context.pool(), move |conn| { - User_::read_from_apub_id(&conn, user_url.as_str()) + User_::read_from_apub_id(&conn, &user_url.into()) }) .await??; let community_follower_form = CommunityFollowerForm { diff --git a/crates/apub/src/inbox/mod.rs b/crates/apub/src/inbox/mod.rs index a91dd48eb..65e476e51 100644 --- a/crates/apub/src/inbox/mod.rs +++ b/crates/apub/src/inbox/mod.rs @@ -119,8 +119,11 @@ pub(crate) async fn is_addressed_to_local_user( pool: &DbPool, ) -> Result { for url in to_and_cc { - let url = url.to_string(); - let user = blocking(&pool, move |conn| User_::read_from_apub_id(&conn, &url)).await?; + let url = url.to_owned(); + let user = blocking(&pool, move |conn| { + User_::read_from_apub_id(&conn, &url.into()) + }) + .await?; if let Ok(u) = user { if u.local { return Ok(true); @@ -140,9 +143,9 @@ pub(crate) async fn is_addressed_to_community_followers( let url = url.to_string(); // TODO: extremely hacky, we should just store the followers url for each community in the db if url.ends_with("/followers") { - let community_url = url.replace("/followers", ""); + let community_url = Url::parse(&url.replace("/followers", ""))?; let community = blocking(&pool, move |conn| { - Community::read_from_apub_id(&conn, &community_url) + Community::read_from_apub_id(&conn, &community_url.into()) }) .await??; if !community.local { diff --git a/crates/apub/src/inbox/shared_inbox.rs b/crates/apub/src/inbox/shared_inbox.rs index f9b9bfc01..93df6e728 100644 --- a/crates/apub/src/inbox/shared_inbox.rs +++ b/crates/apub/src/inbox/shared_inbox.rs @@ -54,7 +54,7 @@ pub async fn shared_inbox( let actor = inbox_verify_http_signature(&activity, &context, request, request_counter).await?; // Do nothing if we received the same activity before - let actor_id = actor.actor_id()?; + let actor_id = actor.actor_id(); let activity_id = get_activity_id(&activity, &actor_id)?; if is_activity_already_known(context.pool(), &activity_id).await? { return Ok(HttpResponse::Ok().finish()); @@ -137,8 +137,11 @@ async fn extract_local_community_from_destinations( pool: &DbPool, ) -> Result, LemmyError> { for url in to_and_cc { - let url = url.to_string(); - let community = blocking(&pool, move |conn| Community::read_from_apub_id(&conn, &url)).await?; + let url = url.to_owned(); + let community = blocking(&pool, move |conn| { + Community::read_from_apub_id(&conn, &url.into()) + }) + .await?; if let Ok(c) = community { if c.local { return Ok(Some(c)); diff --git a/crates/apub/src/inbox/user_inbox.rs b/crates/apub/src/inbox/user_inbox.rs index 353a296e3..6496a60a0 100644 --- a/crates/apub/src/inbox/user_inbox.rs +++ b/crates/apub/src/inbox/user_inbox.rs @@ -90,7 +90,7 @@ pub async fn user_inbox( let actor = inbox_verify_http_signature(&activity, &context, request, request_counter).await?; // Do nothing if we received the same activity before - let activity_id = get_activity_id(&activity, &actor.actor_id()?)?; + let activity_id = get_activity_id(&activity, &actor.actor_id())?; if is_activity_already_known(context.pool(), &activity_id).await? { return Ok(HttpResponse::Ok().finish()); } @@ -103,7 +103,7 @@ pub async fn user_inbox( .await??; let to_and_cc = get_activity_to_and_cc(&activity); // TODO: we should also accept activities that are sent to community followers - if !to_and_cc.contains(&&user.actor_id()?) { + if !to_and_cc.contains(&&user.actor_id()) { return Err(anyhow!("Activity delivered to wrong user").into()); } @@ -114,7 +114,7 @@ pub async fn user_inbox( "User {} received activity {:?} from {}", user.name, &activity.id_unchecked(), - &actor.actor_id_str() + &actor.actor_id() ); user_receive_message( @@ -139,7 +139,7 @@ pub(crate) async fn user_receive_message( let any_base = activity.clone().into_any_base()?; let kind = activity.kind().context(location_info!())?; - let actor_url = actor.actor_id()?; + let actor_url = actor.actor_id(); match kind { UserValidTypes::Accept => { receive_accept(&context, any_base, actor, to_user.unwrap(), request_counter).await?; @@ -209,11 +209,11 @@ async fn receive_accept( request_counter: &mut i32, ) -> Result<(), LemmyError> { let accept = Accept::from_any_base(activity)?.context(location_info!())?; - verify_activity_domains_valid(&accept, &actor.actor_id()?, false)?; + verify_activity_domains_valid(&accept, &actor.actor_id(), false)?; let object = accept.object().to_owned().one().context(location_info!())?; let follow = Follow::from_any_base(object)?.context(location_info!())?; - verify_activity_domains_valid(&follow, &user.actor_id()?, false)?; + verify_activity_domains_valid(&follow, &user.actor_id(), false)?; let community_uri = accept .actor()? @@ -243,7 +243,7 @@ async fn receive_announce( request_counter: &mut i32, ) -> Result<(), LemmyError> { let announce = Announce::from_any_base(activity)?.context(location_info!())?; - verify_activity_domains_valid(&announce, &actor.actor_id()?, false)?; + verify_activity_domains_valid(&announce, &actor.actor_id(), false)?; is_addressed_to_public(&announce)?; let kind = announce.object().as_single_kind_str(); @@ -375,18 +375,18 @@ async fn find_community_or_private_message_by_id( context: &LemmyContext, apub_id: Url, ) -> Result { - let ap_id = apub_id.to_string(); + let ap_id = apub_id.to_owned(); let community = blocking(context.pool(), move |conn| { - Community::read_from_apub_id(conn, &ap_id) + Community::read_from_apub_id(conn, &ap_id.into()) }) .await?; if let Ok(c) = community { return Ok(CommunityOrPrivateMessage::Community(c)); } - let ap_id = apub_id.to_string(); + let ap_id = apub_id.to_owned(); let private_message = blocking(context.pool(), move |conn| { - PrivateMessage::read_from_apub_id(conn, &ap_id) + PrivateMessage::read_from_apub_id(conn, &ap_id.into()) }) .await?; if let Ok(p) = private_message { diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs index d5d682a7d..f76a0b8ff 100644 --- a/crates/apub/src/lib.rs +++ b/crates/apub/src/lib.rs @@ -140,7 +140,7 @@ pub trait ApubLikeableType { /// implemented by all actors. #[async_trait::async_trait(?Send)] pub trait ActorType { - fn actor_id_str(&self) -> String; + fn actor_id(&self) -> Url; // TODO: every actor should have a public key, so this shouldnt be an option (needs to be fixed in db) fn public_key(&self) -> Option; @@ -178,17 +178,13 @@ pub trait ActorType { /// For a given community, returns the inboxes of all followers. async fn get_follower_inboxes(&self, pool: &DbPool) -> Result, LemmyError>; - fn actor_id(&self) -> Result { - Url::parse(&self.actor_id_str()) - } - // TODO move these to the db rows fn get_inbox_url(&self) -> Result { - Url::parse(&format!("{}/inbox", &self.actor_id_str())) + Url::parse(&format!("{}/inbox", &self.actor_id())) } fn get_shared_inbox_url(&self) -> Result { - let actor_id = self.actor_id()?; + let actor_id = self.actor_id(); let url = format!( "{}://{}{}/inbox", &actor_id.scheme(), @@ -203,18 +199,18 @@ pub trait ActorType { } fn get_outbox_url(&self) -> Result { - Url::parse(&format!("{}/outbox", &self.actor_id_str())) + Url::parse(&format!("{}/outbox", &self.actor_id())) } fn get_followers_url(&self) -> Result { - Url::parse(&format!("{}/followers", &self.actor_id_str())) + Url::parse(&format!("{}/followers", &self.actor_id())) } fn get_public_key_ext(&self) -> Result { Ok( PublicKey { - id: format!("{}#main-key", self.actor_id_str()), - owner: self.actor_id_str(), + id: format!("{}#main-key", self.actor_id()), + owner: self.actor_id(), public_key_pem: self.public_key().context(location_info!())?, } .to_ext(), @@ -254,18 +250,18 @@ pub(crate) async fn find_post_or_comment_by_id( context: &LemmyContext, apub_id: Url, ) -> Result { - let ap_id = apub_id.to_string(); + let ap_id = apub_id.clone(); let post = blocking(context.pool(), move |conn| { - Post::read_from_apub_id(conn, &ap_id) + Post::read_from_apub_id(conn, &ap_id.into()) }) .await?; if let Ok(p) = post { return Ok(PostOrComment::Post(p)); } - let ap_id = apub_id.to_string(); + let ap_id = apub_id.clone(); let comment = blocking(context.pool(), move |conn| { - Comment::read_from_apub_id(conn, &ap_id) + Comment::read_from_apub_id(conn, &ap_id.into()) }) .await?; if let Ok(c) = comment { @@ -287,34 +283,34 @@ pub(crate) async fn find_object_by_id( context: &LemmyContext, apub_id: Url, ) -> Result { - if let Ok(pc) = find_post_or_comment_by_id(context, apub_id.to_owned()).await { + let ap_id = apub_id.clone(); + if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await { return Ok(match pc { PostOrComment::Post(p) => Object::Post(p), PostOrComment::Comment(c) => Object::Comment(c), }); } - let ap_id = apub_id.to_string(); + let ap_id = apub_id.clone(); let user = blocking(context.pool(), move |conn| { - User_::read_from_apub_id(conn, &ap_id) + User_::read_from_apub_id(conn, &ap_id.into()) }) .await?; if let Ok(u) = user { return Ok(Object::User(u)); } - let ap_id = apub_id.to_string(); + let ap_id = apub_id.clone(); let community = blocking(context.pool(), move |conn| { - Community::read_from_apub_id(conn, &ap_id) + Community::read_from_apub_id(conn, &ap_id.into()) }) .await?; if let Ok(c) = community { return Ok(Object::Community(c)); } - let ap_id = apub_id.to_string(); let private_message = blocking(context.pool(), move |conn| { - PrivateMessage::read_from_apub_id(conn, &ap_id) + PrivateMessage::read_from_apub_id(conn, &apub_id.into()) }) .await?; if let Ok(pm) = private_message { diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs index 5dba4149b..f20da66f9 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -54,22 +54,22 @@ impl ToApub for Comment { // Add a vector containing some important info to the "in_reply_to" field // [post_ap_id, Option(parent_comment_ap_id)] - let mut in_reply_to_vec = vec![post.ap_id]; + let mut in_reply_to_vec = vec![post.ap_id.into_inner()]; if let Some(parent_id) = self.parent_id { let parent_comment = blocking(pool, move |conn| Comment::read(conn, parent_id)).await??; - in_reply_to_vec.push(parent_comment.ap_id); + in_reply_to_vec.push(parent_comment.ap_id.into_inner()); } comment // Not needed when the Post is embedded in a collection (like for community outbox) .set_many_contexts(lemmy_context()?) - .set_id(Url::parse(&self.ap_id)?) + .set_id(self.ap_id.to_owned().into_inner()) .set_published(convert_datetime(self.published)) - .set_to(community.actor_id) + .set_to(community.actor_id.into_inner()) .set_many_in_reply_tos(in_reply_to_vec) - .set_attributed_to(creator.actor_id); + .set_attributed_to(creator.actor_id.into_inner()); set_content_and_source(&mut comment, &self.content)?; @@ -81,7 +81,12 @@ impl ToApub for Comment { } fn to_tombstone(&self) -> Result { - create_tombstone(self.deleted, &self.ap_id, self.updated, NoteType::Note) + create_tombstone( + self.deleted, + self.ap_id.to_owned().into(), + self.updated, + NoteType::Note, + ) } } diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index 4d7a235cc..566e4714a 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -51,15 +51,15 @@ impl ToApub for Community { CommunityModeratorView::for_community(&conn, id) }) .await??; - let moderators: Vec = moderators + let moderators: Vec = moderators .into_iter() - .map(|m| m.moderator.actor_id) + .map(|m| m.moderator.actor_id.into_inner()) .collect(); let mut group = ApObject::new(Group::new()); group .set_many_contexts(lemmy_context()?) - .set_id(Url::parse(&self.actor_id)?) + .set_id(self.actor_id.to_owned().into()) .set_name(self.title.to_owned()) .set_published(convert_datetime(self.published)) .set_many_attributed_tos(moderators); @@ -108,7 +108,12 @@ impl ToApub for Community { } fn to_tombstone(&self) -> Result { - create_tombstone(self.deleted, &self.actor_id, self.updated, GroupType::Group) + create_tombstone( + self.deleted, + self.actor_id.to_owned().into(), + self.updated, + GroupType::Group, + ) } } diff --git a/crates/apub/src/objects/mod.rs b/crates/apub/src/objects/mod.rs index d9eea762e..e32bfe72f 100644 --- a/crates/apub/src/objects/mod.rs +++ b/crates/apub/src/objects/mod.rs @@ -64,7 +64,7 @@ pub(in crate::objects) trait FromApubToForm { /// Updated is actually the deletion time fn create_tombstone( deleted: bool, - object_id: &str, + object_id: Url, updated: Option, former_type: T, ) -> Result @@ -74,7 +74,7 @@ where if deleted { if let Some(updated) = updated { let mut tombstone = Tombstone::new(); - tombstone.set_id(object_id.parse()?); + tombstone.set_id(object_id); tombstone.set_former_type(former_type.to_string()); tombstone.set_deleted(convert_datetime(updated)); Ok(tombstone) @@ -89,14 +89,14 @@ where pub(in crate::objects) fn check_object_domain( apub: &T, expected_domain: Url, -) -> Result +) -> Result where T: Base + AsBase, { let domain = expected_domain.domain().context(location_info!())?; let object_id = apub.id(domain)?.context(location_info!())?; - check_is_apub_id_valid(&object_id)?; - Ok(object_id.to_string()) + check_is_apub_id_valid(object_id)?; + Ok(object_id.to_owned().into()) } pub(in crate::objects) fn set_content_and_source( @@ -189,7 +189,7 @@ where // if its a local object, return it directly from the database if Settings::get().hostname == domain { let object = blocking(context.pool(), move |conn| { - To::read_from_apub_id(conn, object_id.as_str()) + To::read_from_apub_id(conn, &object_id.into()) }) .await??; Ok(object) diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index 6d5ed8e23..31f848a4d 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -55,13 +55,13 @@ impl ToApub for Post { // TODO: need to set proper context defining sensitive/commentsEnabled fields // https://git.asonix.dog/Aardwolf/activitystreams/issues/5 .set_many_contexts(lemmy_context()?) - .set_id(self.ap_id.parse::()?) + .set_id(self.ap_id.to_owned().into_inner()) // 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)) - .set_to(community.actor_id) - .set_attributed_to(creator.actor_id); + .set_to(community.actor_id.into_inner()) + .set_attributed_to(creator.actor_id.into_inner()); if let Some(body) = &self.body { set_content_and_source(&mut page, &body)?; @@ -93,7 +93,12 @@ impl ToApub for Post { } fn to_tombstone(&self) -> Result { - create_tombstone(self.deleted, &self.ap_id, self.updated, PageType::Page) + create_tombstone( + self.deleted, + self.ap_id.to_owned().into(), + self.updated, + PageType::Page, + ) } } diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs index 1a7b5e327..df91b03f0 100644 --- a/crates/apub/src/objects/private_message.rs +++ b/crates/apub/src/objects/private_message.rs @@ -44,10 +44,10 @@ impl ToApub for PrivateMessage { private_message .set_many_contexts(lemmy_context()?) - .set_id(Url::parse(&self.ap_id.to_owned())?) + .set_id(self.ap_id.to_owned().into_inner()) .set_published(convert_datetime(self.published)) - .set_to(recipient.actor_id) - .set_attributed_to(creator.actor_id); + .set_to(recipient.actor_id.into_inner()) + .set_attributed_to(creator.actor_id.into_inner()); set_content_and_source(&mut private_message, &self.content)?; @@ -59,7 +59,12 @@ impl ToApub for PrivateMessage { } fn to_tombstone(&self) -> Result { - create_tombstone(self.deleted, &self.ap_id, self.updated, NoteType::Note) + create_tombstone( + self.deleted, + self.ap_id.to_owned().into(), + self.updated, + NoteType::Note, + ) } } diff --git a/crates/apub/src/objects/user.rs b/crates/apub/src/objects/user.rs index aad407f30..a0bd5173c 100644 --- a/crates/apub/src/objects/user.rs +++ b/crates/apub/src/objects/user.rs @@ -41,7 +41,7 @@ impl ToApub for User_ { let mut person = ApObject::new(Person::new()); person .set_many_contexts(lemmy_context()?) - .set_id(Url::parse(&self.actor_id)?) + .set_id(self.actor_id.to_owned().into_inner()) .set_published(convert_datetime(self.published)); if let Some(u) = self.updated { @@ -101,7 +101,7 @@ impl FromApub for User_ { let domain = user_id.domain().context(location_info!())?; if domain == Settings::get().hostname { let user = blocking(context.pool(), move |conn| { - User_::read_from_apub_id(conn, user_id.as_str()) + User_::read_from_apub_id(conn, &user_id.into()) }) .await??; Ok(user) diff --git a/crates/db_queries/src/lib.rs b/crates/db_queries/src/lib.rs index 997f4f964..b0a73b7ba 100644 --- a/crates/db_queries/src/lib.rs +++ b/crates/db_queries/src/lib.rs @@ -10,6 +10,7 @@ extern crate lazy_static; extern crate diesel_migrations; use diesel::{result::Error, *}; +use lemmy_db_schema::Url; use regex::Regex; use serde::{Deserialize, Serialize}; use std::{env, env::VarError}; @@ -108,7 +109,7 @@ pub trait Reportable { } pub trait ApubObject { - fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result + fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result where Self: Sized; fn upsert(conn: &PgConnection, user_form: &T) -> Result diff --git a/crates/db_queries/src/source/comment.rs b/crates/db_queries/src/source/comment.rs index 6e99bf36e..28d52e89c 100644 --- a/crates/db_queries/src/source/comment.rs +++ b/crates/db_queries/src/source/comment.rs @@ -10,6 +10,7 @@ use lemmy_db_schema::{ CommentSaved, CommentSavedForm, }, + Url, }; pub trait Comment_ { @@ -144,7 +145,7 @@ impl Crud for Comment { } impl ApubObject for Comment { - fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result { + fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result { use lemmy_db_schema::schema::comment::dsl::*; comment.filter(ap_id.eq(object_id)).first::(conn) } diff --git a/crates/db_queries/src/source/community.rs b/crates/db_queries/src/source/community.rs index 28245d8dc..bb7a9c240 100644 --- a/crates/db_queries/src/source/community.rs +++ b/crates/db_queries/src/source/community.rs @@ -12,6 +12,7 @@ use lemmy_db_schema::{ CommunityUserBan, CommunityUserBanForm, }, + Url, }; mod safe_type { @@ -91,7 +92,7 @@ impl Crud for Community { } impl ApubObject for Community { - fn read_from_apub_id(conn: &PgConnection, for_actor_id: &str) -> Result { + fn read_from_apub_id(conn: &PgConnection, for_actor_id: &Url) -> Result { use lemmy_db_schema::schema::community::dsl::*; community .filter(actor_id.eq(for_actor_id)) diff --git a/crates/db_queries/src/source/post.rs b/crates/db_queries/src/source/post.rs index bca848cad..7816d4a11 100644 --- a/crates/db_queries/src/source/post.rs +++ b/crates/db_queries/src/source/post.rs @@ -12,6 +12,7 @@ use lemmy_db_schema::{ PostSaved, PostSavedForm, }, + Url, }; impl Crud for Post { @@ -146,7 +147,7 @@ impl Post_ for Post { } impl ApubObject for Post { - fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result { + fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result { use lemmy_db_schema::schema::post::dsl::*; post.filter(ap_id.eq(object_id)).first::(conn) } diff --git a/crates/db_queries/src/source/private_message.rs b/crates/db_queries/src/source/private_message.rs index d63f698d9..4e0f66b65 100644 --- a/crates/db_queries/src/source/private_message.rs +++ b/crates/db_queries/src/source/private_message.rs @@ -1,6 +1,6 @@ use crate::{ApubObject, Crud}; use diesel::{dsl::*, result::Error, *}; -use lemmy_db_schema::{naive_now, source::private_message::*}; +use lemmy_db_schema::{naive_now, source::private_message::*, Url}; impl Crud for PrivateMessage { fn read(conn: &PgConnection, private_message_id: i32) -> Result { @@ -28,7 +28,7 @@ impl Crud for PrivateMessage { } impl ApubObject for PrivateMessage { - fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result + fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result where Self: Sized, { diff --git a/crates/db_queries/src/source/user.rs b/crates/db_queries/src/source/user.rs index 6e285f99b..b7db3e2d1 100644 --- a/crates/db_queries/src/source/user.rs +++ b/crates/db_queries/src/source/user.rs @@ -5,6 +5,7 @@ use lemmy_db_schema::{ naive_now, schema::user_::dsl::*, source::user::{UserForm, UserSafeSettings, User_}, + Url, }; use lemmy_utils::settings::Settings; @@ -237,7 +238,7 @@ impl Crud for User_ { } impl ApubObject for User_ { - fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result { + fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result { use lemmy_db_schema::schema::user_::dsl::*; user_ .filter(deleted.eq(false)) diff --git a/crates/db_schema/src/lib.rs b/crates/db_schema/src/lib.rs index 981ecba27..b0733884e 100644 --- a/crates/db_schema/src/lib.rs +++ b/crates/db_schema/src/lib.rs @@ -2,10 +2,69 @@ extern crate diesel; use chrono::NaiveDateTime; +use diesel::{ + backend::Backend, + deserialize::FromSql, + serialize::{Output, ToSql}, + sql_types::Text, +}; +use serde::Serialize; +use std::{ + fmt::{Display, Formatter}, + io::Write, +}; pub mod schema; pub mod source; +#[repr(transparent)] +#[derive(Clone, PartialEq, Serialize, Debug, AsExpression, FromSqlRow)] +#[sql_type = "Text"] +pub struct Url(url::Url); + +impl ToSql for Url +where + String: ToSql, +{ + fn to_sql(&self, out: &mut Output) -> diesel::serialize::Result { + self.0.to_string().to_sql(out) + } +} + +impl FromSql for Url +where + String: FromSql, +{ + fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result { + let str = String::from_sql(bytes)?; + Ok(Url(url::Url::parse(&str)?)) + } +} + +impl Url { + pub fn into_inner(self) -> url::Url { + self.0 + } +} + +impl Display for Url { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + self.to_owned().into_inner().fmt(f) + } +} + +impl From for url::Url { + fn from(url: Url) -> Self { + url.0 + } +} + +impl From for Url { + fn from(url: url::Url) -> Self { + Url(url) + } +} + // TODO: can probably move this back to lemmy_db_queries pub fn naive_now() -> NaiveDateTime { chrono::prelude::Utc::now().naive_utc() diff --git a/crates/db_schema/src/source/comment.rs b/crates/db_schema/src/source/comment.rs index 8c553a51a..72b9e740a 100644 --- a/crates/db_schema/src/source/comment.rs +++ b/crates/db_schema/src/source/comment.rs @@ -1,9 +1,9 @@ use crate::{ schema::{comment, comment_alias_1, comment_like, comment_saved}, source::post::Post, + Url, }; use serde::Serialize; -use url::{ParseError, Url}; // WITH RECURSIVE MyTree AS ( // SELECT * FROM comment WHERE parent_id IS NULL @@ -26,7 +26,7 @@ pub struct Comment { pub published: chrono::NaiveDateTime, pub updated: Option, pub deleted: bool, - pub ap_id: String, + pub ap_id: Url, pub local: bool, } @@ -44,7 +44,7 @@ pub struct CommentAlias1 { pub published: chrono::NaiveDateTime, pub updated: Option, pub deleted: bool, - pub ap_id: String, + pub ap_id: Url, pub local: bool, } @@ -60,16 +60,10 @@ pub struct CommentForm { pub published: Option, pub updated: Option, pub deleted: Option, - pub ap_id: Option, + pub ap_id: Option, pub local: bool, } -impl CommentForm { - pub fn get_ap_id(&self) -> Result { - Url::parse(&self.ap_id.as_ref().unwrap_or(&"not_a_url".to_string())) - } -} - #[derive(Identifiable, Queryable, Associations, PartialEq, Debug, Clone)] #[belongs_to(Comment)] #[table_name = "comment_like"] diff --git a/crates/db_schema/src/source/community.rs b/crates/db_schema/src/source/community.rs index af7fce0c9..d938d265e 100644 --- a/crates/db_schema/src/source/community.rs +++ b/crates/db_schema/src/source/community.rs @@ -1,4 +1,7 @@ -use crate::schema::{community, community_follower, community_moderator, community_user_ban}; +use crate::{ + schema::{community, community_follower, community_moderator, community_user_ban}, + Url, +}; use serde::Serialize; #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] @@ -15,7 +18,7 @@ pub struct Community { pub updated: Option, pub deleted: bool, pub nsfw: bool, - pub actor_id: String, + pub actor_id: Url, pub local: bool, pub private_key: Option, pub public_key: Option, @@ -39,7 +42,7 @@ pub struct CommunitySafe { pub updated: Option, pub deleted: bool, pub nsfw: bool, - pub actor_id: String, + pub actor_id: Url, pub local: bool, pub icon: Option, pub banner: Option, @@ -58,7 +61,7 @@ pub struct CommunityForm { pub updated: Option, pub deleted: Option, pub nsfw: bool, - pub actor_id: Option, + pub actor_id: Option, pub local: bool, pub private_key: Option, pub public_key: Option, diff --git a/crates/db_schema/src/source/post.rs b/crates/db_schema/src/source/post.rs index b0cc78e0e..4ec6b56d0 100644 --- a/crates/db_schema/src/source/post.rs +++ b/crates/db_schema/src/source/post.rs @@ -1,6 +1,8 @@ -use crate::schema::{post, post_like, post_read, post_saved}; +use crate::{ + schema::{post, post_like, post_read, post_saved}, + Url, +}; use serde::Serialize; -use url::{ParseError, Url}; #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[table_name = "post"] @@ -22,7 +24,7 @@ pub struct Post { pub embed_description: Option, pub embed_html: Option, pub thumbnail_url: Option, - pub ap_id: String, + pub ap_id: Url, pub local: bool, } @@ -45,16 +47,10 @@ pub struct PostForm { pub embed_description: Option, pub embed_html: Option, pub thumbnail_url: Option, - pub ap_id: Option, + pub ap_id: Option, pub local: bool, } -impl PostForm { - pub fn get_ap_id(&self) -> Result { - Url::parse(&self.ap_id.as_ref().unwrap_or(&"not_a_url".to_string())) - } -} - #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] #[belongs_to(Post)] #[table_name = "post_like"] diff --git a/crates/db_schema/src/source/private_message.rs b/crates/db_schema/src/source/private_message.rs index 341040692..376728a1b 100644 --- a/crates/db_schema/src/source/private_message.rs +++ b/crates/db_schema/src/source/private_message.rs @@ -1,4 +1,4 @@ -use crate::schema::private_message; +use crate::{schema::private_message, Url}; use serde::Serialize; #[derive(Clone, Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)] @@ -12,7 +12,7 @@ pub struct PrivateMessage { pub read: bool, pub published: chrono::NaiveDateTime, pub updated: Option, - pub ap_id: String, + pub ap_id: Url, pub local: bool, } @@ -26,6 +26,6 @@ pub struct PrivateMessageForm { pub read: Option, pub published: Option, pub updated: Option, - pub ap_id: Option, + pub ap_id: Option, pub local: bool, } diff --git a/crates/db_schema/src/source/user.rs b/crates/db_schema/src/source/user.rs index f9dc0a59a..f702c84bb 100644 --- a/crates/db_schema/src/source/user.rs +++ b/crates/db_schema/src/source/user.rs @@ -1,4 +1,7 @@ -use crate::schema::{user_, user_alias_1, user_alias_2}; +use crate::{ + schema::{user_, user_alias_1, user_alias_2}, + Url, +}; use serde::Serialize; #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] @@ -22,7 +25,7 @@ pub struct User_ { pub show_avatars: bool, pub send_notifications_to_email: bool, pub matrix_user_id: Option, - pub actor_id: String, + pub actor_id: Url, pub bio: Option, pub local: bool, pub private_key: Option, @@ -45,7 +48,7 @@ pub struct UserSafe { pub published: chrono::NaiveDateTime, pub updated: Option, pub matrix_user_id: Option, - pub actor_id: String, + pub actor_id: Url, pub bio: Option, pub local: bool, pub banner: Option, @@ -73,7 +76,7 @@ pub struct UserSafeSettings { pub show_avatars: bool, pub send_notifications_to_email: bool, pub matrix_user_id: Option, - pub actor_id: String, + pub actor_id: Url, pub bio: Option, pub local: bool, pub last_refreshed_at: chrono::NaiveDateTime, @@ -102,7 +105,7 @@ pub struct UserAlias1 { pub show_avatars: bool, pub send_notifications_to_email: bool, pub matrix_user_id: Option, - pub actor_id: String, + pub actor_id: Url, pub bio: Option, pub local: bool, pub private_key: Option, @@ -124,7 +127,7 @@ pub struct UserSafeAlias1 { pub published: chrono::NaiveDateTime, pub updated: Option, pub matrix_user_id: Option, - pub actor_id: String, + pub actor_id: Url, pub bio: Option, pub local: bool, pub banner: Option, @@ -152,7 +155,7 @@ pub struct UserAlias2 { pub show_avatars: bool, pub send_notifications_to_email: bool, pub matrix_user_id: Option, - pub actor_id: String, + pub actor_id: Url, pub bio: Option, pub local: bool, pub private_key: Option, @@ -174,7 +177,7 @@ pub struct UserSafeAlias2 { pub published: chrono::NaiveDateTime, pub updated: Option, pub matrix_user_id: Option, - pub actor_id: String, + pub actor_id: Url, pub bio: Option, pub local: bool, pub banner: Option, @@ -201,7 +204,7 @@ pub struct UserForm { pub show_avatars: bool, pub send_notifications_to_email: bool, pub matrix_user_id: Option>, - pub actor_id: Option, + pub actor_id: Option, pub bio: Option>, pub local: bool, pub private_key: Option, diff --git a/crates/structs/Cargo.toml b/crates/structs/Cargo.toml index 36a47772f..75d107c8e 100644 --- a/crates/structs/Cargo.toml +++ b/crates/structs/Cargo.toml @@ -21,3 +21,4 @@ diesel = "1.4.5" actix-web = "3.3.2" chrono = { version = "0.4.19", features = ["serde"] } serde_json = { version = "1.0.60", features = ["preserve_order"] } +url = "2.2.0" diff --git a/crates/structs/src/lib.rs b/crates/structs/src/lib.rs index f91b5fcb0..8b56fab6b 100644 --- a/crates/structs/src/lib.rs +++ b/crates/structs/src/lib.rs @@ -16,13 +16,14 @@ use lemmy_db_schema::source::{ use lemmy_utils::{email::send_email, settings::Settings, utils::MentionData, LemmyError}; use log::error; use serde::{Deserialize, Serialize}; +use url::Url; #[derive(Serialize, Deserialize, Debug)] pub struct WebFingerLink { pub rel: Option, #[serde(rename(serialize = "type", deserialize = "type"))] pub type_: Option, - pub href: Option, + pub href: Option, #[serde(skip_serializing_if = "Option::is_none")] pub template: Option, } @@ -30,7 +31,7 @@ pub struct WebFingerLink { #[derive(Serialize, Deserialize, Debug)] pub struct WebFingerResponse { pub subject: String, - pub aliases: Vec, + pub aliases: Vec, pub links: Vec, } diff --git a/migrations/2021-01-26-173850_default_actor_id/down.sql b/migrations/2021-01-26-173850_default_actor_id/down.sql new file mode 100644 index 000000000..fb612743e --- /dev/null +++ b/migrations/2021-01-26-173850_default_actor_id/down.sql @@ -0,0 +1,6 @@ +create or replace function generate_unique_changeme() +returns text language sql +as $$ + select 'changeme_' || string_agg (substr('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789', ceil (random() * 62)::integer, 1), '') + from generate_series(1, 20) +$$; \ No newline at end of file diff --git a/migrations/2021-01-26-173850_default_actor_id/up.sql b/migrations/2021-01-26-173850_default_actor_id/up.sql new file mode 100644 index 000000000..4370c4a52 --- /dev/null +++ b/migrations/2021-01-26-173850_default_actor_id/up.sql @@ -0,0 +1,6 @@ +create or replace function generate_unique_changeme() +returns text language sql +as $$ + select 'http://changeme_' || string_agg (substr('abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789', ceil (random() * 62)::integer, 1), '') + from generate_series(1, 20) +$$; \ No newline at end of file diff --git a/src/code_migrations.rs b/src/code_migrations.rs index d2928244e..a6586ae73 100644 --- a/src/code_migrations.rs +++ b/src/code_migrations.rs @@ -42,7 +42,7 @@ fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> { // Update the actor_id, private_key, and public_key, last_refreshed_at let incorrect_users = user_ - .filter(actor_id.like("changeme_%")) + .filter(actor_id.like("http://changeme_%")) .filter(local.eq(true)) .load::(conn)?; @@ -68,7 +68,7 @@ fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> { lang: cuser.lang.to_owned(), show_avatars: cuser.show_avatars, send_notifications_to_email: cuser.send_notifications_to_email, - actor_id: Some(make_apub_endpoint(EndpointType::User, &cuser.name).to_string()), + actor_id: Some(make_apub_endpoint(EndpointType::User, &cuser.name).into()), bio: Some(cuser.bio.to_owned()), local: cuser.local, private_key: Some(keypair.private_key), @@ -91,7 +91,7 @@ fn community_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> { // Update the actor_id, private_key, and public_key, last_refreshed_at let incorrect_communities = community - .filter(actor_id.like("changeme_%")) + .filter(actor_id.like("http://changeme_%")) .filter(local.eq(true)) .load::(conn)?; @@ -108,7 +108,7 @@ fn community_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> { deleted: None, nsfw: ccommunity.nsfw, updated: None, - actor_id: Some(make_apub_endpoint(EndpointType::Community, &ccommunity.name).to_string()), + actor_id: Some(make_apub_endpoint(EndpointType::Community, &ccommunity.name).into()), local: ccommunity.local, private_key: Some(keypair.private_key), public_key: Some(keypair.public_key), @@ -133,7 +133,7 @@ fn post_updates_2020_04_03(conn: &PgConnection) -> Result<(), LemmyError> { // Update the ap_id let incorrect_posts = post - .filter(ap_id.eq("changeme_%")) + .filter(ap_id.eq("http://changeme_%")) .filter(local.eq(true)) .load::(conn)?; @@ -154,7 +154,7 @@ fn comment_updates_2020_04_03(conn: &PgConnection) -> Result<(), LemmyError> { // Update the ap_id let incorrect_comments = comment - .filter(ap_id.eq("changeme_%")) + .filter(ap_id.eq("http://changeme_%")) .filter(local.eq(true)) .load::(conn)?; @@ -175,7 +175,7 @@ fn private_message_updates_2020_05_05(conn: &PgConnection) -> Result<(), LemmyEr // Update the ap_id let incorrect_pms = private_message - .filter(ap_id.eq("changeme_%")) + .filter(ap_id.eq("http://changeme_%")) .filter(local.eq(true)) .load::(conn)?; diff --git a/src/routes/feeds.rs b/src/routes/feeds.rs index 5065390c2..864670527 100644 --- a/src/routes/feeds.rs +++ b/src/routes/feeds.rs @@ -204,7 +204,7 @@ fn get_feed_community( channel_builder .namespaces(RSS_NAMESPACE.to_owned()) .title(&format!("{} - {}", site_view.site.name, community.name)) - .link(community.actor_id) + .link(community.actor_id.to_string()) .items(items); if let Some(community_desc) = community.description { @@ -367,7 +367,7 @@ fn create_post_items(posts: Vec) -> Result, LemmyError> { i.title(p.post.name); - dc_extension.creators(vec![p.creator.actor_id.to_owned()]); + dc_extension.creators(vec![p.creator.actor_id.to_string()]); let dt = DateTime::::from_utc(p.post.published, Utc); i.pub_date(dt.to_rfc2822()); diff --git a/src/routes/webfinger.rs b/src/routes/webfinger.rs index 0e4d7f948..4059e0f89 100644 --- a/src/routes/webfinger.rs +++ b/src/routes/webfinger.rs @@ -70,18 +70,18 @@ async fn get_webfinger_response( let json = WebFingerResponse { subject: info.resource.to_owned(), - aliases: vec![url.to_owned()], + aliases: vec![url.to_owned().into()], links: vec![ WebFingerLink { rel: Some("http://webfinger.net/rel/profile-page".to_string()), type_: Some("text/html".to_string()), - href: Some(url.to_owned()), + href: Some(url.to_owned().into()), template: None, }, WebFingerLink { rel: Some("self".to_string()), type_: Some("application/activity+json".to_string()), - href: Some(url), + href: Some(url.into()), template: None, }, // TODO: this also needs to return the subscribe link once that's implemented //{ diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 5e6964e44..28e67a71a 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -104,7 +104,11 @@ fn create_user(conn: &PgConnection, name: &str) -> User_ { lang: "browser".into(), show_avatars: true, send_notifications_to_email: false, - actor_id: Some(format!("http://localhost:8536/u/{}", name)), + actor_id: Some( + Url::parse(&format!("http://localhost:8536/u/{}", name)) + .unwrap() + .into(), + ), bio: None, local: true, private_key: Some(user_keypair.private_key), @@ -137,7 +141,7 @@ fn create_community(conn: &PgConnection, creator_id: i32) -> Community { }; Community::create(&conn, &new_community).unwrap() } -fn create_activity<'a, Activity, Return>(user_id: String) -> web::Json +fn create_activity<'a, Activity, Return>(user_id: Url) -> web::Json where for<'de> Return: Deserialize<'de> + 'a, Activity: std::default::Default + Serialize, @@ -173,7 +177,7 @@ async fn test_shared_inbox_expired_signature() { let connection = &context.pool().get().unwrap(); let user = create_user(connection, "shared_inbox_rvgfd"); let activity = - create_activity::>(user.actor_id); + create_activity::>(user.actor_id.into()); let response = shared_inbox(request, activity, web::Data::new(context)).await; assert_eq!( format!("{}", response.err().unwrap()), @@ -189,7 +193,7 @@ async fn test_user_inbox_expired_signature() { let connection = &context.pool().get().unwrap(); let user = create_user(connection, "user_inbox_cgsax"); let activity = - create_activity::>(user.actor_id); + create_activity::>(user.actor_id.into()); let path = Path:: { 0: "username".to_string(), }; @@ -209,7 +213,7 @@ async fn test_community_inbox_expired_signature() { let community = create_community(connection, user.id); let request = create_http_request(); let activity = create_activity::>( - user.actor_id, + user.actor_id.into(), ); let path = Path:: { 0: community.name }; let response = community_inbox(request, activity, path, web::Data::new(context)).await;