Fix vault creation to require mnemonic and set up initial unlocker
- Vault creation now prompts for mnemonic if not in environment - Automatically creates passphrase unlocker during vault creation - Prevents 'missing public key' error when adding secrets to new vaults - Updates tests to reflect new vault creation flow
This commit is contained in:
@@ -39,10 +39,12 @@ func newAddCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
func newGetCmd() *cobra.Command {
|
||||
cli := NewCLIInstance()
|
||||
cmd := &cobra.Command{
|
||||
Use: "get <secret-name>",
|
||||
Short: "Retrieve a secret from the vault",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Use: "get <secret-name>",
|
||||
Short: "Retrieve a secret from the vault",
|
||||
Args: cobra.ExactArgs(1),
|
||||
ValidArgsFunction: getSecretNamesCompletionFunc(cli.fs, cli.stateDir),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
version, _ := cmd.Flags().GetString("version")
|
||||
cli := NewCLIInstance()
|
||||
@@ -108,13 +110,15 @@ func newImportCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
func newRemoveCmd() *cobra.Command {
|
||||
cli := NewCLIInstance()
|
||||
cmd := &cobra.Command{
|
||||
Use: "remove <secret-name>",
|
||||
Aliases: []string{"rm"},
|
||||
Short: "Remove a secret from the vault",
|
||||
Long: `Remove a secret and all its versions from the current vault. This action is permanent and ` +
|
||||
`cannot be undone.`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Args: cobra.ExactArgs(1),
|
||||
ValidArgsFunction: getSecretNamesCompletionFunc(cli.fs, cli.stateDir),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
cli := NewCLIInstance()
|
||||
|
||||
@@ -126,6 +130,7 @@ func newRemoveCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
func newMoveCmd() *cobra.Command {
|
||||
cli := NewCLIInstance()
|
||||
cmd := &cobra.Command{
|
||||
Use: "move <source> <destination>",
|
||||
Aliases: []string{"mv", "rename"},
|
||||
@@ -133,6 +138,14 @@ func newMoveCmd() *cobra.Command {
|
||||
Long: `Move or rename a secret within the current vault. ` +
|
||||
`If the destination already exists, the operation will fail.`,
|
||||
Args: cobra.ExactArgs(2), //nolint:mnd // Command requires exactly 2 arguments: source and destination
|
||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
// Only complete the first argument (source)
|
||||
if len(args) == 0 {
|
||||
return getSecretNamesCompletionFunc(cli.fs, cli.stateDir)(cmd, args, toComplete)
|
||||
}
|
||||
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
cli := NewCLIInstance()
|
||||
|
||||
@@ -360,20 +373,21 @@ func (cli *Instance) ListSecrets(cmd *cobra.Command, jsonOutput bool, quietOutpu
|
||||
return fmt.Errorf("failed to marshal JSON: %w", err)
|
||||
}
|
||||
|
||||
cmd.Println(string(jsonBytes))
|
||||
_, _ = fmt.Fprintln(cmd.OutOrStdout(), string(jsonBytes))
|
||||
} else if quietOutput {
|
||||
// Quiet output - just secret names
|
||||
for _, secretName := range filteredSecrets {
|
||||
cmd.Println(secretName)
|
||||
_, _ = fmt.Fprintln(cmd.OutOrStdout(), secretName)
|
||||
}
|
||||
} else {
|
||||
// Pretty table output
|
||||
out := cmd.OutOrStdout()
|
||||
if len(filteredSecrets) == 0 {
|
||||
if filter != "" {
|
||||
cmd.Printf("No secrets found in vault '%s' matching filter '%s'.\n", vlt.GetName(), filter)
|
||||
_, _ = fmt.Fprintf(out, "No secrets found in vault '%s' matching filter '%s'.\n", vlt.GetName(), filter)
|
||||
} else {
|
||||
cmd.Println("No secrets found in current vault.")
|
||||
cmd.Println("Run 'secret add <name>' to create one.")
|
||||
_, _ = fmt.Fprintln(out, "No secrets found in current vault.")
|
||||
_, _ = fmt.Fprintln(out, "Run 'secret add <name>' to create one.")
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -381,12 +395,25 @@ func (cli *Instance) ListSecrets(cmd *cobra.Command, jsonOutput bool, quietOutpu
|
||||
|
||||
// Get current vault name for display
|
||||
if filter != "" {
|
||||
cmd.Printf("Secrets in vault '%s' matching '%s':\n\n", vlt.GetName(), filter)
|
||||
_, _ = fmt.Fprintf(out, "Secrets in vault '%s' matching '%s':\n\n", vlt.GetName(), filter)
|
||||
} else {
|
||||
cmd.Printf("Secrets in vault '%s':\n\n", vlt.GetName())
|
||||
_, _ = fmt.Fprintf(out, "Secrets in vault '%s':\n\n", vlt.GetName())
|
||||
}
|
||||
cmd.Printf("%-40s %-20s\n", "NAME", "LAST UPDATED")
|
||||
cmd.Printf("%-40s %-20s\n", "----", "------------")
|
||||
|
||||
// Calculate the maximum name length for proper column alignment
|
||||
maxNameLen := len("NAME") // Start with header length
|
||||
for _, secretName := range filteredSecrets {
|
||||
if len(secretName) > maxNameLen {
|
||||
maxNameLen = len(secretName)
|
||||
}
|
||||
}
|
||||
// Add some padding
|
||||
maxNameLen += 2
|
||||
|
||||
// Print headers with dynamic width
|
||||
nameFormat := fmt.Sprintf("%%-%ds", maxNameLen)
|
||||
_, _ = fmt.Fprintf(out, nameFormat+" %-20s\n", "NAME", "LAST UPDATED")
|
||||
_, _ = fmt.Fprintf(out, nameFormat+" %-20s\n", strings.Repeat("-", len("NAME")), "------------")
|
||||
|
||||
for _, secretName := range filteredSecrets {
|
||||
lastUpdated := "unknown"
|
||||
@@ -394,14 +421,14 @@ func (cli *Instance) ListSecrets(cmd *cobra.Command, jsonOutput bool, quietOutpu
|
||||
metadata := secretObj.GetMetadata()
|
||||
lastUpdated = metadata.UpdatedAt.Format("2006-01-02 15:04")
|
||||
}
|
||||
cmd.Printf("%-40s %-20s\n", secretName, lastUpdated)
|
||||
_, _ = fmt.Fprintf(out, nameFormat+" %-20s\n", secretName, lastUpdated)
|
||||
}
|
||||
|
||||
cmd.Printf("\nTotal: %d secret(s)", len(filteredSecrets))
|
||||
_, _ = fmt.Fprintf(out, "\nTotal: %d secret(s)", len(filteredSecrets))
|
||||
if filter != "" {
|
||||
cmd.Printf(" (filtered from %d)", len(secrets))
|
||||
_, _ = fmt.Fprintf(out, " (filtered from %d)", len(secrets))
|
||||
}
|
||||
cmd.Println()
|
||||
_, _ = fmt.Fprintln(out)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user