feat: add ability to name tokens (#6365)

* add tokens switch

* reorged TokensPage

* using Trans component for description

* using Trans component on DeleteDialog

* add owner col

* simplify hook return

* lint

* type for response

* added flag for name

* fixed auth

* lint, prettier, tests

* added unique index for login type token

* remove tokens by name

* better check for unique constraint

* docs

* test: Fix dbfake to insert token name

* fix doc tests

* Update cli/tokens.go

Co-authored-by: Steven Masley <Emyrk@users.noreply.github.com>

* Update coderd/database/migrations/000102_add_apikey_name.down.sql

Co-authored-by: Steven Masley <Emyrk@users.noreply.github.com>

* add more specificity to IsUniqueViolation check

* fix tests

* Fix AutorizeAllEndpoints

* rename migration

---------

Co-authored-by: Steven Masley <stevenmasley@coder.com>
Co-authored-by: Steven Masley <Emyrk@users.noreply.github.com>
This commit is contained in:
Kira Pilot
2023-03-02 09:39:38 -08:00
committed by GitHub
co-authored by Steven Masley Steven Masley
parent e3a4861e93
commit 71d1e63af0
37 changed files with 447 additions and 63 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ Get Started:
$ coder tokens rm WuoWs4ZsMX
Commands:
create Create a tokens
create Create a token
list List tokens
remove Delete a token
+2 -1
View File
@@ -1,4 +1,4 @@
Create a tokens
Create a token
Usage:
coder tokens create [flags]
@@ -7,6 +7,7 @@ Flags:
-h, --help help for create
--lifetime duration Specify a duration for the lifetime of the token.
Consumes $CODER_TOKEN_LIFETIME (default 720h0m0s)
-n, --name string Specify a human-readable name.
Global Flags:
--global-config coder Path to the global coder config directory.
+3 -3
View File
@@ -9,9 +9,9 @@ Aliases:
Flags:
-a, --all Specifies whether all users' tokens will be listed or not (must have
Owner role to see all tokens).
-c, --column strings Columns to display in table output. Available columns: id, last used,
expires at, created at, owner (default [id,last used,expires
at,created at])
-c, --column strings Columns to display in table output. Available columns: id, name, last
used, expires at, created at, owner (default [id,name,last
used,expires at,created at])
-h, --help help for list
-o, --output string Output format. Available formats: table, json (default "table")
+1 -1
View File
@@ -1,7 +1,7 @@
Delete a token
Usage:
coder tokens remove [id] [flags]
coder tokens remove [name] [flags]
Aliases:
remove, rm
+18 -6
View File
@@ -49,10 +49,13 @@ func tokens() *cobra.Command {
}
func createToken() *cobra.Command {
var tokenLifetime time.Duration
var (
tokenLifetime time.Duration
name string
)
cmd := &cobra.Command{
Use: "create",
Short: "Create a tokens",
Short: "Create a token",
RunE: func(cmd *cobra.Command, args []string) error {
client, err := CreateClient(cmd)
if err != nil {
@@ -60,7 +63,8 @@ func createToken() *cobra.Command {
}
res, err := client.CreateToken(cmd.Context(), codersdk.Me, codersdk.CreateTokenRequest{
Lifetime: tokenLifetime,
Lifetime: tokenLifetime,
TokenName: name,
})
if err != nil {
return xerrors.Errorf("create tokens: %w", err)
@@ -81,6 +85,7 @@ func createToken() *cobra.Command {
}
cliflag.DurationVarP(cmd.Flags(), &tokenLifetime, "lifetime", "", "CODER_TOKEN_LIFETIME", 30*24*time.Hour, "Specify a duration for the lifetime of the token.")
cmd.Flags().StringVarP(&name, "name", "n", "", "Specify a human-readable name.")
return cmd
}
@@ -92,6 +97,7 @@ type tokenListRow struct {
// For table format:
ID string `json:"-" table:"id,default_sort"`
TokenName string `json:"token_name" table:"name"`
LastUsed time.Time `json:"-" table:"last used"`
ExpiresAt time.Time `json:"-" table:"expires at"`
CreatedAt time.Time `json:"-" table:"created at"`
@@ -102,6 +108,7 @@ func tokenListRowFromToken(token codersdk.APIKeyWithOwner) tokenListRow {
return tokenListRow{
APIKey: token.APIKey,
ID: token.ID,
TokenName: token.TokenName,
LastUsed: token.LastUsed,
ExpiresAt: token.ExpiresAt,
CreatedAt: token.CreatedAt,
@@ -111,7 +118,7 @@ func tokenListRowFromToken(token codersdk.APIKeyWithOwner) tokenListRow {
func listTokens() *cobra.Command {
// we only display the 'owner' column if the --all argument is passed in
defaultCols := []string{"id", "last used", "expires at", "created at"}
defaultCols := []string{"id", "name", "last used", "expires at", "created at"}
if slices.Contains(os.Args, "-a") || slices.Contains(os.Args, "--all") {
defaultCols = append(defaultCols, "owner")
}
@@ -172,7 +179,7 @@ func listTokens() *cobra.Command {
func removeToken() *cobra.Command {
cmd := &cobra.Command{
Use: "remove [id]",
Use: "remove [name]",
Aliases: []string{"rm"},
Short: "Delete a token",
Args: cobra.ExactArgs(1),
@@ -182,7 +189,12 @@ func removeToken() *cobra.Command {
return xerrors.Errorf("create codersdk client: %w", err)
}
err = client.DeleteAPIKey(cmd.Context(), codersdk.Me, args[0])
token, err := client.APIKeyByName(cmd.Context(), codersdk.Me, args[0])
if err != nil {
return xerrors.Errorf("fetch api key by name %s: %w", args[0], err)
}
err = client.DeleteAPIKey(cmd.Context(), codersdk.Me, token.ID)
if err != nil {
return xerrors.Errorf("delete api key: %w", err)
}
+2 -2
View File
@@ -33,7 +33,7 @@ func TestTokens(t *testing.T) {
res := buf.String()
require.Contains(t, res, "tokens found")
cmd, root = clitest.New(t, "tokens", "create")
cmd, root = clitest.New(t, "tokens", "create", "--name", "token-one")
clitest.SetupConfig(t, client, root)
buf = new(bytes.Buffer)
cmd.SetOut(buf)
@@ -73,7 +73,7 @@ func TestTokens(t *testing.T) {
require.Len(t, tokens, 1)
require.Equal(t, id, tokens[0].ID)
cmd, root = clitest.New(t, "tokens", "rm", id)
cmd, root = clitest.New(t, "tokens", "rm", "token-one")
clitest.SetupConfig(t, client, root)
buf = new(bytes.Buffer)
cmd.SetOut(buf)