From e3ed6538c33b9358f8c8071ad067dab45de1699d Mon Sep 17 00:00:00 2001 From: "Edward J. Jinotti" Date: Tue, 15 Sep 2026 12:45:14 -0400 Subject: [PATCH 1/2] claude: replace serde_yml --- Cargo.toml | 4 ++-- src/config.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d6924f8..8861eda 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mauth-client" -version = "0.8.1" +version = "0.9.0" authors = ["Mason Gup "] edition = "2024" rust-version = "1.88" @@ -21,7 +21,7 @@ async-trait = ">= 0.1.83" url = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" -serde_yml = ">= 0.0.10" +yaml_serde = "0.10" uuid = { version = "1", features = ["v4"] } dirs = "7" chrono = "0.4" diff --git a/src/config.rs b/src/config.rs index 7815ace..a1b3544 100644 --- a/src/config.rs +++ b/src/config.rs @@ -23,12 +23,12 @@ impl MAuthInfo { home.push(CONFIG_FILE); let config_data = std::fs::read_to_string(&home)?; - let config_data_value: serde_yml::Value = serde_yml::from_slice(&config_data.into_bytes())?; + let config_data_value: yaml_serde::Value = yaml_serde::from_str(&config_data)?; let common_section = config_data_value .get("common") .ok_or(ConfigReadError::InvalidFile(None))?; let common_section_typed: ConfigFileSection = - serde_yml::from_value(common_section.clone())?; + yaml_serde::from_value(common_section.clone())?; Ok(common_section_typed) } @@ -124,7 +124,7 @@ pub enum ConfigReadError { #[error("File Read Error: {0}")] FileReadError(#[from] io::Error), #[error("Not a valid maudit config file: {0:?}")] - InvalidFile(Option), + InvalidFile(Option), #[error("MAudit URI not valid: {0}")] InvalidUri(#[from] url::ParseError), #[error("App UUID not valid: {0}")] @@ -146,8 +146,8 @@ impl From for ConfigReadError { } } -impl From for ConfigReadError { - fn from(err: serde_yml::Error) -> ConfigReadError { +impl From for ConfigReadError { + fn from(err: yaml_serde::Error) -> ConfigReadError { ConfigReadError::InvalidFile(Some(err)) } } From df483d9e0a57971b13b7a0f836e2b33ca8ba57ad Mon Sep 17 00:00:00 2001 From: "Edward J. Jinotti" Date: Tue, 15 Sep 2026 13:08:35 -0400 Subject: [PATCH 2/2] claude: address copilot review --- src/config.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/src/config.rs b/src/config.rs index a1b3544..7f9abf3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -22,8 +22,14 @@ impl MAuthInfo { let mut home = dirs::home_dir().unwrap(); home.push(CONFIG_FILE); let config_data = std::fs::read_to_string(&home)?; + Self::config_section_from_yaml(&config_data) + } - let config_data_value: yaml_serde::Value = yaml_serde::from_str(&config_data)?; + /// Parse the `common` section out of the YAML contents of a config file. + pub(crate) fn config_section_from_yaml( + config_data: &str, + ) -> Result { + let config_data_value: yaml_serde::Value = yaml_serde::from_str(config_data)?; let common_section = config_data_value .get("common") .ok_or(ConfigReadError::InvalidFile(None))?; @@ -157,6 +163,87 @@ mod test { use super::*; use tokio::fs; + #[test] + fn parses_documented_common_section() { + let yaml = "\ +common: &common + mauth_baseurl: https://mauth.example.com + mauth_api_version: v1 + app_uuid: c7db7fde-2448-11ef-b358-125eb8485a60 + private_key_file: /path/to/key.pem +"; + let section = MAuthInfo::config_section_from_yaml(yaml).unwrap(); + assert_eq!(section.mauth_baseurl, "https://mauth.example.com"); + assert_eq!(section.mauth_api_version, "v1"); + assert_eq!(section.app_uuid, "c7db7fde-2448-11ef-b358-125eb8485a60"); + assert_eq!( + section.private_key_file.as_deref(), + Some("/path/to/key.pem") + ); + assert!(section.private_key_data.is_none()); + assert!(section.v2_only_sign_requests.is_none()); + assert!(section.v2_only_authenticate.is_none()); + assert!(section.pubkey_cache_capacity.is_none()); + } + + #[test] + fn parses_optional_fields_and_ignores_other_sections() { + let yaml = "\ +common: &common + mauth_baseurl: https://mauth.example.com + mauth_api_version: v1 + app_uuid: c7db7fde-2448-11ef-b358-125eb8485a60 + private_key_data: | + -----BEGIN RSA PRIVATE KEY----- + not-really-a-key + -----END RSA PRIVATE KEY----- + v2_only_sign_requests: true + v2_only_authenticate: false + pubkey_cache_capacity: 42 +development: + <<: *common + mauth_baseurl: https://mauth-dev.example.com +"; + let section = MAuthInfo::config_section_from_yaml(yaml).unwrap(); + assert_eq!(section.mauth_baseurl, "https://mauth.example.com"); + assert!(section.private_key_file.is_none()); + let key = section.private_key_data.unwrap(); + assert!(key.starts_with("-----BEGIN RSA PRIVATE KEY-----\n")); + assert!(key.contains("not-really-a-key")); + assert_eq!(section.v2_only_sign_requests, Some(true)); + assert_eq!(section.v2_only_authenticate, Some(false)); + assert_eq!(section.pubkey_cache_capacity, Some(42)); + } + + #[test] + fn missing_common_section_returns_right_error() { + let yaml = "\ +development: + mauth_baseurl: https://mauth.example.com + mauth_api_version: v1 + app_uuid: c7db7fde-2448-11ef-b358-125eb8485a60 +"; + let result = MAuthInfo::config_section_from_yaml(yaml); + assert!(matches!(result, Err(ConfigReadError::InvalidFile(None)))); + } + + #[test] + fn missing_required_field_returns_right_error() { + let yaml = "\ +common: + mauth_baseurl: https://mauth.example.com + mauth_api_version: v1 +"; + let result = MAuthInfo::config_section_from_yaml(yaml); + assert!(matches!(result, Err(ConfigReadError::InvalidFile(Some(_))))); + } + + #[test] + fn malformed_yaml_returns_right_error() { + let result = MAuthInfo::config_section_from_yaml("common: [unterminated"); + assert!(matches!(result, Err(ConfigReadError::InvalidFile(Some(_))))); + } + #[tokio::test] async fn invalid_uri_returns_right_error() { let bad_config = ConfigFileSection {