From 294916478c735cb33ddf777e6104af45fc8506b9 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Thu, 30 Jan 2025 07:55:52 +0000 Subject: [PATCH 1/2] chore(cli): support deleting tokens by id --- .../coder_tokens_remove_--help.golden | 6 ++- cli/tokens.go | 41 ++++++++++++++++++- cli/tokens_test.go | 38 ++++++++++++++++- docs/reference/cli/tokens_remove.md | 12 +++++- 4 files changed, 91 insertions(+), 6 deletions(-) diff --git a/cli/testdata/coder_tokens_remove_--help.golden b/cli/testdata/coder_tokens_remove_--help.golden index 30440e8ef2e7c..81c9a405db0cf 100644 --- a/cli/testdata/coder_tokens_remove_--help.golden +++ b/cli/testdata/coder_tokens_remove_--help.golden @@ -1,11 +1,15 @@ coder v0.0.0-devel USAGE: - coder tokens remove + coder tokens remove [flags] Delete a token Aliases: delete, rm +OPTIONS: + -y, --yes bool + Bypass prompts. + ——— Run `coder --help` for a list of global options. diff --git a/cli/tokens.go b/cli/tokens.go index 2488a687a0c07..88e3cd2585e2a 100644 --- a/cli/tokens.go +++ b/cli/tokens.go @@ -3,6 +3,7 @@ package cli import ( "fmt" "os" + "strings" "time" "golang.org/x/exp/slices" @@ -10,6 +11,7 @@ import ( "github.com/coder/coder/v2/cli/cliui" "github.com/coder/coder/v2/codersdk" + "github.com/coder/pretty" "github.com/coder/serpent" ) @@ -223,17 +225,52 @@ func (r *RootCmd) listTokens() *serpent.Command { func (r *RootCmd) removeToken() *serpent.Command { client := new(codersdk.Client) cmd := &serpent.Command{ - Use: "remove ", + Use: "remove ", Aliases: []string{"delete"}, Short: "Delete a token", Middleware: serpent.Chain( serpent.RequireNArgs(1), r.InitClient(client), ), + Options: serpent.OptionSet{ + cliui.SkipPromptOption(), + }, Handler: func(inv *serpent.Invocation) error { token, err := client.APIKeyByName(inv.Context(), codersdk.Me, inv.Args[0]) if err != nil { - return xerrors.Errorf("fetch api key by name %s: %w", inv.Args[0], err) + // If it's a token, we need to extract the ID + maybeID := strings.Split(inv.Args[0], "-")[0] + token, err = client.APIKeyByID(inv.Context(), codersdk.Me, maybeID) + if err != nil { + return xerrors.Errorf("fetch api key by name or id: %w", err) + } + } + + var prompt string + if token.TokenName == "" { + prompt = fmt.Sprintf("Are you sure you want to delete the token with ID %s?\n ", + pretty.Sprint(cliui.DefaultStyles.Code, token.ID), + ) + } else { + prompt = fmt.Sprintf("Are you sure you want to delete the token with the name %s? (ID: %s)\n ", + pretty.Sprint(cliui.DefaultStyles.Code, token.TokenName), + pretty.Sprint(cliui.DefaultStyles.Code, token.ID), + ) + } + + if !token.LastUsed.IsZero() { + prompt = fmt.Sprintf("%sIt was last used on %s.", prompt, pretty.Sprint(cliui.DefaultStyles.Code, token.LastUsed.String())) + } else { + prompt = fmt.Sprintf("%sIt has never been used.", prompt) + } + + _, err = cliui.Prompt(inv, cliui.PromptOptions{ + Text: prompt, + IsConfirm: true, + Default: cliui.ConfirmYes, + }) + if err != nil { + return err } err = client.DeleteAPIKey(inv.Context(), codersdk.Me, token.ID) diff --git a/cli/tokens_test.go b/cli/tokens_test.go index 7c024f3ad1a6f..01eb66ad54075 100644 --- a/cli/tokens_test.go +++ b/cli/tokens_test.go @@ -93,7 +93,7 @@ func TestTokens(t *testing.T) { require.Contains(t, res, secondTokenID) // Test creating a token for third user from second user's (non-admin) session - inv, root = clitest.New(t, "tokens", "create", "--name", "token-two", "--user", thirdUser.ID.String()) + inv, root = clitest.New(t, "tokens", "create", "--name", "failed-token", "--user", thirdUser.ID.String()) clitest.SetupConfig(t, secondUserClient, root) buf = new(bytes.Buffer) inv.Stdout = buf @@ -113,7 +113,41 @@ func TestTokens(t *testing.T) { require.Len(t, tokens, 1) require.Equal(t, id, tokens[0].ID) - inv, root = clitest.New(t, "tokens", "rm", "token-one") + // Delete by name + inv, root = clitest.New(t, "tokens", "rm", "token-one", "--yes") + clitest.SetupConfig(t, client, root) + buf = new(bytes.Buffer) + inv.Stdout = buf + err = inv.WithContext(ctx).Run() + require.NoError(t, err) + res = buf.String() + require.NotEmpty(t, res) + require.Contains(t, res, "deleted") + + // Delete by ID + inv, root = clitest.New(t, "tokens", "rm", secondTokenID, "--yes") + clitest.SetupConfig(t, client, root) + buf = new(bytes.Buffer) + inv.Stdout = buf + err = inv.WithContext(ctx).Run() + require.NoError(t, err) + res = buf.String() + require.NotEmpty(t, res) + require.Contains(t, res, "deleted") + + // Create third token + inv, root = clitest.New(t, "tokens", "create", "--name", "token-three") + clitest.SetupConfig(t, client, root) + buf = new(bytes.Buffer) + inv.Stdout = buf + err = inv.WithContext(ctx).Run() + require.NoError(t, err) + res = buf.String() + require.NotEmpty(t, res) + fourthToken := res + + // Delete by token + inv, root = clitest.New(t, "tokens", "rm", fourthToken, "--yes") clitest.SetupConfig(t, client, root) buf = new(bytes.Buffer) inv.Stdout = buf diff --git a/docs/reference/cli/tokens_remove.md b/docs/reference/cli/tokens_remove.md index 8825040f5e3a7..e127ae4dbc309 100644 --- a/docs/reference/cli/tokens_remove.md +++ b/docs/reference/cli/tokens_remove.md @@ -11,5 +11,15 @@ Aliases: ## Usage ```console -coder tokens remove +coder tokens remove [flags] ``` + +## Options + +### -y, --yes + +| | | +|------|-------------------| +| Type | bool | + +Bypass prompts. From ec8ff1a61f52283018e77b133721a658873c2f28 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Mon, 3 Feb 2025 07:04:47 +0000 Subject: [PATCH 2/2] remove prompt --- .../coder_tokens_remove_--help.golden | 6 +--- cli/tokens.go | 31 ------------------- cli/tokens_test.go | 6 ++-- docs/reference/cli/tokens_remove.md | 12 +------ 4 files changed, 5 insertions(+), 50 deletions(-) diff --git a/cli/testdata/coder_tokens_remove_--help.golden b/cli/testdata/coder_tokens_remove_--help.golden index 81c9a405db0cf..63caab0c7e09f 100644 --- a/cli/testdata/coder_tokens_remove_--help.golden +++ b/cli/testdata/coder_tokens_remove_--help.golden @@ -1,15 +1,11 @@ coder v0.0.0-devel USAGE: - coder tokens remove [flags] + coder tokens remove Delete a token Aliases: delete, rm -OPTIONS: - -y, --yes bool - Bypass prompts. - ——— Run `coder --help` for a list of global options. diff --git a/cli/tokens.go b/cli/tokens.go index 88e3cd2585e2a..d132547576d32 100644 --- a/cli/tokens.go +++ b/cli/tokens.go @@ -11,7 +11,6 @@ import ( "github.com/coder/coder/v2/cli/cliui" "github.com/coder/coder/v2/codersdk" - "github.com/coder/pretty" "github.com/coder/serpent" ) @@ -232,9 +231,6 @@ func (r *RootCmd) removeToken() *serpent.Command { serpent.RequireNArgs(1), r.InitClient(client), ), - Options: serpent.OptionSet{ - cliui.SkipPromptOption(), - }, Handler: func(inv *serpent.Invocation) error { token, err := client.APIKeyByName(inv.Context(), codersdk.Me, inv.Args[0]) if err != nil { @@ -246,33 +242,6 @@ func (r *RootCmd) removeToken() *serpent.Command { } } - var prompt string - if token.TokenName == "" { - prompt = fmt.Sprintf("Are you sure you want to delete the token with ID %s?\n ", - pretty.Sprint(cliui.DefaultStyles.Code, token.ID), - ) - } else { - prompt = fmt.Sprintf("Are you sure you want to delete the token with the name %s? (ID: %s)\n ", - pretty.Sprint(cliui.DefaultStyles.Code, token.TokenName), - pretty.Sprint(cliui.DefaultStyles.Code, token.ID), - ) - } - - if !token.LastUsed.IsZero() { - prompt = fmt.Sprintf("%sIt was last used on %s.", prompt, pretty.Sprint(cliui.DefaultStyles.Code, token.LastUsed.String())) - } else { - prompt = fmt.Sprintf("%sIt has never been used.", prompt) - } - - _, err = cliui.Prompt(inv, cliui.PromptOptions{ - Text: prompt, - IsConfirm: true, - Default: cliui.ConfirmYes, - }) - if err != nil { - return err - } - err = client.DeleteAPIKey(inv.Context(), codersdk.Me, token.ID) if err != nil { return xerrors.Errorf("delete api key: %w", err) diff --git a/cli/tokens_test.go b/cli/tokens_test.go index 01eb66ad54075..0c717bb890f9e 100644 --- a/cli/tokens_test.go +++ b/cli/tokens_test.go @@ -114,7 +114,7 @@ func TestTokens(t *testing.T) { require.Equal(t, id, tokens[0].ID) // Delete by name - inv, root = clitest.New(t, "tokens", "rm", "token-one", "--yes") + inv, root = clitest.New(t, "tokens", "rm", "token-one") clitest.SetupConfig(t, client, root) buf = new(bytes.Buffer) inv.Stdout = buf @@ -125,7 +125,7 @@ func TestTokens(t *testing.T) { require.Contains(t, res, "deleted") // Delete by ID - inv, root = clitest.New(t, "tokens", "rm", secondTokenID, "--yes") + inv, root = clitest.New(t, "tokens", "rm", secondTokenID) clitest.SetupConfig(t, client, root) buf = new(bytes.Buffer) inv.Stdout = buf @@ -147,7 +147,7 @@ func TestTokens(t *testing.T) { fourthToken := res // Delete by token - inv, root = clitest.New(t, "tokens", "rm", fourthToken, "--yes") + inv, root = clitest.New(t, "tokens", "rm", fourthToken) clitest.SetupConfig(t, client, root) buf = new(bytes.Buffer) inv.Stdout = buf diff --git a/docs/reference/cli/tokens_remove.md b/docs/reference/cli/tokens_remove.md index e127ae4dbc309..ae443f6ad083e 100644 --- a/docs/reference/cli/tokens_remove.md +++ b/docs/reference/cli/tokens_remove.md @@ -11,15 +11,5 @@ Aliases: ## Usage ```console -coder tokens remove [flags] +coder tokens remove ``` - -## Options - -### -y, --yes - -| | | -|------|-------------------| -| Type | bool | - -Bypass prompts. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy