diff --git a/src/secrets/CommandEdit.ts b/src/secrets/CommandEdit.ts index afdfe442..bc39ff09 100644 --- a/src/secrets/CommandEdit.ts +++ b/src/secrets/CommandEdit.ts @@ -22,7 +22,9 @@ class CommandEdit extends CommandPolykey { this.addOption(binOptions.nodeId); this.addOption(binOptions.clientHost); this.addOption(binOptions.clientPort); - this.action(async (secretPath, options) => { + this.action(async (fullSecretPath, options) => { + const vaultName = fullSecretPath[0]; + const secretPath = fullSecretPath[1] ?? '/'; const os = await import('os'); const { spawn } = await import('child_process'); const vaultsErrors = await import('polykey/dist/vaults/errors'); @@ -60,13 +62,13 @@ class CommandEdit extends CommandPolykey { }, logger: this.logger.getChild(PolykeyClient.name), }); - const tmpFile = path.join(tmpDir, path.basename(secretPath[1])); + const tmpFile = path.join(tmpDir, path.basename(secretPath)); const secretExists = await binUtils.retryAuthentication( async (auth) => { let exists = true; const response = await pkClient.rpcClient.methods.vaultsSecretsGet({ - nameOrId: secretPath[0], - secretName: secretPath[1] ?? '/', + nameOrId: vaultName, + secretName: secretPath, metadata: auth, }); try { @@ -86,7 +88,7 @@ class CommandEdit extends CommandPolykey { // First, write the inline error to standard error like other // secrets commands do. process.stderr.write( - `edit: ${secretPath[1] ?? '/'}: No such file or directory\n`, + `edit: ${secretPath}: No such file or directory\n`, ); // Then, throw an error to get the non-zero exit code. As this // command is Polykey-specific, the code doesn't really matter @@ -160,8 +162,8 @@ class CommandEdit extends CommandPolykey { async (auth) => await pkClient.rpcClient.methods.vaultsSecretsWriteFile({ metadata: auth, - nameOrId: secretPath[0], - secretName: secretPath[1], + nameOrId: vaultName, + secretName: secretPath, secretContent: content, }), meta, diff --git a/src/secrets/CommandEnv.ts b/src/secrets/CommandEnv.ts index c6549263..bf97a577 100644 --- a/src/secrets/CommandEnv.ts +++ b/src/secrets/CommandEnv.ts @@ -24,7 +24,7 @@ class CommandEnv extends CommandPolykey { this.addOption(binOptions.envDuplicate); this.addOption(binOptions.preserveNewline); this.argument( - '', + '[args...]', 'command and arguments formatted as [envPaths...][-- cmd [cmdArgs...]]', binParsers.parseEnvArgs, ); @@ -34,7 +34,17 @@ class CommandEnv extends CommandPolykey { args: [Array<[string, string?, string?]>, Array], options, ) => { - args[1].shift(); + // The parser sets the default value for args. If no arguments are + // provided, then args is an empty array []. This is different from the + // expected structure. This block ensure that the structure is preserved. + args = args[0] == null && args[1] == null ? [[], []] : args; + + // There needs to be at least one argument or preserved argument provided + if (args[0].length === 0 && options.preserveNewline.length === 0) { + this.help(); + } + // Remove the -- from the command arguments + args[1]?.shift(); const { default: PolykeyClient } = await import( 'polykey/dist/PolykeyClient' ); @@ -55,6 +65,10 @@ class CommandEnv extends CommandPolykey { // b. output the env variables in the desired format const [envVariables, [cmd, ...argv]] = args; + // Append the secret paths which we want to preserve the newlines of + if (options.preserveNewline) { + envVariables.push(...options.preserveNewline); + } const clientOptions = await binProcessors.processClientOptions( options.nodePath, options.nodeId, @@ -161,8 +175,20 @@ class CommandEnv extends CommandPolykey { utils.never(); } } + + // Find if we need to preserve the newline for this secret + let preserveNewline = false; + if (options.preserveNewline) { + for (const pair of options.preserveNewline) { + if (pair[1] === secretName) { + preserveNewline = true; + break; + } + } + } + // Trim the single trailing newline if it exists - if (secretContent.endsWith('\n')) { + if (!preserveNewline && secretContent.endsWith('\n')) { envp[newName] = secretContent.slice(0, -1); } else { envp[newName] = secretContent; diff --git a/src/utils/options.ts b/src/utils/options.ts index 0f16ff94..d2e3108f 100644 --- a/src/utils/options.ts +++ b/src/utils/options.ts @@ -319,10 +319,14 @@ const parents = new commander.Option( ).default(false); const preserveNewline = new commander.Option( - '--preserve-newline ', + '-pn --preserve-newline ', 'Preserve the last trailing newline for the secret content', ) - .argParser(binParsers.parseSecretPathEnv) + .argParser((value: string, previous: Array<[string, string?, string?]>) => { + const out = previous ?? []; + out.push(binParsers.parseSecretPathEnv(value)); + return out; + }) .default(undefined); export {