-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdelete.go
More file actions
147 lines (119 loc) · 3.62 KB
/
delete.go
File metadata and controls
147 lines (119 loc) · 3.62 KB
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package cmd
import (
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
"pass-cli/internal/vault"
)
var (
deleteForce bool
)
var deleteCmd = &cobra.Command{
Use: "delete <service> [service...]",
GroupID: "credentials",
Aliases: []string{"rm", "remove"},
Short: "Delete credentials from the vault",
Long: `Delete removes one or more credentials from your vault.
By default, you'll see a usage warning if the credential has been accessed before,
showing where and when it was last used. This helps prevent accidental deletion
of actively-used credentials.
You can delete multiple credentials at once by providing multiple service names.
Use --force to skip all confirmation prompts (dangerous!).`,
Example: ` # Delete a single credential
pass-cli delete github
# Delete multiple credentials
pass-cli delete github gitlab bitbucket
# Delete with alias
pass-cli rm old-service
# Force delete without confirmation (dangerous!)
pass-cli delete github --force`,
Args: cobra.MinimumNArgs(1),
RunE: runDelete,
}
func init() {
rootCmd.AddCommand(deleteCmd)
deleteCmd.Flags().BoolVarP(&deleteForce, "force", "f", false, "skip confirmation prompts")
}
func runDelete(cmd *cobra.Command, args []string) error {
vaultPath := GetVaultPath()
// Check if vault exists
if _, err := os.Stat(vaultPath); os.IsNotExist(err) {
return fmt.Errorf("vault not found at %s\nRun 'pass-cli init' to create a vault first", vaultPath)
}
// Create vault service
vaultService, err := vault.New(vaultPath)
if err != nil {
return fmt.Errorf("failed to create vault service at %s: %w", vaultPath, err)
}
// Smart sync pull before unlock to get latest version
syncPullBeforeUnlock(vaultService)
// Unlock vault
if err := unlockVault(vaultService); err != nil {
return err
}
defer vaultService.Lock()
// Process each service to delete
deleted := 0
skipped := 0
for _, service := range args {
service = strings.TrimSpace(service)
if service == "" {
continue
}
// Check if credential exists and get metadata
cred, err := vaultService.GetCredential(service, false)
if err != nil {
fmt.Fprintf(os.Stderr, "❌ Error: %s - %v\n", service, err)
skipped++
continue
}
// Show usage warning if credential has been accessed
if !deleteForce {
stats, _ := vaultService.GetUsageStats(service)
if len(stats) > 0 {
fmt.Printf("\n⚠️ Warning: Deleting '%s'\n", service)
totalCount := 0
var lastAccessed string
for _, record := range stats {
totalCount += record.Count
if lastAccessed == "" || record.Timestamp.After(cred.UpdatedAt) {
lastAccessed = formatRelativeTime(record.Timestamp)
}
}
fmt.Printf(" Used in %d location(s), last used %s\n", len(stats), lastAccessed)
fmt.Printf(" Total access count: %d\n", totalCount)
fmt.Println()
} else {
fmt.Printf("\n🗑️ Deleting '%s' (never used)\n", service)
}
// Ask for confirmation
fmt.Print("Confirm deletion? (y/N): ")
var confirm string
_, _ = fmt.Scanln(&confirm)
confirm = strings.ToLower(strings.TrimSpace(confirm))
if confirm != "y" && confirm != "yes" {
fmt.Printf("⏭️ Skipped: %s\n", service)
skipped++
continue
}
}
// Delete the credential
if err := vaultService.DeleteCredential(service); err != nil {
fmt.Fprintf(os.Stderr, "❌ Error deleting %s: %v\n", service, err)
skipped++
continue
}
fmt.Printf("✅ Deleted: %s\n", service)
deleted++
}
// Summary
fmt.Println()
if deleted > 0 {
fmt.Printf("Successfully deleted %d credential(s)\n", deleted)
}
if skipped > 0 {
fmt.Printf("Skipped %d credential(s)\n", skipped)
}
return nil
}