From 809982cdc78e287bc9f3fc0dbac5e2aab2fd7f7d Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Sun, 11 Jan 2026 21:07:33 +0000 Subject: fix(config): trim whitespace from relay-owner-nsec CLI/env input When relay_owner_nsec is provided via CLI argument or environment variable (e.g., read from a file by the NixOS module), trim any leading/trailing whitespace including newlines. This matches the behavior when reading from the .relay-owner.nsec file directly. Fixes issue where NixOS module reads nsec file with 'cat', which includes the trailing newline, making the nsec invalid when passed as a CLI argument. Also reverted the tr workaround in nix/module.nix since ngit-grasp now handles this correctly. --- src/config.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'src/config.rs') diff --git a/src/config.rs b/src/config.rs index 74327c9..1812fe2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -185,6 +185,10 @@ impl Config { // If relay_owner_nsec not provided, load from file or generate if config.relay_owner_nsec.is_none() { config.relay_owner_nsec = Some(Self::load_or_generate_relay_owner_key()?); + } else { + // If provided via CLI/env, trim any whitespace (newlines, spaces, etc.) + // This handles cases where the value is read from a file with trailing newline + config.relay_owner_nsec = config.relay_owner_nsec.map(|s| s.trim().to_string()); } Ok(config) @@ -370,6 +374,38 @@ mod tests { assert!(npub.starts_with("npub1")); } + #[test] + fn test_relay_owner_nsec_trims_whitespace() { + // Test that Config::load() trims whitespace from provided nsec + // This simulates what happens when nsec is read from a file with trailing newline + let nsec_clean = "nsec1rt5f3gfnktvd77fdarg00ff94l8j833y778ym3xlzkx89g9v5zvq4y2qee"; + let nsec_with_newline = format!("{}\n", nsec_clean); + let nsec_with_spaces = format!(" {} ", nsec_clean); + + // Test that trimming happens by directly creating config with whitespace + let mut config1 = Config::for_testing(); + config1.relay_owner_nsec = Some(nsec_with_newline.clone()); + // Simulate what Config::load() does + config1.relay_owner_nsec = config1.relay_owner_nsec.map(|s| s.trim().to_string()); + + let mut config2 = Config::for_testing(); + config2.relay_owner_nsec = Some(nsec_with_spaces.clone()); + config2.relay_owner_nsec = config2.relay_owner_nsec.map(|s| s.trim().to_string()); + + // Both should parse successfully after trimming + assert!(config1.relay_owner_keys().is_ok()); + assert!(config2.relay_owner_keys().is_ok()); + + // Both should produce the same public key + let keys1 = config1.relay_owner_keys().unwrap(); + let keys2 = config2.relay_owner_keys().unwrap(); + assert_eq!(keys1.public_key(), keys2.public_key()); + + // Verify trimmed nsec equals clean nsec + assert_eq!(config1.relay_owner_nsec.unwrap(), nsec_clean); + assert_eq!(config2.relay_owner_nsec.unwrap(), nsec_clean); + } + #[test] fn test_metrics_config_defaults() { let config = Config::for_testing(); -- cgit v1.2.3