diff --git a/cli/testdata/coder_tokens_create_--help.golden b/cli/testdata/coder_tokens_create_--help.golden index f36d80f229783..f887c38acd00c 100644 --- a/cli/testdata/coder_tokens_create_--help.golden +++ b/cli/testdata/coder_tokens_create_--help.golden @@ -12,5 +12,9 @@ OPTIONS: -n, --name string, $CODER_TOKEN_NAME Specify a human-readable name. + -u, --user string, $CODER_TOKEN_USER + Specify the user to create the token for (Only works if logged in user + is admin). + ——— Run `coder --help` for a list of global options. diff --git a/cli/tokens.go b/cli/tokens.go index 4961ac7e3e9b5..30eda97e17623 100644 --- a/cli/tokens.go +++ b/cli/tokens.go @@ -48,6 +48,7 @@ func (r *RootCmd) createToken() *serpent.Command { var ( tokenLifetime time.Duration name string + user string ) client := new(codersdk.Client) cmd := &serpent.Command{ @@ -58,7 +59,11 @@ func (r *RootCmd) createToken() *serpent.Command { r.InitClient(client), ), Handler: func(inv *serpent.Invocation) error { - res, err := client.CreateToken(inv.Context(), codersdk.Me, codersdk.CreateTokenRequest{ + userID := codersdk.Me + if user != "" { + userID = user + } + res, err := client.CreateToken(inv.Context(), userID, codersdk.CreateTokenRequest{ Lifetime: tokenLifetime, TokenName: name, }) @@ -87,6 +92,13 @@ func (r *RootCmd) createToken() *serpent.Command { Description: "Specify a human-readable name.", Value: serpent.StringOf(&name), }, + { + Flag: "user", + FlagShorthand: "u", + Env: "CODER_TOKEN_USER", + Description: "Specify the user to create the token for (Only works if logged in user is admin).", + Value: serpent.StringOf(&user), + }, } return cmd diff --git a/cli/tokens_test.go b/cli/tokens_test.go index fdb062b959a3b..7c024f3ad1a6f 100644 --- a/cli/tokens_test.go +++ b/cli/tokens_test.go @@ -17,13 +17,17 @@ import ( func TestTokens(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) - _ = coderdtest.CreateFirstUser(t, client) + adminUser := coderdtest.CreateFirstUser(t, client) + + secondUserClient, secondUser := coderdtest.CreateAnotherUser(t, client, adminUser.OrganizationID) + _, thirdUser := coderdtest.CreateAnotherUser(t, client, adminUser.OrganizationID) ctx, cancelFunc := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancelFunc() // helpful empty response inv, root := clitest.New(t, "tokens", "ls") + //nolint:gocritic // This should be run as the owner user. clitest.SetupConfig(t, client, root) buf := new(bytes.Buffer) inv.Stdout = buf @@ -42,6 +46,19 @@ func TestTokens(t *testing.T) { require.NotEmpty(t, res) id := res[:10] + // Test creating a token for second user from first user's (admin) session + inv, root = clitest.New(t, "tokens", "create", "--name", "token-two", "--user", secondUser.ID.String()) + clitest.SetupConfig(t, client, root) + buf = new(bytes.Buffer) + inv.Stdout = buf + err = inv.WithContext(ctx).Run() + // Test should succeed in creating token for second user + require.NoError(t, err) + res = buf.String() + require.NotEmpty(t, res) + secondTokenID := res[:10] + + // Test listing tokens from the first user's (admin) session inv, root = clitest.New(t, "tokens", "ls") clitest.SetupConfig(t, client, root) buf = new(bytes.Buffer) @@ -50,11 +67,39 @@ func TestTokens(t *testing.T) { require.NoError(t, err) res = buf.String() require.NotEmpty(t, res) + // Result should only contain the token created for the admin user require.Contains(t, res, "ID") require.Contains(t, res, "EXPIRES AT") require.Contains(t, res, "CREATED AT") require.Contains(t, res, "LAST USED") require.Contains(t, res, id) + // Result should not contain the token created for the second user + require.NotContains(t, res, secondTokenID) + + // Test listing tokens from the second user's session + inv, root = clitest.New(t, "tokens", "ls") + clitest.SetupConfig(t, secondUserClient, 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, "ID") + require.Contains(t, res, "EXPIRES AT") + require.Contains(t, res, "CREATED AT") + require.Contains(t, res, "LAST USED") + // Result should contain the token created for the second user + 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()) + clitest.SetupConfig(t, secondUserClient, root) + buf = new(bytes.Buffer) + inv.Stdout = buf + err = inv.WithContext(ctx).Run() + // User (non-admin) should not be able to create a token for another user + require.Error(t, err) inv, root = clitest.New(t, "tokens", "ls", "--output=json") clitest.SetupConfig(t, client, root) diff --git a/docs/reference/cli/tokens_create.md b/docs/reference/cli/tokens_create.md index e6b613fa0090a..09a4a5d200ea5 100644 --- a/docs/reference/cli/tokens_create.md +++ b/docs/reference/cli/tokens_create.md @@ -30,3 +30,12 @@ Specify a duration for the lifetime of the token. | Environment | $CODER_TOKEN_NAME | Specify a human-readable name. + +### -u, --user + +| | | +| ----------- | ------------------------------ | +| Type | string | +| Environment | $CODER_TOKEN_USER | + +Specify the user to create the token for (Only works if logged in user is admin). 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