diff --git a/action/audit.go b/action/audit.go index ce3e3c3224..eab9ee7d36 100644 --- a/action/audit.go +++ b/action/audit.go @@ -88,6 +88,10 @@ func (s *Action) Audit(ctx context.Context, c *cli.Context) error { close(checked) fmt.Println() // Print empty line after the progressbar. + return s.auditPrintResults(ctx, duplicates, messages, errors) +} + +func (s *Action) auditPrintResults(ctx context.Context, duplicates, messages, errors map[string][]string) error { foundDuplicates := false for _, secrets := range duplicates { if len(secrets) > 1 { diff --git a/action/clone.go b/action/clone.go index e593361241..2d122c648c 100644 --- a/action/clone.go +++ b/action/clone.go @@ -3,14 +3,11 @@ package action import ( "context" "fmt" - "os" - "os/exec" "github.com/fatih/color" + git "github.com/justwatchcom/gopass/backend/git/cli" "github.com/justwatchcom/gopass/config" - "github.com/justwatchcom/gopass/utils/fsutil" "github.com/justwatchcom/gopass/utils/out" - "github.com/pkg/errors" "github.com/urfave/cli" ) @@ -40,7 +37,7 @@ func (s *Action) clone(ctx context.Context, repo, mount, path string) error { } // clone repo - if err := gitClone(ctx, repo, path); err != nil { + if _, err := git.Clone(ctx, s.gpg.Binary(), repo, path); err != nil { return exitError(ctx, ExitGit, err, "failed to clone repo '%s' to '%s'", repo, path) } @@ -95,18 +92,3 @@ func (s *Action) clone(ctx context.Context, repo, mount, path string) error { return nil } - -func gitClone(ctx context.Context, repo, path string) error { - if fsutil.IsDir(path) { - return errors.Errorf("%s is a directory that already exists", path) - } - - fmt.Printf("Cloning repository %s to %s ...\n", repo, path) - - cmd := exec.CommandContext(ctx, "git", "clone", repo, path) - cmd.Stdout = os.Stdout - cmd.Stdin = os.Stdin - cmd.Stderr = os.Stderr - - return cmd.Run() -} diff --git a/action/delete.go b/action/delete.go index c4decdf700..6c43177a40 100644 --- a/action/delete.go +++ b/action/delete.go @@ -44,17 +44,7 @@ func (s *Action) Delete(ctx context.Context, c *cli.Context) error { // deletes a single key from a YAML doc if key != "" { - sec, err := s.Store.Get(ctx, name) - if err != nil { - return exitError(ctx, ExitIO, err, "Can not delete key '%s' from '%s': %s", key, name, err) - } - if err := sec.DeleteKey(key); err != nil { - return exitError(ctx, ExitIO, err, "Can not delete key '%s' from '%s': %s", key, name, err) - } - if err := s.Store.Set(sub.WithReason(ctx, "Updated Key in YAML"), name, sec); err != nil { - return exitError(ctx, ExitIO, err, "Can not delete key '%s' from '%s': %s", key, name, err) - } - return nil + return s.deleteKeyFromYAML(ctx, name, key) } if err := s.Store.Delete(ctx, name); err != nil { @@ -62,3 +52,17 @@ func (s *Action) Delete(ctx context.Context, c *cli.Context) error { } return nil } + +func (s *Action) deleteKeyFromYAML(ctx context.Context, name, key string) error { + sec, err := s.Store.Get(ctx, name) + if err != nil { + return exitError(ctx, ExitIO, err, "Can not delete key '%s' from '%s': %s", key, name, err) + } + if err := sec.DeleteKey(key); err != nil { + return exitError(ctx, ExitIO, err, "Can not delete key '%s' from '%s': %s", key, name, err) + } + if err := s.Store.Set(sub.WithReason(ctx, "Updated Key in YAML"), name, sec); err != nil { + return exitError(ctx, ExitIO, err, "Can not delete key '%s' from '%s': %s", key, name, err) + } + return nil +} diff --git a/action/hibp.go b/action/hibp.go index 57dfee3062..40218e00a5 100644 --- a/action/hibp.go +++ b/action/hibp.go @@ -102,6 +102,10 @@ func (s *Action) HIBP(ctx context.Context, c *cli.Context) error { <-done } + return s.printHIBPMatches(ctx, matchList) +} + +func (s *Action) printHIBPMatches(ctx context.Context, matchList []string) error { if len(matchList) < 0 { _ = notify.Notify("gopass - audit HIBP", "Good news - No matches found!") out.Green(ctx, "Good news - No matches found!") diff --git a/action/init.go b/action/init.go index 6c60947471..81430d3448 100644 --- a/action/init.go +++ b/action/init.go @@ -92,13 +92,7 @@ func (s *Action) init(ctx context.Context, alias, path string, nogit bool, keys } out.Green(ctx, "Password store %s initialized for:", path) - for _, recipient := range s.Store.ListRecipients(ctx, alias) { - r := "0x" + recipient - if kl, err := s.gpg.FindPublicKeys(ctx, recipient); err == nil && len(kl) > 0 { - r = kl[0].OneLine() - } - out.Yellow(ctx, " "+r) - } + s.printRecipients(ctx, path, alias) // write config if err := s.cfg.Save(); err != nil { @@ -108,6 +102,16 @@ func (s *Action) init(ctx context.Context, alias, path string, nogit bool, keys return nil } +func (s *Action) printRecipients(ctx context.Context, path, alias string) { + for _, recipient := range s.Store.ListRecipients(ctx, alias) { + r := "0x" + recipient + if kl, err := s.gpg.FindPublicKeys(ctx, recipient); err == nil && len(kl) > 0 { + r = kl[0].OneLine() + } + out.Yellow(ctx, " "+r) + } +} + // InitOnboarding will invoke the onboarding / setup wizard func (s *Action) InitOnboarding(ctx context.Context, c *cli.Context) error { remote := c.String("remote") diff --git a/action/recipients.go b/action/recipients.go index 6cced95991..ed91306a9a 100644 --- a/action/recipients.go +++ b/action/recipients.go @@ -134,29 +134,11 @@ func (s *Action) RecipientsRemove(ctx context.Context, c *cli.Context) error { // select recipient recipients := []string(c.Args()) if len(recipients) < 1 { - ids := s.Store.ListRecipients(ctx, store) - choices := make([]string, 0, len(ids)) - kl, err := s.gpg.FindPublicKeys(ctx, ids...) - if err == nil && kl != nil { - for _, id := range ids { - if key, err := kl.FindKey(id); err == nil { - choices = append(choices, key.OneLine()) - continue - } - choices = append(choices, id) - } - } - if len(choices) > 0 { - act, sel := termwiz.GetSelection(ctx, "Remove recipient -", "<↑/↓> to change the selection, <→> to remove this recipient, to quit", choices) - switch act { - case "default": - fallthrough - case "show": - recipients = []string{ids[sel]} - default: - return exitError(ctx, ExitAborted, nil, "user aborted") - } + rs, err := s.recipientsSelectForRemoval(ctx, store) + if err != nil { + return err } + recipients = rs } removed := 0 @@ -180,3 +162,30 @@ func (s *Action) RecipientsRemove(ctx context.Context, c *cli.Context) error { out.Cyan(ctx, "You need to run 'gopass sync' to push these changes") return nil } + +func (s *Action) recipientsSelectForRemoval(ctx context.Context, store string) ([]string, error) { + ids := s.Store.ListRecipients(ctx, store) + choices := make([]string, 0, len(ids)) + kl, err := s.gpg.FindPublicKeys(ctx, ids...) + if err == nil && kl != nil { + for _, id := range ids { + if key, err := kl.FindKey(id); err == nil { + choices = append(choices, key.OneLine()) + continue + } + choices = append(choices, id) + } + } + if len(choices) < 1 { + return nil, nil + } + act, sel := termwiz.GetSelection(ctx, "Remove recipient -", "<↑/↓> to change the selection, <→> to remove this recipient, to quit", choices) + switch act { + case "default": + fallthrough + case "show": + return []string{ids[sel]}, nil + default: + return nil, exitError(ctx, ExitAborted, nil, "user aborted") + } +} diff --git a/backend/git/cli/git.go b/backend/git/cli/git.go index b15fc9ff0f..0fd0ec7633 100644 --- a/backend/git/cli/git.go +++ b/backend/git/cli/git.go @@ -30,6 +30,20 @@ func New(path, gpg string) *Git { } } +// Clone clones an existing git repo and returns a new cli based git backend +// configured for this clone repo +func Clone(ctx context.Context, gpg, repo, path string) (*Git, error) { + g := &Git{ + gpg: gpg, + path: filepath.Dir(path), + } + if err := g.Cmd(ctx, "Clone", "clone", repo, path); err != nil { + return nil, err + } + g.path = path + return g, nil +} + // Cmd runs an git command func (g *Git) Cmd(ctx context.Context, name string, args ...string) error { buf := &bytes.Buffer{} diff --git a/utils/jsonapi/manifest/location.go b/utils/jsonapi/manifest/location.go index 238faa9085..33947fc3a9 100644 --- a/utils/jsonapi/manifest/location.go +++ b/utils/jsonapi/manifest/location.go @@ -2,68 +2,59 @@ package manifest import ( "fmt" - "path" "runtime" ) +var globalLocations = map[string]map[string]string{ + "darwin": map[string]string{ + "firefox": "/Library/Application Support/Mozilla/NativeMessagingHosts/%s.json", + "chrome": "/Library/Google/Chrome/NativeMessagingHosts/%s.json", + "chromium": "/Library/Application Support/Chromium/NativeMessagingHosts/%s.json", + }, + "linux": map[string]string{ + "firefox": "mozilla/native-messaging-hosts/%s.json", + "chrome": "/etc/opt/chrome/native-messaging-hosts/%s.json", + "chromium": "/etc/chromium/native-messaging-hosts/%s.json", + }, +} + +var locations = map[string]map[string]string{ + "darwin": map[string]string{ + "firefox": "~/Library/Application Support/Mozilla/NativeMessagingHosts/%s.json", + "chrome": "~/Library/Application Support/Google/Chrome/NativeMessagingHosts/%s.json", + "chromium": "~/Library/Application Support/Chromium/NativeMessagingHosts/%s.json", + }, + "linux": map[string]string{ + "firefox": "~/.mozilla/native-messaging-hosts/%s.json", + "chrome": "~/.config/google-chrome/NativeMessagingHosts/%s.json", + "chromium": "~/.config/chromium/NativeMessagingHosts/%s.json", + }, +} + func getLocation(browser, libpath string, globalInstall bool) (string, error) { - switch platform := runtime.GOOS; platform { - case "darwin": - { - switch browser { - case "firefox": - { - if globalInstall { - return "/Library/Application Support/Mozilla/NativeMessagingHosts/%s.json", nil - } - return "~/Library/Application Support/Mozilla/NativeMessagingHosts/%s.json", nil - } - case "chrome": - { - if globalInstall { - return "/Library/Google/Chrome/NativeMessagingHosts/%s.json", nil - } - return "~/Library/Application Support/Google/Chrome/NativeMessagingHosts/%s.json", nil - } - case "chromium": - { - if globalInstall { - return "/Library/Application Support/Chromium/NativeMessagingHosts/%s.json", nil - } - return "~/Library/Application Support/Chromium/NativeMessagingHosts/%s.json", nil - } - } + platform := runtime.GOOS + if globalInstall { + pm, found := globalLocations[platform] + if !found { + return "", fmt.Errorf("platform %s is currently not supported", platform) } - case "linux": - { - switch browser { - case "firefox": - { - if globalInstall { - return path.Join(libpath, "mozilla/native-messaging-hosts/%s.json"), nil - } - return "~/.mozilla/native-messaging-hosts/%s.json", nil - } - case "chrome": - { - if globalInstall { - return "/etc/opt/chrome/native-messaging-hosts/%s.json", nil - } - return "~/.config/google-chrome/NativeMessagingHosts/%s.json", nil - } - case "chromium": - { - if globalInstall { - return "/etc/chromium/native-messaging-hosts/%s.json", nil - } - return "~/.config/chromium/NativeMessagingHosts/%s.json", nil - } - } + path, found := pm[browser] + if !found { + return "", fmt.Errorf("browser %s on %s is currently not supported", browser, platform) } - default: - { - return "", fmt.Errorf("platform %s is currently not supported", platform) + if browser == "firefox" { + path = libpath + "/" + path } + return path, nil + } + + pm, found := locations[platform] + if !found { + return "", fmt.Errorf("platform %s is currently not supported", platform) + } + path, found := pm[browser] + if !found { + return "", fmt.Errorf("browser %s on %s is currently not supported", browser, platform) } - return "", nil + return path, nil }