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.
This commit is contained in:
DanConwayDev
2026-01-11 21:07:33 +00:00
parent c89d3b6b36
commit 809982cdc7
2 changed files with 37 additions and 2 deletions
+1 -2
View File
@@ -245,8 +245,7 @@ let
# Command to run
ExecStart = if cfg.relayOwnerNsecFile != null then
# Use nsec from file - need to use shell to read the file
# Use tr to remove trailing newline which would invalidate the nsec
"${pkgs.bash}/bin/bash -c '${ngit-grasp}/bin/ngit-grasp --relay-owner-nsec \"$(cat ${cfg.relayOwnerNsecFile} | tr -d \"\\n\")\"'"
"${pkgs.bash}/bin/bash -c '${ngit-grasp}/bin/ngit-grasp --relay-owner-nsec \"$(cat ${cfg.relayOwnerNsecFile})\"'"
else
# Let ngit-grasp auto-generate nsec in .relay-owner.nsec file in dataDir
"${ngit-grasp}/bin/ngit-grasp";
+36
View File
@@ -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();