forked from gopasspw/gopass
/
delete.go
111 lines (87 loc) · 3.11 KB
/
delete.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package action
import (
"context"
"fmt"
"github.com/kpitt/gopass/internal/action/exit"
"github.com/kpitt/gopass/pkg/ctxutil"
"github.com/kpitt/gopass/pkg/debug"
"github.com/kpitt/gopass/pkg/termio"
"github.com/urfave/cli/v2"
)
// Delete a secret file with its content.
func (s *Action) Delete(c *cli.Context) error {
ctx := ctxutil.WithGlobalFlags(c)
recursive := c.Bool("recursive")
name := c.Args().First()
if name == "" {
return exit.Error(exit.Usage, nil, "Usage: %s rm name", s.Name)
}
if recursive {
if len(c.Args().Tail()) > 1 {
return exit.Error(exit.Usage, nil, "Deleting multiple keys is not supported in recursive mode")
}
return s.deleteRecursive(ctx, name, c.Bool("force"))
}
if s.Store.IsDir(ctx, name) && !s.Store.Exists(ctx, name) {
return exit.Error(exit.Usage, nil, "Cannot remove %q: Is a directory. Use 'gopass rm -r %s' to delete", name, name)
}
// specifying a key is optional.
key := c.Args().Get(1)
// multiple secrets, so not a key
if len(c.Args().Tail()) > 1 {
key = ""
}
names := append([]string{name}, c.Args().Tail()...)
if key != "" && s.Store.Exists(ctx, key) {
return exit.Error(exit.Unsupported, nil, "Key %q clashes with a secret of this name, use 'gopass edit %s' to delete", key, name)
}
if !s.Store.Exists(ctx, name) {
return exit.Error(exit.NotFound, nil, "Secret %q does not exist", name)
}
if !c.Bool("force") { // don't check if it's force anyway.
qStr := fmt.Sprintf("☠ Are you sure you would like to delete %q?", names)
if key != "" {
qStr = fmt.Sprintf("☠ Are you sure you would like to delete %q from %q?", key, name)
}
if (s.Store.Exists(ctx, name) || s.Store.IsDir(ctx, name)) && key == "" && !termio.AskForConfirmation(ctx, qStr) {
return nil
}
}
// deletes a single key from a YAML doc.
if key != "" {
debug.Log("removing key %q from %q", key, name)
return s.deleteKeyFromYAML(ctx, name, key)
}
for _, name := range names {
debug.Log("removing entry %q", name)
if err := s.Store.Delete(ctx, name); err != nil {
return exit.Error(exit.IO, err, "Can not delete %q: %s", name, err)
}
}
return nil
}
func (s *Action) deleteRecursive(ctx context.Context, name string, force bool) error {
if !force { // don't check if it's force anyway.
if (s.Store.Exists(ctx, name) || s.Store.IsDir(ctx, name)) && !termio.AskForConfirmation(ctx, fmt.Sprintf("☠ Are you sure you would like to recursively delete %q?", name)) {
return nil
}
}
debug.Log("pruning %q", name)
if err := s.Store.Prune(ctx, name); err != nil {
return exit.Error(exit.Unknown, err, "failed to prune %q: %s", name, err)
}
debug.Log("pruned %q", name)
return nil
}
// deleteKeyFromYAML deletes a single key from YAML.
func (s *Action) deleteKeyFromYAML(ctx context.Context, name, key string) error {
sec, err := s.Store.Get(ctx, name)
if err != nil {
return exit.Error(exit.IO, err, "Can not delete key %q from %q: %s", key, name, err)
}
sec.Del(key)
if err := s.Store.Set(ctxutil.WithCommitMessage(ctx, "Updated Key"), name, sec); err != nil {
return exit.Error(exit.IO, err, "Can not delete key %q from %q: %s", key, name, err)
}
return nil
}