upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-01-11 21:07:33 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-01-11 21:07:33 +0000
commit809982cdc78e287bc9f3fc0dbac5e2aab2fd7f7d (patch)
tree6e2663dcb1d2db77b870dbf833b9969696e63dcd
parentc89d3b6b3646b707b53146226bb7afd21cca11fa (diff)
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.
-rw-r--r--nix/module.nix3
-rw-r--r--src/config.rs36
2 files changed, 37 insertions, 2 deletions
diff --git a/nix/module.nix b/nix/module.nix
index 60b8d5f..d820b67 100644
--- a/nix/module.nix
+++ b/nix/module.nix
@@ -245,8 +245,7 @@ let
245 # Command to run 245 # Command to run
246 ExecStart = if cfg.relayOwnerNsecFile != null then 246 ExecStart = if cfg.relayOwnerNsecFile != null then
247 # Use nsec from file - need to use shell to read the file 247 # Use nsec from file - need to use shell to read the file
248 # Use tr to remove trailing newline which would invalidate the nsec 248 "${pkgs.bash}/bin/bash -c '${ngit-grasp}/bin/ngit-grasp --relay-owner-nsec \"$(cat ${cfg.relayOwnerNsecFile})\"'"
249 "${pkgs.bash}/bin/bash -c '${ngit-grasp}/bin/ngit-grasp --relay-owner-nsec \"$(cat ${cfg.relayOwnerNsecFile} | tr -d \"\\n\")\"'"
250 else 249 else
251 # Let ngit-grasp auto-generate nsec in .relay-owner.nsec file in dataDir 250 # Let ngit-grasp auto-generate nsec in .relay-owner.nsec file in dataDir
252 "${ngit-grasp}/bin/ngit-grasp"; 251 "${ngit-grasp}/bin/ngit-grasp";
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 {
185 // If relay_owner_nsec not provided, load from file or generate 185 // If relay_owner_nsec not provided, load from file or generate
186 if config.relay_owner_nsec.is_none() { 186 if config.relay_owner_nsec.is_none() {
187 config.relay_owner_nsec = Some(Self::load_or_generate_relay_owner_key()?); 187 config.relay_owner_nsec = Some(Self::load_or_generate_relay_owner_key()?);
188 } else {
189 // If provided via CLI/env, trim any whitespace (newlines, spaces, etc.)
190 // This handles cases where the value is read from a file with trailing newline
191 config.relay_owner_nsec = config.relay_owner_nsec.map(|s| s.trim().to_string());
188 } 192 }
189 193
190 Ok(config) 194 Ok(config)
@@ -371,6 +375,38 @@ mod tests {
371 } 375 }
372 376
373 #[test] 377 #[test]
378 fn test_relay_owner_nsec_trims_whitespace() {
379 // Test that Config::load() trims whitespace from provided nsec
380 // This simulates what happens when nsec is read from a file with trailing newline
381 let nsec_clean = "nsec1rt5f3gfnktvd77fdarg00ff94l8j833y778ym3xlzkx89g9v5zvq4y2qee";
382 let nsec_with_newline = format!("{}\n", nsec_clean);
383 let nsec_with_spaces = format!(" {} ", nsec_clean);
384
385 // Test that trimming happens by directly creating config with whitespace
386 let mut config1 = Config::for_testing();
387 config1.relay_owner_nsec = Some(nsec_with_newline.clone());
388 // Simulate what Config::load() does
389 config1.relay_owner_nsec = config1.relay_owner_nsec.map(|s| s.trim().to_string());
390
391 let mut config2 = Config::for_testing();
392 config2.relay_owner_nsec = Some(nsec_with_spaces.clone());
393 config2.relay_owner_nsec = config2.relay_owner_nsec.map(|s| s.trim().to_string());
394
395 // Both should parse successfully after trimming
396 assert!(config1.relay_owner_keys().is_ok());
397 assert!(config2.relay_owner_keys().is_ok());
398
399 // Both should produce the same public key
400 let keys1 = config1.relay_owner_keys().unwrap();
401 let keys2 = config2.relay_owner_keys().unwrap();
402 assert_eq!(keys1.public_key(), keys2.public_key());
403
404 // Verify trimmed nsec equals clean nsec
405 assert_eq!(config1.relay_owner_nsec.unwrap(), nsec_clean);
406 assert_eq!(config2.relay_owner_nsec.unwrap(), nsec_clean);
407 }
408
409 #[test]
374 fn test_metrics_config_defaults() { 410 fn test_metrics_config_defaults() {
375 let config = Config::for_testing(); 411 let config = Config::for_testing();
376 assert!(config.metrics_enabled); 412 assert!(config.metrics_enabled);