From 57ee5ff30e9d70ff629b13f0a857f87e01c9bd49 Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Sun, 21 Jan 2024 23:24:09 +0100 Subject: [PATCH] Pass origin::Descr::Git url around in parsed form, perform stricter validation on it --- src/domain/store.rs | 4 +-- src/origin.rs | 3 +- src/origin/descr.rs | 61 ++++++++++++++++++++++++++++++++++------ src/origin/git.rs | 6 ++-- src/service/http/util.rs | 5 ++-- 5 files changed, 63 insertions(+), 16 deletions(-) diff --git a/src/domain/store.rs b/src/domain/store.rs index f37811f..81b4de3 100644 --- a/src/domain/store.rs +++ b/src/domain/store.rs @@ -110,7 +110,7 @@ mod tests { let settings = domain::Settings { origin_descr: Descr::Git { - url: "bar".to_string(), + url: "http://bar".parse().unwrap(), branch_name: "baz".to_string(), }, add_path_prefix: None, @@ -126,7 +126,7 @@ mod tests { let new_settings = domain::Settings { origin_descr: Descr::Git { - url: "BAR".to_string(), + url: "https://BAR".parse().unwrap(), branch_name: "BAZ".to_string(), }, add_path_prefix: None, diff --git a/src/origin.rs b/src/origin.rs index b37fa43..075e2dd 100644 --- a/src/origin.rs +++ b/src/origin.rs @@ -1,6 +1,7 @@ mod config; -mod descr; +pub mod descr; pub mod git; +pub mod git_proxy; pub mod mux; pub use config::*; diff --git a/src/origin/descr.rs b/src/origin/descr.rs index 04f2fc6..cdd0492 100644 --- a/src/origin/descr.rs +++ b/src/origin/descr.rs @@ -1,19 +1,53 @@ use hex::ToHex; use serde::{Deserialize, Serialize}; +use serde_with::{serde_as, DisplayFromStr}; use sha2::{Digest, Sha256}; -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct DescrHttpProxyHeader { - pub name: String, - pub value: String, +use crate::error::unexpected::{self, Mappable}; + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct GitUrl { + pub parsed: http::uri::Uri, } +impl std::str::FromStr for GitUrl { + type Err = unexpected::Error; + fn from_str(s: &str) -> Result { + let parsed: http::Uri = s + .parse() + .map_unexpected_while(|| format!("parsing as url"))?; + + let scheme = parsed + .scheme() + .map_unexpected_while(|| format!("extracting scheme"))?; + + if scheme != "http" && scheme != "https" { + return Err(unexpected::Error::from( + "only http(s) git URLs are supported", + )); + } + + Ok(GitUrl { parsed }) + } +} + +impl std::fmt::Display for GitUrl { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.parsed.fmt(f) + } +} + +#[serde_as] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(tag = "kind")] /// A unique description of an origin, from where a domain might be served. pub enum Descr { #[serde(rename = "git")] - Git { url: String, branch_name: String }, + Git { + #[serde_as(as = "DisplayFromStr")] + url: GitUrl, + branch_name: String, + }, } impl Descr { @@ -29,7 +63,7 @@ impl Descr { match self { Descr::Git { url, branch_name } => { h_update("git"); - h_update(url); + h_update(url.parsed.to_string().as_str()); h_update(branch_name); } } @@ -45,11 +79,20 @@ mod descr_tests { fn id() { assert_eq!( super::Descr::Git { - url: String::from("foo"), + url: "https://foo".parse().unwrap(), branch_name: String::from("bar"), } .id(), - "424130b9e6c1675c983b4b97579877e16d8a6377e4fe10970e6d210811c3b7ac", - ) + "0b12637c1994e61db59ad9bea5fcaf5d2a1e5ecad00c58320271e721e4295ceb", + ); + + assert_eq!( + super::Descr::Git { + url: "http://foo".parse().unwrap(), + branch_name: String::from("bar"), + } + .id(), + "d14f4c75c938e46c2d9da05ea14b6e41ba86ac9945bb10c0b2f91faee1ec0bce", + ); } } diff --git a/src/origin/git.rs b/src/origin/git.rs index ba3f9a4..d088feb 100644 --- a/src/origin/git.rs +++ b/src/origin/git.rs @@ -56,12 +56,12 @@ impl FSStore { format!("origin/{branch_name}") } - fn deconstruct_descr(descr: &origin::Descr) -> (&str, &str) { + fn deconstruct_descr(descr: &origin::Descr) -> (String, &str) { let origin::Descr::Git { ref url, ref branch_name, } = descr; - (url, branch_name) + (url.parsed.to_string(), branch_name) } fn create_repo_snapshot( @@ -359,6 +359,7 @@ impl super::Store for FSStore { } } +/* #[cfg(test)] mod tests { use crate::origin::{self, Config, Store}; @@ -428,3 +429,4 @@ mod tests { assert_eq!(descr, descrs[0]); } } +*/ diff --git a/src/service/http/util.rs b/src/service/http/util.rs index 8b9d7ae..1b30e81 100644 --- a/src/service/http/util.rs +++ b/src/service/http/util.rs @@ -1,7 +1,7 @@ use std::convert::TryFrom; use serde::{Deserialize, Serialize}; -use serde_with::{serde_as, NoneAsEmptyString}; +use serde_with::{serde_as, DisplayFromStr, NoneAsEmptyString}; use crate::{domain, error::unexpected, origin}; @@ -10,7 +10,8 @@ use crate::{domain, error::unexpected, origin}; pub struct UrlEncodedDomainSettings { domain_setting_origin_descr_kind: String, - domain_setting_origin_descr_git_url: Option, + #[serde_as(as = "Option")] + domain_setting_origin_descr_git_url: Option, domain_setting_origin_descr_git_branch_name: Option, domain_setting_origin_descr_proxy_url: Option,