All checks were successful
check / check (push) Successful in 1m8s
- Replace .golangci.yml with the canonical strict config (all linters enabled except the standard disable list; lll 88, funlen 80/50, cyclop 15, dupl 100; test files now linted) - Pin the Dockerfile lint stage to golangci/golangci-lint:v2.12.2 by tag and digest (Debian-based) - Fix all ~1550 findings surfaced by the new config: line wrapping, wsl_v5/nlreturn blank lines, noinlineerr splits, err113 sentinel errors, perfsprint/modernize rewrites, goconst constants, thelper, testifylint, noctx CommandContext, testpackage conversions, t.Parallel() where safe, and complexity/dupl helper extraction - Record the change and follow-up items in TODO.md
191 lines
5.2 KiB
Go
191 lines
5.2 KiB
Go
package cli
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"git.eeqj.de/sneak/secret/internal/vault"
|
|
"github.com/spf13/afero"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// getSecretNamesCompletionFunc returns a completion function that provides
|
|
// secret names
|
|
func getSecretNamesCompletionFunc(fs afero.Fs, stateDir string) func(
|
|
cmd *cobra.Command, args []string, toComplete string,
|
|
) ([]string, cobra.ShellCompDirective) {
|
|
return func(
|
|
_ *cobra.Command, _ []string, toComplete string,
|
|
) ([]string, cobra.ShellCompDirective) {
|
|
// Get current vault
|
|
vlt, err := vault.GetCurrentVault(fs, stateDir)
|
|
if err != nil {
|
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
}
|
|
|
|
// Get list of secrets
|
|
secrets, err := vlt.ListSecrets()
|
|
if err != nil {
|
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
}
|
|
|
|
// Filter secrets based on what user has typed
|
|
var completions []string
|
|
|
|
for _, secret := range secrets {
|
|
if strings.HasPrefix(secret, toComplete) {
|
|
completions = append(completions, secret)
|
|
}
|
|
}
|
|
|
|
return completions, cobra.ShellCompDirectiveNoFileComp
|
|
}
|
|
}
|
|
|
|
// getUnlockerIDsCompletionFunc returns a completion function that provides
|
|
// unlocker IDs
|
|
func getUnlockerIDsCompletionFunc(fs afero.Fs, stateDir string) func(
|
|
cmd *cobra.Command, args []string, toComplete string,
|
|
) ([]string, cobra.ShellCompDirective) {
|
|
return func(
|
|
_ *cobra.Command, _ []string, toComplete string,
|
|
) ([]string, cobra.ShellCompDirective) {
|
|
// Get current vault
|
|
vlt, err := vault.GetCurrentVault(fs, stateDir)
|
|
if err != nil {
|
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
}
|
|
|
|
// Get unlocker metadata list
|
|
unlockerMetadataList, err := vlt.ListUnlockers()
|
|
if err != nil {
|
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
}
|
|
|
|
// Get vault directory
|
|
vaultDir, err := vlt.GetDirectory()
|
|
if err != nil {
|
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
}
|
|
|
|
// Collect unlocker IDs
|
|
var completions []string
|
|
|
|
unlockersDir := filepath.Join(vaultDir, "unlockers.d")
|
|
|
|
for _, metadata := range unlockerMetadataList {
|
|
// Get the actual unlocker ID by creating the unlocker instance
|
|
id := findUnlockerIDByMetadata(fs, unlockersDir, metadata, false)
|
|
if id != "" && strings.HasPrefix(id, toComplete) {
|
|
completions = append(completions, id)
|
|
}
|
|
}
|
|
|
|
return completions, cobra.ShellCompDirectiveNoFileComp
|
|
}
|
|
}
|
|
|
|
// getVaultNamesCompletionFunc returns a completion function that provides
|
|
// vault names
|
|
func getVaultNamesCompletionFunc(fs afero.Fs, stateDir string) func(
|
|
cmd *cobra.Command, args []string, toComplete string,
|
|
) ([]string, cobra.ShellCompDirective) {
|
|
return func(
|
|
_ *cobra.Command, _ []string, toComplete string,
|
|
) ([]string, cobra.ShellCompDirective) {
|
|
vaults, err := vault.ListVaults(fs, stateDir)
|
|
if err != nil {
|
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
}
|
|
|
|
var completions []string
|
|
|
|
for _, v := range vaults {
|
|
if strings.HasPrefix(v, toComplete) {
|
|
completions = append(completions, v)
|
|
}
|
|
}
|
|
|
|
return completions, cobra.ShellCompDirectiveNoFileComp
|
|
}
|
|
}
|
|
|
|
// completeVaultQualifiedSecrets completes "vault:secret" references once a
|
|
// colon is present in the input
|
|
func completeVaultQualifiedSecrets(
|
|
fs afero.Fs, stateDir, toComplete string,
|
|
) []string {
|
|
var completions []string
|
|
|
|
// Complete secret names for the specified vault
|
|
parts := strings.SplitN(toComplete, ":", vaultSecretParts)
|
|
vaultName := parts[0]
|
|
secretPrefix := parts[1]
|
|
|
|
vlt := vault.NewVault(fs, stateDir, vaultName)
|
|
|
|
secrets, err := vlt.ListSecrets()
|
|
if err == nil {
|
|
for _, secretName := range secrets {
|
|
if strings.HasPrefix(secretName, secretPrefix) {
|
|
completions = append(completions, vaultName+":"+secretName)
|
|
}
|
|
}
|
|
}
|
|
|
|
return completions
|
|
}
|
|
|
|
// completeUnqualifiedVaultSecrets completes vault names (with a ":"
|
|
// suffix) and secrets from the current vault
|
|
func completeUnqualifiedVaultSecrets(
|
|
fs afero.Fs, stateDir, toComplete string,
|
|
) []string {
|
|
var completions []string
|
|
|
|
// Complete vault names with ":" suffix
|
|
vaults, err := vault.ListVaults(fs, stateDir)
|
|
if err == nil {
|
|
for _, v := range vaults {
|
|
if strings.HasPrefix(v, toComplete) {
|
|
completions = append(completions, v+":")
|
|
}
|
|
}
|
|
}
|
|
|
|
// Also complete secrets from current vault (for within-vault moves)
|
|
currentVlt, err := vault.GetCurrentVault(fs, stateDir)
|
|
if err == nil {
|
|
secrets, err := currentVlt.ListSecrets()
|
|
if err == nil {
|
|
for _, secretName := range secrets {
|
|
if strings.HasPrefix(secretName, toComplete) {
|
|
completions = append(completions, secretName)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return completions
|
|
}
|
|
|
|
// getVaultSecretCompletionFunc returns a completion function for the
|
|
// vault:secret format. It completes vault names with ":" suffix, and
|
|
// after ":" it completes secrets from that vault.
|
|
func getVaultSecretCompletionFunc(fs afero.Fs, stateDir string) func(
|
|
cmd *cobra.Command, args []string, toComplete string,
|
|
) ([]string, cobra.ShellCompDirective) {
|
|
return func(
|
|
_ *cobra.Command, _ []string, toComplete string,
|
|
) ([]string, cobra.ShellCompDirective) {
|
|
// Check if we're completing after a vault: prefix
|
|
if strings.Contains(toComplete, ":") {
|
|
return completeVaultQualifiedSecrets(fs, stateDir, toComplete),
|
|
cobra.ShellCompDirectiveNoFileComp
|
|
}
|
|
|
|
return completeUnqualifiedVaultSecrets(fs, stateDir, toComplete),
|
|
cobra.ShellCompDirectiveNoSpace
|
|
}
|
|
}
|