Skip to content

Commit 2949164

Browse files
committed
chore(cli): support deleting tokens by id
1 parent 8d8d41e commit 2949164

File tree

4 files changed

+91
-6
lines changed

4 files changed

+91
-6
lines changed
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
coder v0.0.0-devel
22

33
USAGE:
4-
coder tokens remove <name>
4+
coder tokens remove [flags] <name|id|token>
55

66
Delete a token
77

88
Aliases: delete, rm
99

10+
OPTIONS:
11+
-y, --yes bool
12+
Bypass prompts.
13+
1014
———
1115
Run `coder --help` for a list of global options.

cli/tokens.go

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ package cli
33
import (
44
"fmt"
55
"os"
6+
"strings"
67
"time"
78

89
"golang.org/x/exp/slices"
910
"golang.org/x/xerrors"
1011

1112
"github.com/coder/coder/v2/cli/cliui"
1213
"github.com/coder/coder/v2/codersdk"
14+
"github.com/coder/pretty"
1315
"github.com/coder/serpent"
1416
)
1517

@@ -223,17 +225,52 @@ func (r *RootCmd) listTokens() *serpent.Command {
223225
func (r *RootCmd) removeToken() *serpent.Command {
224226
client := new(codersdk.Client)
225227
cmd := &serpent.Command{
226-
Use: "remove <name>",
228+
Use: "remove <name|id|token>",
227229
Aliases: []string{"delete"},
228230
Short: "Delete a token",
229231
Middleware: serpent.Chain(
230232
serpent.RequireNArgs(1),
231233
r.InitClient(client),
232234
),
235+
Options: serpent.OptionSet{
236+
cliui.SkipPromptOption(),
237+
},
233238
Handler: func(inv *serpent.Invocation) error {
234239
token, err := client.APIKeyByName(inv.Context(), codersdk.Me, inv.Args[0])
235240
if err != nil {
236-
return xerrors.Errorf("fetch api key by name %s: %w", inv.Args[0], err)
241+
// If it's a token, we need to extract the ID
242+
maybeID := strings.Split(inv.Args[0], "-")[0]
243+
token, err = client.APIKeyByID(inv.Context(), codersdk.Me, maybeID)
244+
if err != nil {
245+
return xerrors.Errorf("fetch api key by name or id: %w", err)
246+
}
247+
}
248+
249+
var prompt string
250+
if token.TokenName == "" {
251+
prompt = fmt.Sprintf("Are you sure you want to delete the token with ID %s?\n ",
252+
pretty.Sprint(cliui.DefaultStyles.Code, token.ID),
253+
)
254+
} else {
255+
prompt = fmt.Sprintf("Are you sure you want to delete the token with the name %s? (ID: %s)\n ",
256+
pretty.Sprint(cliui.DefaultStyles.Code, token.TokenName),
257+
pretty.Sprint(cliui.DefaultStyles.Code, token.ID),
258+
)
259+
}
260+
261+
if !token.LastUsed.IsZero() {
262+
prompt = fmt.Sprintf("%sIt was last used on %s.", prompt, pretty.Sprint(cliui.DefaultStyles.Code, token.LastUsed.String()))
263+
} else {
264+
prompt = fmt.Sprintf("%sIt has never been used.", prompt)
265+
}
266+
267+
_, err = cliui.Prompt(inv, cliui.PromptOptions{
268+
Text: prompt,
269+
IsConfirm: true,
270+
Default: cliui.ConfirmYes,
271+
})
272+
if err != nil {
273+
return err
237274
}
238275

239276
err = client.DeleteAPIKey(inv.Context(), codersdk.Me, token.ID)

cli/tokens_test.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func TestTokens(t *testing.T) {
9393
require.Contains(t, res, secondTokenID)
9494

9595
// Test creating a token for third user from second user's (non-admin) session
96-
inv, root = clitest.New(t, "tokens", "create", "--name", "token-two", "--user", thirdUser.ID.String())
96+
inv, root = clitest.New(t, "tokens", "create", "--name", "failed-token", "--user", thirdUser.ID.String())
9797
clitest.SetupConfig(t, secondUserClient, root)
9898
buf = new(bytes.Buffer)
9999
inv.Stdout = buf
@@ -113,7 +113,41 @@ func TestTokens(t *testing.T) {
113113
require.Len(t, tokens, 1)
114114
require.Equal(t, id, tokens[0].ID)
115115

116-
inv, root = clitest.New(t, "tokens", "rm", "token-one")
116+
// Delete by name
117+
inv, root = clitest.New(t, "tokens", "rm", "token-one", "--yes")
118+
clitest.SetupConfig(t, client, root)
119+
buf = new(bytes.Buffer)
120+
inv.Stdout = buf
121+
err = inv.WithContext(ctx).Run()
122+
require.NoError(t, err)
123+
res = buf.String()
124+
require.NotEmpty(t, res)
125+
require.Contains(t, res, "deleted")
126+
127+
// Delete by ID
128+
inv, root = clitest.New(t, "tokens", "rm", secondTokenID, "--yes")
129+
clitest.SetupConfig(t, client, root)
130+
buf = new(bytes.Buffer)
131+
inv.Stdout = buf
132+
err = inv.WithContext(ctx).Run()
133+
require.NoError(t, err)
134+
res = buf.String()
135+
require.NotEmpty(t, res)
136+
require.Contains(t, res, "deleted")
137+
138+
// Create third token
139+
inv, root = clitest.New(t, "tokens", "create", "--name", "token-three")
140+
clitest.SetupConfig(t, client, root)
141+
buf = new(bytes.Buffer)
142+
inv.Stdout = buf
143+
err = inv.WithContext(ctx).Run()
144+
require.NoError(t, err)
145+
res = buf.String()
146+
require.NotEmpty(t, res)
147+
fourthToken := res
148+
149+
// Delete by token
150+
inv, root = clitest.New(t, "tokens", "rm", fourthToken, "--yes")
117151
clitest.SetupConfig(t, client, root)
118152
buf = new(bytes.Buffer)
119153
inv.Stdout = buf

docs/reference/cli/tokens_remove.md

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)