From bff0567c2794c3df81d505f110f607bf19c07295 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Wed, 11 Sep 2024 15:46:19 +0200 Subject: [PATCH] stuff --- .../live_federation/activities/create_post.rs | 2 +- examples/live_federation/objects/person.rs | 8 +++--- examples/live_federation/objects/post.rs | 6 ++-- examples/live_federation/utils.rs | 7 +++-- .../local_federation/activities/accept.rs | 2 +- .../activities/create_post.rs | 2 +- .../local_federation/activities/follow.rs | 2 +- examples/local_federation/instance.rs | 10 ++++--- examples/local_federation/objects/person.rs | 10 +++---- examples/local_federation/objects/post.rs | 6 ++-- src/actix_web/inbox.rs | 4 ++- src/fetch/mod.rs | 4 +-- src/url.rs | 28 ++++++++++++++----- 13 files changed, 56 insertions(+), 35 deletions(-) diff --git a/examples/live_federation/activities/create_post.rs b/examples/live_federation/activities/create_post.rs index 51ee5e5..a1d83f9 100644 --- a/examples/live_federation/activities/create_post.rs +++ b/examples/live_federation/activities/create_post.rs @@ -12,9 +12,9 @@ use activitypub_federation::{ kinds::activity::CreateType, protocol::{context::WithContext, helpers::deserialize_one_or_many}, traits::{ActivityHandler, Object}, + url::Url, }; use serde::{Deserialize, Serialize}; -use url::Url; #[derive(Deserialize, Serialize, Debug)] #[serde(rename_all = "camelCase")] diff --git a/examples/live_federation/objects/person.rs b/examples/live_federation/objects/person.rs index d9439ea..f0266db 100644 --- a/examples/live_federation/objects/person.rs +++ b/examples/live_federation/objects/person.rs @@ -6,11 +6,11 @@ use activitypub_federation::{ kinds::actor::PersonType, protocol::{public_key::PublicKey, verification::verify_domains_match}, traits::{ActivityHandler, Actor, Object}, + url::Url, }; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; -use std::fmt::Debug; -use url::Url; +use std::{fmt::Debug, str::FromStr}; #[derive(Debug, Clone)] pub struct DbUser { @@ -36,8 +36,8 @@ pub enum PersonAcceptedActivities { impl DbUser { pub fn new(hostname: &str, name: &str) -> Result { - let ap_id = Url::parse(&format!("https://{}/{}", hostname, &name))?.into(); - let inbox = Url::parse(&format!("https://{}/{}/inbox", hostname, &name))?; + let ap_id = Url::from_str(&format!("https://{}/{}", hostname, &name))?.into(); + let inbox = Url::from_str(&format!("https://{}/{}/inbox", hostname, &name))?; let keypair = generate_actor_keypair()?; Ok(DbUser { name: name.to_string(), diff --git a/examples/live_federation/objects/post.rs b/examples/live_federation/objects/post.rs index 1b19fac..bc88db8 100644 --- a/examples/live_federation/objects/post.rs +++ b/examples/live_federation/objects/post.rs @@ -11,10 +11,10 @@ use activitypub_federation::{ kinds::{object::NoteType, public}, protocol::{helpers::deserialize_one_or_many, verification::verify_domains_match}, traits::{Actor, Object}, + url::Url, }; use activitystreams_kinds::link::MentionType; use serde::{Deserialize, Serialize}; -use url::Url; #[derive(Clone, Debug)] pub struct DbPost { @@ -63,7 +63,7 @@ impl Object for DbPost { id: self.ap_id, content: self.text, attributed_to: self.creator, - to: vec![public()], + to: vec![public().try_into()?], tag: vec![], in_reply_to: None, }) @@ -98,7 +98,7 @@ impl Object for DbPost { kind: Default::default(), id: generate_object_id(data.domain())?.into(), attributed_to: data.local_user().ap_id, - to: vec![public()], + to: vec![public().try_into()?], content: format!("Hello {}", creator.name), in_reply_to: Some(json.id.clone()), tag: vec![mention], diff --git a/examples/live_federation/utils.rs b/examples/live_federation/utils.rs index 0b2b098..f1023ce 100644 --- a/examples/live_federation/utils.rs +++ b/examples/live_federation/utils.rs @@ -1,5 +1,8 @@ +use std::str::FromStr; + +use activitypub_federation::url::Url; use rand::{distributions::Alphanumeric, thread_rng, Rng}; -use url::{ParseError, Url}; +use url::ParseError; /// Just generate random url as object id. In a real project, you probably want to use /// an url which contains the database id for easy retrieval (or store the random id in db). @@ -9,5 +12,5 @@ pub fn generate_object_id(domain: &str) -> Result { .take(7) .map(char::from) .collect(); - Url::parse(&format!("https://{}/objects/{}", domain, id)) + Url::from_str(&format!("https://{}/objects/{}", domain, id)) } diff --git a/examples/local_federation/activities/accept.rs b/examples/local_federation/activities/accept.rs index c18945f..4fa0147 100644 --- a/examples/local_federation/activities/accept.rs +++ b/examples/local_federation/activities/accept.rs @@ -4,9 +4,9 @@ use activitypub_federation::{ fetch::object_id::ObjectId, kinds::activity::AcceptType, traits::ActivityHandler, + url::Url, }; use serde::{Deserialize, Serialize}; -use url::Url; #[derive(Deserialize, Serialize, Debug)] #[serde(rename_all = "camelCase")] diff --git a/examples/local_federation/activities/create_post.rs b/examples/local_federation/activities/create_post.rs index 6f85e2d..fc75b23 100644 --- a/examples/local_federation/activities/create_post.rs +++ b/examples/local_federation/activities/create_post.rs @@ -9,9 +9,9 @@ use activitypub_federation::{ kinds::activity::CreateType, protocol::helpers::deserialize_one_or_many, traits::{ActivityHandler, Object}, + url::Url, }; use serde::{Deserialize, Serialize}; -use url::Url; #[derive(Deserialize, Serialize, Debug)] #[serde(rename_all = "camelCase")] diff --git a/examples/local_federation/activities/follow.rs b/examples/local_federation/activities/follow.rs index 02879d4..f01fec3 100644 --- a/examples/local_federation/activities/follow.rs +++ b/examples/local_federation/activities/follow.rs @@ -9,9 +9,9 @@ use activitypub_federation::{ fetch::object_id::ObjectId, kinds::activity::FollowType, traits::{ActivityHandler, Actor}, + url::Url, }; use serde::{Deserialize, Serialize}; -use url::Url; #[derive(Deserialize, Serialize, Clone, Debug)] #[serde(rename_all = "camelCase")] diff --git a/examples/local_federation/instance.rs b/examples/local_federation/instance.rs index ad1fd12..6571adb 100644 --- a/examples/local_federation/instance.rs +++ b/examples/local_federation/instance.rs @@ -2,21 +2,23 @@ use crate::{ objects::{person::DbUser, post::DbPost}, Error, }; -use activitypub_federation::config::{FederationConfig, UrlVerifier}; +use activitypub_federation::{ + config::{FederationConfig, UrlVerifier}, + url::Url, +}; use anyhow::anyhow; use async_trait::async_trait; use std::{ str::FromStr, sync::{Arc, Mutex}, }; -use url::Url; pub async fn new_instance( hostname: &str, name: String, ) -> Result, Error> { let mut system_user = DbUser::new(hostname, "system".into())?; - system_user.ap_id = Url::parse(&format!("http://{}/", hostname))?.into(); + system_user.ap_id = Url::from_str(&format!("http://{}/", hostname))?.into(); let local_user = DbUser::new(hostname, name)?; let database = Arc::new(Database { @@ -51,7 +53,7 @@ struct MyUrlVerifier(); #[async_trait] impl UrlVerifier for MyUrlVerifier { async fn verify(&self, url: &Url) -> Result<(), activitypub_federation::error::Error> { - if url.domain() == Some("malicious.com") { + if url.domain() == "malicious.com" { Err(activitypub_federation::error::Error::Other( "malicious domain".into(), )) diff --git a/examples/local_federation/objects/person.rs b/examples/local_federation/objects/person.rs index 0ae402f..34ccc45 100644 --- a/examples/local_federation/objects/person.rs +++ b/examples/local_federation/objects/person.rs @@ -14,11 +14,11 @@ use activitypub_federation::{ kinds::actor::PersonType, protocol::{context::WithContext, public_key::PublicKey, verification::verify_domains_match}, traits::{ActivityHandler, Actor, Object}, + url::Url, }; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; -use std::fmt::Debug; -use url::Url; +use std::{fmt::Debug, str::FromStr}; #[derive(Debug, Clone)] pub struct DbUser { @@ -46,8 +46,8 @@ pub enum PersonAcceptedActivities { impl DbUser { pub fn new(hostname: &str, name: String) -> Result { - let ap_id = Url::parse(&format!("http://{}/{}", hostname, &name))?.into(); - let inbox = Url::parse(&format!("http://{}/{}/inbox", hostname, &name))?; + let ap_id = Url::from_str(&format!("http://{}/{}", hostname, &name))?.into(); + let inbox = Url::from_str(&format!("http://{}/{}/inbox", hostname, &name))?; let keypair = generate_actor_keypair()?; Ok(DbUser { name, @@ -79,7 +79,7 @@ impl DbUser { } pub fn followers_url(&self) -> Result { - Ok(Url::parse(&format!("{}/followers", self.ap_id.inner()))?) + Ok(Url::from_str(&format!("{}/followers", self.ap_id.inner()))?) } pub async fn follow(&self, other: &str, data: &Data) -> Result<(), Error> { diff --git a/examples/local_federation/objects/post.rs b/examples/local_federation/objects/post.rs index cbdf8e8..2cca41d 100644 --- a/examples/local_federation/objects/post.rs +++ b/examples/local_federation/objects/post.rs @@ -5,9 +5,9 @@ use activitypub_federation::{ kinds::{object::NoteType, public}, protocol::{helpers::deserialize_one_or_many, verification::verify_domains_match}, traits::Object, + url::Url, }; use serde::{Deserialize, Serialize}; -use url::Url; #[derive(Clone, Debug)] pub struct DbPost { @@ -19,7 +19,7 @@ pub struct DbPost { impl DbPost { pub fn new(text: String, creator: ObjectId) -> Result { - let ap_id = generate_object_id(creator.inner().domain().unwrap())?.into(); + let ap_id = generate_object_id(creator.inner().domain())?.try_into()?; Ok(DbPost { text, ap_id, @@ -65,7 +65,7 @@ impl Object for DbPost { kind: Default::default(), id: self.ap_id, attributed_to: self.creator, - to: vec![public(), creator.followers_url()?], + to: vec![public().try_into()?, creator.followers_url()?], content: self.text, }) } diff --git a/src/actix_web/inbox.rs b/src/actix_web/inbox.rs index e4d20fc..1ac080f 100644 --- a/src/actix_web/inbox.rs +++ b/src/actix_web/inbox.rs @@ -47,6 +47,8 @@ where #[cfg(test)] #[allow(clippy::unwrap_used)] mod test { + use std::str::FromStr; + use super::*; use crate::{ activity_sending::generate_request_headers, @@ -165,7 +167,7 @@ mod test { actor: ObjectId::parse("http://localhost:123").unwrap(), object: ObjectId::parse("http://localhost:124").unwrap(), kind: Default::default(), - id: "http://localhost:123/1".try_into().unwrap(), + id: "http://localhost:123/1".parse().unwrap(), }; let body: Bytes = serde_json::to_vec(&activity).unwrap().into(); let incoming_request = construct_request(&body, activity.actor.inner()).await; diff --git a/src/fetch/mod.rs b/src/fetch/mod.rs index 738384e..4c374d5 100644 --- a/src/fetch/mod.rs +++ b/src/fetch/mod.rs @@ -135,13 +135,13 @@ async fn fetch_object_http_with_accept( match serde_json::from_slice(&text) { Ok(object) => Ok(FetchObjectResponse { object, - url: url.into(), + url: url.try_into()?, content_type, object_id, }), Err(e) => Err(ParseFetchedObject( e, - url.into(), + url.try_into()?, String::from_utf8(Vec::from(text))?, )), } diff --git a/src/url.rs b/src/url.rs index 18c0b77..0423f06 100644 --- a/src/url.rs +++ b/src/url.rs @@ -1,13 +1,12 @@ //! Wrapper for `url::Url` type. +use serde::{Deserialize, Serialize}; use std::{ fmt::{Display, Formatter}, ops::Deref, str::FromStr, }; -use serde::{Deserialize, Serialize}; - /// Wrapper for `url::Url` type. Has `domain` as mandatory field, and prints plain /// string for debugging. #[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)] @@ -22,6 +21,7 @@ impl Deref for Url { } impl Display for Url { + #[allow(clippy::to_string_in_format_args)] fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0.to_string()) } @@ -30,14 +30,24 @@ impl Display for Url { impl Url { /// Returns domain of the url pub fn domain(&self) -> &str { - // TODO: must have error handling, or ensure at creation that it has domain self.0.domain().expect("has domain") } } -impl From for Url { - fn from(value: url::Url) -> Self { - Url(value) +impl TryFrom for Url { + type Error = url::ParseError; + fn try_from(value: url::Url) -> Result { + if value.domain().is_none() { + return Err(url::ParseError::EmptyHost); + } + Ok(Url(value)) + } +} + +#[allow(clippy::from_over_into)] +impl Into for Url { + fn into(self) -> url::Url { + self.0 } } @@ -45,6 +55,10 @@ impl FromStr for Url { type Err = url::ParseError; fn from_str(s: &str) -> Result { - Ok(url::Url::from_str(s).map(Url).unwrap()) + let url = url::Url::from_str(s)?; + if url.domain().is_none() { + return Err(url::ParseError::EmptyHost); + } + Ok(Url(url)) } }