From 1bed8c83e41dce2bcd21e2684f276f592e9bf1a1 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 13 May 2022 09:57:49 -0500 Subject: [PATCH 01/15] feat: Add suspend/active user to cli --- cli/userlist.go | 21 +--------- cli/users.go | 35 +++++++++++++++- cli/userstatus.go | 90 ++++++++++++++++++++++++++++++++++++++++++ cli/userstatus_test.go | 63 +++++++++++++++++++++++++++++ coderd/coderd.go | 5 ++- coderd/users.go | 51 ++++++++++++++---------- coderd/users_test.go | 8 ++-- codersdk/users.go | 24 ++++++++--- 8 files changed, 244 insertions(+), 53 deletions(-) create mode 100644 cli/userstatus.go create mode 100644 cli/userstatus_test.go diff --git a/cli/userlist.go b/cli/userlist.go index 108c22cc0fca7..783593c45e05f 100644 --- a/cli/userlist.go +++ b/cli/userlist.go @@ -2,12 +2,9 @@ package cli import ( "fmt" - "time" - "github.com/jedib0t/go-pretty/v6/table" "github.com/spf13/cobra" - "github.com/coder/coder/cli/cliui" "github.com/coder/coder/codersdk" ) @@ -28,25 +25,11 @@ func userList() *cobra.Command { return err } - tableWriter := cliui.Table() - header := table.Row{"Username", "Email", "Created At"} - tableWriter.AppendHeader(header) - tableWriter.SetColumnConfigs(cliui.FilterTableColumns(header, columns)) - tableWriter.SortBy([]table.SortBy{{ - Name: "Username", - }}) - for _, user := range users { - tableWriter.AppendRow(table.Row{ - user.Username, - user.Email, - user.CreatedAt.Format(time.Stamp), - }) - } - _, err = fmt.Fprintln(cmd.OutOrStdout(), tableWriter.Render()) + _, err = fmt.Fprintln(cmd.OutOrStdout(), DisplayUsers(columns, users...)) return err }, } - cmd.Flags().StringArrayVarP(&columns, "column", "c", nil, + cmd.Flags().StringArrayVarP(&columns, "column", "c", []string{"Username", "Email", "Created At"}, "Specify a column to filter in the table.") return cmd } diff --git a/cli/users.go b/cli/users.go index dcc03c8ddfa02..10ca47c6e0882 100644 --- a/cli/users.go +++ b/cli/users.go @@ -1,12 +1,43 @@ package cli -import "github.com/spf13/cobra" +import ( + "time" + + "github.com/coder/coder/cli/cliui" + "github.com/coder/coder/codersdk" + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" +) func users() *cobra.Command { cmd := &cobra.Command{ Short: "Create, remove, and list users", Use: "users", } - cmd.AddCommand(userCreate(), userList()) + cmd.AddCommand( + userCreate(), + userList(), + userStatus(), + ) return cmd } + +func DisplayUsers(filterColumns []string, users ...codersdk.User) string { + tableWriter := cliui.Table() + header := table.Row{"ID", "Username", "Email", "Created At", "Status"} + tableWriter.AppendHeader(header) + tableWriter.SetColumnConfigs(cliui.FilterTableColumns(header, filterColumns)) + tableWriter.SortBy([]table.SortBy{{ + Name: "Username", + }}) + for _, user := range users { + tableWriter.AppendRow(table.Row{ + user.ID.String(), + user.Username, + user.Email, + user.CreatedAt.Format(time.Stamp), + user.Status, + }) + } + return tableWriter.Render() +} diff --git a/cli/userstatus.go b/cli/userstatus.go new file mode 100644 index 0000000000000..565905bfedfb2 --- /dev/null +++ b/cli/userstatus.go @@ -0,0 +1,90 @@ +package cli + +import ( + "fmt" + + "github.com/coder/coder/codersdk" + + "github.com/coder/coder/cli/cliui" + "github.com/spf13/cobra" + "golang.org/x/xerrors" +) + +func userStatus() *cobra.Command { + cmd := &cobra.Command{ + Use: "status", + Short: "Update the status of a user", + } + cmd.AddCommand( + setUserStatus(codersdk.UserStatusActive), + setUserStatus(codersdk.UserStatusSuspended), + ) + return cmd +} + +// setUserStatus sets a user status. +func setUserStatus(sdkStatus codersdk.UserStatus) *cobra.Command { + var verb string + switch sdkStatus { + case codersdk.UserStatusActive: + verb = "active" + case codersdk.UserStatusSuspended: + verb = "suspend" + default: + panic(fmt.Sprintf("%s is not supported", sdkStatus)) + } + + var ( + columns []string + ) + cmd := &cobra.Command{ + Use: fmt.Sprintf("%s ", verb), + Short: fmt.Sprintf("Update a user's status to %q", sdkStatus), + Args: cobra.ExactArgs(1), + Example: fmt.Sprintf("coder status %s example_user", verb), + RunE: func(cmd *cobra.Command, args []string) error { + client, err := createClient(cmd) + if err != nil { + return err + } + + identifier := args[0] + if identifier == "" { + return xerrors.Errorf("user identifier cannot be an empty string") + } + + user, err := client.UserByIdentifier(cmd.Context(), identifier) + if err != nil { + return xerrors.Errorf("fetch user: %w", err) + } + + // Display the user + _, _ = fmt.Fprintln(cmd.OutOrStdout(), DisplayUsers(columns, user)) + + // User status is already set to this + if user.Status == sdkStatus { + _, _ = fmt.Fprintf(cmd.OutOrStdout(), "User status is already %q\n", sdkStatus) + return nil + } + + // Prompt to confirm the action + _, err = cliui.Prompt(cmd, cliui.PromptOptions{ + Text: fmt.Sprintf("Are you sure you want to %s this user?", verb), + IsConfirm: true, + Default: "yes", + }) + if err != nil { + return err + } + + _, err = client.SetUserStatus(cmd.Context(), user.ID, sdkStatus) + if err != nil { + return xerrors.Errorf("%s user: %w", verb, err) + } + return nil + }, + } + cmd.Flags().StringArrayVarP(&columns, "column", "c", []string{"Username", "Email", "Created At", "Status"}, + "Specify a column to filter in the table.") + return cmd +} diff --git a/cli/userstatus_test.go b/cli/userstatus_test.go new file mode 100644 index 0000000000000..750f5e7b81c7a --- /dev/null +++ b/cli/userstatus_test.go @@ -0,0 +1,63 @@ +package cli_test + +import ( + "bytes" + "context" + "testing" + + "github.com/coder/coder/codersdk" + + "github.com/stretchr/testify/require" + + "github.com/coder/coder/cli/clitest" + "github.com/coder/coder/coderd/coderdtest" +) + +func TestUserStatus(t *testing.T) { + t.Parallel() + client := coderdtest.New(t, nil) + admin := coderdtest.CreateFirstUser(t, client) + other := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID) + otherUser, err := other.User(context.Background(), codersdk.Me) + require.NoError(t, err, "fetch user") + + t.Run("StatusSelf", func(t *testing.T) { + cmd, root := clitest.New(t, "users", "status", "suspend", "me") + clitest.SetupConfig(t, client, root) + // Yes to the prompt + cmd.SetIn(bytes.NewReader([]byte("yes\n"))) + err := cmd.Execute() + // Expect an error, as you cannot suspend yourself + require.Error(t, err) + require.ErrorContains(t, err, "cannot suspend yourself") + }) + + t.Run("StatusOther", func(t *testing.T) { + require.Equal(t, otherUser.Status, codersdk.UserStatusActive, "start as active") + + cmd, root := clitest.New(t, "users", "status", "suspend", otherUser.Username) + clitest.SetupConfig(t, client, root) + // Yes to the prompt + cmd.SetIn(bytes.NewReader([]byte("yes\n"))) + err := cmd.Execute() + require.NoError(t, err, "suspend user") + + // Check the user status + otherUser, err = client.User(context.Background(), otherUser.ID) + require.NoError(t, err, "fetch suspended user") + require.Equal(t, otherUser.Status, codersdk.UserStatusSuspended, "suspended user") + + // Set back to active + cmd, root = clitest.New(t, "users", "status", "active", otherUser.Username) + clitest.SetupConfig(t, client, root) + // Yes to the prompt + cmd.SetIn(bytes.NewReader([]byte("yes\n"))) + err = cmd.Execute() + require.NoError(t, err, "suspend user") + + // Check the user status + otherUser, err = client.User(context.Background(), otherUser.ID) + require.NoError(t, err, "fetch active user") + require.Equal(t, otherUser.Status, codersdk.UserStatusActive, "active user") + }) +} diff --git a/coderd/coderd.go b/coderd/coderd.go index 4d394cb9362ae..4f717ba3f58f5 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -239,7 +239,10 @@ func New(options *Options) (http.Handler, func()) { r.Use(httpmw.ExtractUserParam(options.Database)) r.Get("/", api.userByName) r.Put("/profile", api.putUserProfile) - r.Put("/suspend", api.putUserSuspend) + r.Route("/status", func(r chi.Router) { + r.Put("/suspend", api.putUserStatus(database.UserStatusSuspended)) + r.Put("/active", api.putUserStatus(database.UserStatusActive)) + }) r.Route("/password", func(r chi.Router) { r.Use(httpmw.WithRBACObject(rbac.ResourceUserPasswordRole)) r.Put("/", authorize(api.putUserPassword, rbac.ActionUpdate)) diff --git a/coderd/users.go b/coderd/users.go index f6dc26ccb51fe..c5eda83342dbc 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -303,31 +303,40 @@ func (api *api) putUserProfile(rw http.ResponseWriter, r *http.Request) { httpapi.Write(rw, http.StatusOK, convertUser(updatedUserProfile, organizationIDs)) } -func (api *api) putUserSuspend(rw http.ResponseWriter, r *http.Request) { - user := httpmw.UserParam(r) - - suspendedUser, err := api.Database.UpdateUserStatus(r.Context(), database.UpdateUserStatusParams{ - ID: user.ID, - Status: database.UserStatusSuspended, - UpdatedAt: database.Now(), - }) +func (api *api) putUserStatus(status database.UserStatus) func(rw http.ResponseWriter, r *http.Request) { + return func(rw http.ResponseWriter, r *http.Request) { + user := httpmw.UserParam(r) + apiKey := httpmw.APIKey(r) + if status == database.UserStatusSuspended && user.ID == apiKey.UserID { + httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ + Message: fmt.Sprintf("You cannot suspend yourself"), + }) + return + } - if err != nil { - httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ - Message: fmt.Sprintf("put user suspended: %s", err.Error()), + suspendedUser, err := api.Database.UpdateUserStatus(r.Context(), database.UpdateUserStatusParams{ + ID: user.ID, + Status: status, + UpdatedAt: database.Now(), }) - return - } - organizations, err := userOrganizationIDs(r.Context(), api, user) - if err != nil { - httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ - Message: fmt.Sprintf("get organization IDs: %s", err.Error()), - }) - return - } + if err != nil { + httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ + Message: fmt.Sprintf("put user suspended: %s", err.Error()), + }) + return + } - httpapi.Write(rw, http.StatusOK, convertUser(suspendedUser, organizations)) + organizations, err := userOrganizationIDs(r.Context(), api, user) + if err != nil { + httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ + Message: fmt.Sprintf("get organization IDs: %s", err.Error()), + }) + return + } + + httpapi.Write(rw, http.StatusOK, convertUser(suspendedUser, organizations)) + } } func (api *api) putUserPassword(rw http.ResponseWriter, r *http.Request) { diff --git a/coderd/users_test.go b/coderd/users_test.go index 99d1849ca6cf8..d513f03db6e3f 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -452,7 +452,7 @@ func TestPutUserSuspend(t *testing.T) { Password: "password", OrganizationID: me.OrganizationID, }) - user, err := client.SuspendUser(context.Background(), user.ID) + user, err := client.SetUserStatus(context.Background(), user.ID, codersdk.UserStatusSuspended) require.NoError(t, err) require.Equal(t, user.Status, codersdk.UserStatusSuspended) }) @@ -462,7 +462,7 @@ func TestPutUserSuspend(t *testing.T) { client := coderdtest.New(t, nil) coderdtest.CreateFirstUser(t, client) client.User(context.Background(), codersdk.Me) - suspendedUser, err := client.SuspendUser(context.Background(), codersdk.Me) + suspendedUser, err := client.SetUserStatus(context.Background(), codersdk.Me, codersdk.UserStatusSuspended) require.NoError(t, err) require.Equal(t, suspendedUser.Status, codersdk.UserStatusSuspended) @@ -504,7 +504,7 @@ func TestGetUser(t *testing.T) { exp, err := client.User(context.Background(), firstUser.UserID) require.NoError(t, err) - user, err := client.UserByUsername(context.Background(), exp.Username) + user, err := client.UserByIdentifier(context.Background(), exp.Username) require.NoError(t, err) require.Equal(t, exp, user) }) @@ -551,7 +551,7 @@ func TestGetUsers(t *testing.T) { require.NoError(t, err) active = append(active, bruno) - _, err = client.SuspendUser(context.Background(), first.UserID) + _, err = client.SetUserStatus(context.Background(), first.UserID, codersdk.UserStatusSuspended) require.NoError(t, err) users, err := client.Users(context.Background(), codersdk.UsersRequest{ diff --git a/codersdk/users.go b/codersdk/users.go index 63f8683ebdded..d84bd5187f6bd 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -7,6 +7,8 @@ import ( "net/http" "time" + "golang.org/x/xerrors" + "github.com/google/uuid" ) @@ -211,9 +213,19 @@ func (c *Client) UpdateUserProfile(ctx context.Context, userID uuid.UUID, req Up return user, json.NewDecoder(res.Body).Decode(&user) } -// SuspendUser enables callers to suspend a user -func (c *Client) SuspendUser(ctx context.Context, userID uuid.UUID) (User, error) { - res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/suspend", uuidOrMe(userID)), nil) +// SetUserStatus sets the user status to the given status +func (c *Client) SetUserStatus(ctx context.Context, userID uuid.UUID, status UserStatus) (User, error) { + path := fmt.Sprintf("/api/v2/users/%s/status/", uuidOrMe(userID)) + switch status { + case UserStatusActive: + path += "active" + case UserStatusSuspended: + path += "suspend" + default: + return User{}, xerrors.Errorf("status %q is not supported", status) + } + + res, err := c.request(ctx, http.MethodPut, path, nil) if err != nil { return User{}, err } @@ -336,8 +348,8 @@ func (c *Client) User(ctx context.Context, id uuid.UUID) (User, error) { return c.userByIdentifier(ctx, uuidOrMe(id)) } -// UserByUsername returns a user for the username provided. -func (c *Client) UserByUsername(ctx context.Context, username string) (User, error) { +// UserByIdentifier returns a user for the username or uuid provided. +func (c *Client) UserByIdentifier(ctx context.Context, username string) (User, error) { return c.userByIdentifier(ctx, username) } @@ -347,7 +359,7 @@ func (c *Client) userByIdentifier(ctx context.Context, ident string) (User, erro return User{}, err } defer res.Body.Close() - if res.StatusCode > http.StatusOK { + if res.StatusCode != http.StatusOK { return User{}, readBodyAsError(res) } var user User From ddf257127d9b991635384bf242f7ca5ae284e9bb Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 13 May 2022 09:59:40 -0500 Subject: [PATCH 02/15] Add aliases --- cli/userstatus.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/userstatus.go b/cli/userstatus.go index 565905bfedfb2..66cf17a1f4fd3 100644 --- a/cli/userstatus.go +++ b/cli/userstatus.go @@ -25,11 +25,14 @@ func userStatus() *cobra.Command { // setUserStatus sets a user status. func setUserStatus(sdkStatus codersdk.UserStatus) *cobra.Command { var verb string + var aliases []string switch sdkStatus { case codersdk.UserStatusActive: verb = "active" + aliases = []string{"activate"} case codersdk.UserStatusSuspended: verb = "suspend" + aliases = []string{"rm", "delete"} default: panic(fmt.Sprintf("%s is not supported", sdkStatus)) } @@ -41,7 +44,8 @@ func setUserStatus(sdkStatus codersdk.UserStatus) *cobra.Command { Use: fmt.Sprintf("%s ", verb), Short: fmt.Sprintf("Update a user's status to %q", sdkStatus), Args: cobra.ExactArgs(1), - Example: fmt.Sprintf("coder status %s example_user", verb), + Aliases: aliases, + Example: fmt.Sprintf("coder users status %s example_user", verb), RunE: func(cmd *cobra.Command, args []string) error { client, err := createClient(cmd) if err != nil { From 77f489010ccf00bf5b396551546b7f12a979f720 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 13 May 2022 10:01:58 -0500 Subject: [PATCH 03/15] Add comment to displayUsers --- cli/users.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/users.go b/cli/users.go index 10ca47c6e0882..9b8d59198b792 100644 --- a/cli/users.go +++ b/cli/users.go @@ -22,6 +22,9 @@ func users() *cobra.Command { return cmd } +// DisplayUsers will return a table displaying all users passed in. +// filterColumns must be a subset of the user fields and will determine which +// columns to display func DisplayUsers(filterColumns []string, users ...codersdk.User) string { tableWriter := cliui.Table() header := table.Row{"ID", "Username", "Email", "Created At", "Status"} From f57008c7b4ae9af5524fa281509ab693d21907bf Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 13 May 2022 10:03:46 -0500 Subject: [PATCH 04/15] Add comment to displayUsers --- cli/userlist.go | 2 +- cli/users.go | 4 ++-- cli/userstatus.go | 2 +- cli/userstatus_test.go | 3 +-- codersdk/users.go | 3 +-- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/cli/userlist.go b/cli/userlist.go index 783593c45e05f..debbec3aa48a3 100644 --- a/cli/userlist.go +++ b/cli/userlist.go @@ -25,7 +25,7 @@ func userList() *cobra.Command { return err } - _, err = fmt.Fprintln(cmd.OutOrStdout(), DisplayUsers(columns, users...)) + _, err = fmt.Fprintln(cmd.OutOrStdout(), displayUsers(columns, users...)) return err }, } diff --git a/cli/users.go b/cli/users.go index 9b8d59198b792..dcdce690fa3d7 100644 --- a/cli/users.go +++ b/cli/users.go @@ -22,10 +22,10 @@ func users() *cobra.Command { return cmd } -// DisplayUsers will return a table displaying all users passed in. +// displayUsers will return a table displaying all users passed in. // filterColumns must be a subset of the user fields and will determine which // columns to display -func DisplayUsers(filterColumns []string, users ...codersdk.User) string { +func displayUsers(filterColumns []string, users ...codersdk.User) string { tableWriter := cliui.Table() header := table.Row{"ID", "Username", "Email", "Created At", "Status"} tableWriter.AppendHeader(header) diff --git a/cli/userstatus.go b/cli/userstatus.go index 66cf17a1f4fd3..fd40f3548077c 100644 --- a/cli/userstatus.go +++ b/cli/userstatus.go @@ -63,7 +63,7 @@ func setUserStatus(sdkStatus codersdk.UserStatus) *cobra.Command { } // Display the user - _, _ = fmt.Fprintln(cmd.OutOrStdout(), DisplayUsers(columns, user)) + _, _ = fmt.Fprintln(cmd.OutOrStdout(), displayUsers(columns, user)) // User status is already set to this if user.Status == sdkStatus { diff --git a/cli/userstatus_test.go b/cli/userstatus_test.go index 750f5e7b81c7a..7ce0727a75711 100644 --- a/cli/userstatus_test.go +++ b/cli/userstatus_test.go @@ -5,12 +5,11 @@ import ( "context" "testing" - "github.com/coder/coder/codersdk" - "github.com/stretchr/testify/require" "github.com/coder/coder/cli/clitest" "github.com/coder/coder/coderd/coderdtest" + "github.com/coder/coder/codersdk" ) func TestUserStatus(t *testing.T) { diff --git a/codersdk/users.go b/codersdk/users.go index d84bd5187f6bd..3a226c67c68ab 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -7,9 +7,8 @@ import ( "net/http" "time" - "golang.org/x/xerrors" - "github.com/google/uuid" + "golang.org/x/xerrors" ) // Me is used as a replacement for your own ID. From 6989e13840ed82209f12b12258b1f2af2f97c8b8 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 13 May 2022 10:04:32 -0500 Subject: [PATCH 05/15] Import order --- cli/userstatus.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/userstatus.go b/cli/userstatus.go index fd40f3548077c..6970b956447ff 100644 --- a/cli/userstatus.go +++ b/cli/userstatus.go @@ -3,11 +3,11 @@ package cli import ( "fmt" - "github.com/coder/coder/codersdk" - - "github.com/coder/coder/cli/cliui" "github.com/spf13/cobra" "golang.org/x/xerrors" + + "github.com/coder/coder/cli/cliui" + "github.com/coder/coder/codersdk" ) func userStatus() *cobra.Command { From 23a8191e54b6f16f38c59f2c77c62c7b01e84add Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 13 May 2022 10:26:44 -0500 Subject: [PATCH 06/15] Fix unit test --- coderd/users_test.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/coderd/users_test.go b/coderd/users_test.go index d513f03db6e3f..2950c42286108 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -530,9 +530,15 @@ func TestGetUsers(t *testing.T) { }) t.Run("ActiveUsers", func(t *testing.T) { t.Parallel() + active := make([]codersdk.User, 0) client := coderdtest.New(t, nil) first := coderdtest.CreateFirstUser(t, client) - active := make([]codersdk.User, 0) + + firstUser, err := client.User(context.Background(), first.UserID) + require.NoError(t, err, "") + active = append(active, firstUser) + + // Alice will be suspended alice, err := client.CreateUser(context.Background(), codersdk.CreateUserRequest{ Email: "alice@email.com", Username: "alice", @@ -540,7 +546,6 @@ func TestGetUsers(t *testing.T) { OrganizationID: first.OrganizationID, }) require.NoError(t, err) - active = append(active, alice) bruno, err := client.CreateUser(context.Background(), codersdk.CreateUserRequest{ Email: "bruno@email.com", @@ -551,7 +556,7 @@ func TestGetUsers(t *testing.T) { require.NoError(t, err) active = append(active, bruno) - _, err = client.SetUserStatus(context.Background(), first.UserID, codersdk.UserStatusSuspended) + _, err = client.SetUserStatus(context.Background(), alice.ID, codersdk.UserStatusSuspended) require.NoError(t, err) users, err := client.Users(context.Background(), codersdk.UsersRequest{ From 02968cb3167fbeda51590d86f04563334d10e665 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 13 May 2022 10:28:19 -0500 Subject: [PATCH 07/15] Fix linting --- cli/users.go | 5 +++-- cli/userstatus_test.go | 2 ++ codersdk/users.go | 8 ++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/cli/users.go b/cli/users.go index dcdce690fa3d7..0cd995c8ff7cf 100644 --- a/cli/users.go +++ b/cli/users.go @@ -3,10 +3,11 @@ package cli import ( "time" - "github.com/coder/coder/cli/cliui" - "github.com/coder/coder/codersdk" "github.com/jedib0t/go-pretty/v6/table" "github.com/spf13/cobra" + + "github.com/coder/coder/cli/cliui" + "github.com/coder/coder/codersdk" ) func users() *cobra.Command { diff --git a/cli/userstatus_test.go b/cli/userstatus_test.go index 7ce0727a75711..899feed5f9667 100644 --- a/cli/userstatus_test.go +++ b/cli/userstatus_test.go @@ -20,6 +20,7 @@ func TestUserStatus(t *testing.T) { otherUser, err := other.User(context.Background(), codersdk.Me) require.NoError(t, err, "fetch user") + //nolint:paralleltest t.Run("StatusSelf", func(t *testing.T) { cmd, root := clitest.New(t, "users", "status", "suspend", "me") clitest.SetupConfig(t, client, root) @@ -31,6 +32,7 @@ func TestUserStatus(t *testing.T) { require.ErrorContains(t, err, "cannot suspend yourself") }) + //nolint:paralleltest t.Run("StatusOther", func(t *testing.T) { require.Equal(t, otherUser.Status, codersdk.UserStatusActive, "start as active") diff --git a/codersdk/users.go b/codersdk/users.go index 3a226c67c68ab..a02f2e3b2a0b6 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -344,15 +344,11 @@ func (c *Client) Logout(ctx context.Context) error { // User returns a user for the ID provided. // If the uuid is nil, the current user will be returned. func (c *Client) User(ctx context.Context, id uuid.UUID) (User, error) { - return c.userByIdentifier(ctx, uuidOrMe(id)) + return c.UserByIdentifier(ctx, uuidOrMe(id)) } // UserByIdentifier returns a user for the username or uuid provided. -func (c *Client) UserByIdentifier(ctx context.Context, username string) (User, error) { - return c.userByIdentifier(ctx, username) -} - -func (c *Client) userByIdentifier(ctx context.Context, ident string) (User, error) { +func (c *Client) UserByIdentifier(ctx context.Context, ident string) (User, error) { res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s", ident), nil) if err != nil { return User{}, err From 40bef92551d07066f14808073bce494f12953084 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 13 May 2022 10:40:05 -0500 Subject: [PATCH 08/15] Fix linting --- coderd/users.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/users.go b/coderd/users.go index c5eda83342dbc..e3274b902f5fe 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -309,7 +309,7 @@ func (api *api) putUserStatus(status database.UserStatus) func(rw http.ResponseW apiKey := httpmw.APIKey(r) if status == database.UserStatusSuspended && user.ID == apiKey.UserID { httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ - Message: fmt.Sprintf("You cannot suspend yourself"), + Message: "You cannot suspend yourself", }) return } From 5e80192d1a603a4ded86003671a3e3c1e7fdd248 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 13 May 2022 10:45:15 -0500 Subject: [PATCH 09/15] Fix unit test --- coderd/users_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/coderd/users_test.go b/coderd/users_test.go index 2950c42286108..3db82d214c886 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -462,10 +462,9 @@ func TestPutUserSuspend(t *testing.T) { client := coderdtest.New(t, nil) coderdtest.CreateFirstUser(t, client) client.User(context.Background(), codersdk.Me) - suspendedUser, err := client.SetUserStatus(context.Background(), codersdk.Me, codersdk.UserStatusSuspended) + _, err := client.SetUserStatus(context.Background(), codersdk.Me, codersdk.UserStatusSuspended) - require.NoError(t, err) - require.Equal(t, suspendedUser.Status, codersdk.UserStatusSuspended) + require.ErrorContains(t, err, "suspend yourself", "cannot suspend yourself") }) } From 53adce9c75da87aeab41d5eed8aad04d8f142988 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 13 May 2022 13:03:58 -0500 Subject: [PATCH 10/15] PR cleanup, better short msg --- cli/userstatus.go | 19 +++++++++++-------- coderd/users_test.go | 6 +++--- codersdk/users.go | 4 ++-- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/cli/userstatus.go b/cli/userstatus.go index 6970b956447ff..78e526f95f910 100644 --- a/cli/userstatus.go +++ b/cli/userstatus.go @@ -16,23 +16,26 @@ func userStatus() *cobra.Command { Short: "Update the status of a user", } cmd.AddCommand( - setUserStatus(codersdk.UserStatusActive), - setUserStatus(codersdk.UserStatusSuspended), + createUserStatusCommand(codersdk.UserStatusActive), + createUserStatusCommand(codersdk.UserStatusSuspended), ) return cmd } -// setUserStatus sets a user status. -func setUserStatus(sdkStatus codersdk.UserStatus) *cobra.Command { +// createUserStatusCommand sets a user status. +func createUserStatusCommand(sdkStatus codersdk.UserStatus) *cobra.Command { var verb string var aliases []string + var short string switch sdkStatus { case codersdk.UserStatusActive: - verb = "active" - aliases = []string{"activate"} + verb = "activate" + aliases = []string{"active"} + short = "Update a user's status to 'active'. Active users can fully interact with the platform" case codersdk.UserStatusSuspended: verb = "suspend" aliases = []string{"rm", "delete"} + short = "Update a user's status to 'suspended'. A suspended user cannot log into the platform" default: panic(fmt.Sprintf("%s is not supported", sdkStatus)) } @@ -42,7 +45,7 @@ func setUserStatus(sdkStatus codersdk.UserStatus) *cobra.Command { ) cmd := &cobra.Command{ Use: fmt.Sprintf("%s ", verb), - Short: fmt.Sprintf("Update a user's status to %q", sdkStatus), + Short: short, Args: cobra.ExactArgs(1), Aliases: aliases, Example: fmt.Sprintf("coder users status %s example_user", verb), @@ -81,7 +84,7 @@ func setUserStatus(sdkStatus codersdk.UserStatus) *cobra.Command { return err } - _, err = client.SetUserStatus(cmd.Context(), user.ID, sdkStatus) + _, err = client.UpdateUserStatus(cmd.Context(), user.ID, sdkStatus) if err != nil { return xerrors.Errorf("%s user: %w", verb, err) } diff --git a/coderd/users_test.go b/coderd/users_test.go index 3db82d214c886..19ebf36ea0241 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -452,7 +452,7 @@ func TestPutUserSuspend(t *testing.T) { Password: "password", OrganizationID: me.OrganizationID, }) - user, err := client.SetUserStatus(context.Background(), user.ID, codersdk.UserStatusSuspended) + user, err := client.UpdateUserStatus(context.Background(), user.ID, codersdk.UserStatusSuspended) require.NoError(t, err) require.Equal(t, user.Status, codersdk.UserStatusSuspended) }) @@ -462,7 +462,7 @@ func TestPutUserSuspend(t *testing.T) { client := coderdtest.New(t, nil) coderdtest.CreateFirstUser(t, client) client.User(context.Background(), codersdk.Me) - _, err := client.SetUserStatus(context.Background(), codersdk.Me, codersdk.UserStatusSuspended) + _, err := client.UpdateUserStatus(context.Background(), codersdk.Me, codersdk.UserStatusSuspended) require.ErrorContains(t, err, "suspend yourself", "cannot suspend yourself") }) @@ -555,7 +555,7 @@ func TestGetUsers(t *testing.T) { require.NoError(t, err) active = append(active, bruno) - _, err = client.SetUserStatus(context.Background(), alice.ID, codersdk.UserStatusSuspended) + _, err = client.UpdateUserStatus(context.Background(), alice.ID, codersdk.UserStatusSuspended) require.NoError(t, err) users, err := client.Users(context.Background(), codersdk.UsersRequest{ diff --git a/codersdk/users.go b/codersdk/users.go index a02f2e3b2a0b6..4ea317f72336b 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -212,8 +212,8 @@ func (c *Client) UpdateUserProfile(ctx context.Context, userID uuid.UUID, req Up return user, json.NewDecoder(res.Body).Decode(&user) } -// SetUserStatus sets the user status to the given status -func (c *Client) SetUserStatus(ctx context.Context, userID uuid.UUID, status UserStatus) (User, error) { +// UpdateUserStatus sets the user status to the given status +func (c *Client) UpdateUserStatus(ctx context.Context, userID uuid.UUID, status UserStatus) (User, error) { path := fmt.Sprintf("/api/v2/users/%s/status/", uuidOrMe(userID)) switch status { case UserStatusActive: From 2ed42499aba4c8c9527fc74b51d896e79b7887a0 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 13 May 2022 15:06:55 -0500 Subject: [PATCH 11/15] Move command outside status subgroup --- cli/users.go | 3 ++- cli/userstatus.go | 14 +------------- cli/userstatus_test.go | 8 ++++---- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/cli/users.go b/cli/users.go index 0cd995c8ff7cf..8a0223c975451 100644 --- a/cli/users.go +++ b/cli/users.go @@ -18,7 +18,8 @@ func users() *cobra.Command { cmd.AddCommand( userCreate(), userList(), - userStatus(), + createUserStatusCommand(codersdk.UserStatusActive), + createUserStatusCommand(codersdk.UserStatusSuspended), ) return cmd } diff --git a/cli/userstatus.go b/cli/userstatus.go index 78e526f95f910..b3e65a9d7e1cf 100644 --- a/cli/userstatus.go +++ b/cli/userstatus.go @@ -10,18 +10,6 @@ import ( "github.com/coder/coder/codersdk" ) -func userStatus() *cobra.Command { - cmd := &cobra.Command{ - Use: "status", - Short: "Update the status of a user", - } - cmd.AddCommand( - createUserStatusCommand(codersdk.UserStatusActive), - createUserStatusCommand(codersdk.UserStatusSuspended), - ) - return cmd -} - // createUserStatusCommand sets a user status. func createUserStatusCommand(sdkStatus codersdk.UserStatus) *cobra.Command { var verb string @@ -48,7 +36,7 @@ func createUserStatusCommand(sdkStatus codersdk.UserStatus) *cobra.Command { Short: short, Args: cobra.ExactArgs(1), Aliases: aliases, - Example: fmt.Sprintf("coder users status %s example_user", verb), + Example: fmt.Sprintf("coder users %s example_user", verb), RunE: func(cmd *cobra.Command, args []string) error { client, err := createClient(cmd) if err != nil { diff --git a/cli/userstatus_test.go b/cli/userstatus_test.go index 899feed5f9667..f48d7057744c0 100644 --- a/cli/userstatus_test.go +++ b/cli/userstatus_test.go @@ -22,7 +22,7 @@ func TestUserStatus(t *testing.T) { //nolint:paralleltest t.Run("StatusSelf", func(t *testing.T) { - cmd, root := clitest.New(t, "users", "status", "suspend", "me") + cmd, root := clitest.New(t, "users", "suspend", "me") clitest.SetupConfig(t, client, root) // Yes to the prompt cmd.SetIn(bytes.NewReader([]byte("yes\n"))) @@ -36,7 +36,7 @@ func TestUserStatus(t *testing.T) { t.Run("StatusOther", func(t *testing.T) { require.Equal(t, otherUser.Status, codersdk.UserStatusActive, "start as active") - cmd, root := clitest.New(t, "users", "status", "suspend", otherUser.Username) + cmd, root := clitest.New(t, "users", "suspend", otherUser.Username) clitest.SetupConfig(t, client, root) // Yes to the prompt cmd.SetIn(bytes.NewReader([]byte("yes\n"))) @@ -48,8 +48,8 @@ func TestUserStatus(t *testing.T) { require.NoError(t, err, "fetch suspended user") require.Equal(t, otherUser.Status, codersdk.UserStatusSuspended, "suspended user") - // Set back to active - cmd, root = clitest.New(t, "users", "status", "active", otherUser.Username) + // Set back to active. Try using a uuid as well + cmd, root = clitest.New(t, "users", "activate", otherUser.ID.String()) clitest.SetupConfig(t, client, root) // Yes to the prompt cmd.SetIn(bytes.NewReader([]byte("yes\n"))) From ab8e5d1499449b280db1f43948c479e7ab2c0271 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 16 May 2022 11:01:43 -0500 Subject: [PATCH 12/15] Fix table headers --- cli/userlist.go | 2 +- cli/users.go | 2 +- cli/userstatus.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/userlist.go b/cli/userlist.go index debbec3aa48a3..7a9b9cb7908e7 100644 --- a/cli/userlist.go +++ b/cli/userlist.go @@ -29,7 +29,7 @@ func userList() *cobra.Command { return err }, } - cmd.Flags().StringArrayVarP(&columns, "column", "c", []string{"Username", "Email", "Created At"}, + cmd.Flags().StringArrayVarP(&columns, "column", "c", []string{"username", "email", "created_at"}, "Specify a column to filter in the table.") return cmd } diff --git a/cli/users.go b/cli/users.go index 8a0223c975451..29b20b3d1d60e 100644 --- a/cli/users.go +++ b/cli/users.go @@ -29,7 +29,7 @@ func users() *cobra.Command { // columns to display func displayUsers(filterColumns []string, users ...codersdk.User) string { tableWriter := cliui.Table() - header := table.Row{"ID", "Username", "Email", "Created At", "Status"} + header := table.Row{"id", "username", "email", "created_at", "status"} tableWriter.AppendHeader(header) tableWriter.SetColumnConfigs(cliui.FilterTableColumns(header, filterColumns)) tableWriter.SortBy([]table.SortBy{{ diff --git a/cli/userstatus.go b/cli/userstatus.go index b3e65a9d7e1cf..ffed9063573f2 100644 --- a/cli/userstatus.go +++ b/cli/userstatus.go @@ -79,7 +79,7 @@ func createUserStatusCommand(sdkStatus codersdk.UserStatus) *cobra.Command { return nil }, } - cmd.Flags().StringArrayVarP(&columns, "column", "c", []string{"Username", "Email", "Created At", "Status"}, + cmd.Flags().StringArrayVarP(&columns, "column", "c", []string{"username", "email", "created_at", "status"}, "Specify a column to filter in the table.") return cmd } From e19b3bb42d0eaa6da1d39947a28ef28cbce7d476 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 16 May 2022 15:04:14 -0500 Subject: [PATCH 13/15] UserID is now a string and allows for username too --- coderd/coderdtest/coderdtest.go | 4 +- coderd/gitsshkey_test.go | 12 +++--- coderd/roles_test.go | 2 +- coderd/users_test.go | 24 ++++++------ coderd/workspaces_test.go | 2 +- codersdk/gitsshkey.go | 8 ++-- codersdk/organizations.go | 8 ++-- codersdk/roles.go | 2 +- codersdk/users.go | 68 +++++++++++++-------------------- 9 files changed, 57 insertions(+), 73 deletions(-) diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index bcf45e43ed060..6985cc96174e7 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -254,7 +254,7 @@ func CreateAnotherUser(t *testing.T, client *codersdk.Client, organizationID uui } // TODO: @emyrk switch "other" to "client" when we support updating other // users. - _, err := other.UpdateUserRoles(context.Background(), user.ID, codersdk.UpdateRoles{Roles: siteRoles}) + _, err := other.UpdateUserRoles(context.Background(), user.ID.String(), codersdk.UpdateRoles{Roles: siteRoles}) require.NoError(t, err, "update site roles") // Update org roles @@ -262,7 +262,7 @@ func CreateAnotherUser(t *testing.T, client *codersdk.Client, organizationID uui organizationID, err := uuid.Parse(orgID) require.NoError(t, err, fmt.Sprintf("parse org id %q", orgID)) // TODO: @Emyrk add the member to the organization if they do not already belong. - _, err = other.UpdateOrganizationMemberRoles(context.Background(), organizationID, user.ID, + _, err = other.UpdateOrganizationMemberRoles(context.Background(), organizationID, user.ID.String(), codersdk.UpdateRoles{Roles: append(roles, rbac.RoleOrgMember(organizationID))}) require.NoError(t, err, "update org membership roles") } diff --git a/coderd/gitsshkey_test.go b/coderd/gitsshkey_test.go index 1839cd9bd31fb..fe0071c67c262 100644 --- a/coderd/gitsshkey_test.go +++ b/coderd/gitsshkey_test.go @@ -21,7 +21,7 @@ func TestGitSSHKey(t *testing.T) { ctx := context.Background() client := coderdtest.New(t, nil) res := coderdtest.CreateFirstUser(t, client) - key, err := client.GitSSHKey(ctx, res.UserID) + key, err := client.GitSSHKey(ctx, res.UserID.String()) require.NoError(t, err) require.NotEmpty(t, key.PublicKey) }) @@ -32,7 +32,7 @@ func TestGitSSHKey(t *testing.T) { SSHKeygenAlgorithm: gitsshkey.AlgorithmEd25519, }) res := coderdtest.CreateFirstUser(t, client) - key, err := client.GitSSHKey(ctx, res.UserID) + key, err := client.GitSSHKey(ctx, res.UserID.String()) require.NoError(t, err) require.NotEmpty(t, key.PublicKey) }) @@ -43,7 +43,7 @@ func TestGitSSHKey(t *testing.T) { SSHKeygenAlgorithm: gitsshkey.AlgorithmECDSA, }) res := coderdtest.CreateFirstUser(t, client) - key, err := client.GitSSHKey(ctx, res.UserID) + key, err := client.GitSSHKey(ctx, res.UserID.String()) require.NoError(t, err) require.NotEmpty(t, key.PublicKey) }) @@ -54,7 +54,7 @@ func TestGitSSHKey(t *testing.T) { SSHKeygenAlgorithm: gitsshkey.AlgorithmRSA4096, }) res := coderdtest.CreateFirstUser(t, client) - key, err := client.GitSSHKey(ctx, res.UserID) + key, err := client.GitSSHKey(ctx, res.UserID.String()) require.NoError(t, err) require.NotEmpty(t, key.PublicKey) }) @@ -65,10 +65,10 @@ func TestGitSSHKey(t *testing.T) { SSHKeygenAlgorithm: gitsshkey.AlgorithmEd25519, }) res := coderdtest.CreateFirstUser(t, client) - key1, err := client.GitSSHKey(ctx, res.UserID) + key1, err := client.GitSSHKey(ctx, res.UserID.String()) require.NoError(t, err) require.NotEmpty(t, key1.PublicKey) - key2, err := client.RegenerateGitSSHKey(ctx, res.UserID) + key2, err := client.RegenerateGitSSHKey(ctx, res.UserID.String()) require.NoError(t, err) require.GreaterOrEqual(t, key2.UpdatedAt, key1.UpdatedAt) require.NotEmpty(t, key2.PublicKey) diff --git a/coderd/roles_test.go b/coderd/roles_test.go index b4d79ae6760c4..2ff4931215fa7 100644 --- a/coderd/roles_test.go +++ b/coderd/roles_test.go @@ -107,7 +107,7 @@ func TestListRoles(t *testing.T) { member := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID) orgAdmin := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID, rbac.RoleOrgAdmin(admin.OrganizationID)) - otherOrg, err := client.CreateOrganization(ctx, admin.UserID, codersdk.CreateOrganizationRequest{ + otherOrg, err := client.CreateOrganization(ctx, admin.UserID.String(), codersdk.CreateOrganizationRequest{ Name: "other", }) require.NoError(t, err, "create org") diff --git a/coderd/users_test.go b/coderd/users_test.go index 19ebf36ea0241..3f460df0c23c5 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -209,7 +209,7 @@ func TestUpdateUserProfile(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) coderdtest.CreateFirstUser(t, client) - _, err := client.UpdateUserProfile(context.Background(), uuid.New(), codersdk.UpdateUserProfileRequest{ + _, err := client.UpdateUserProfile(context.Background(), uuid.New().String(), codersdk.UpdateUserProfileRequest{ Username: "newusername", Email: "newemail@coder.com", }) @@ -295,7 +295,7 @@ func TestUpdateUserPassword(t *testing.T) { client := coderdtest.New(t, nil) admin := coderdtest.CreateFirstUser(t, client) member := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID) - err := member.UpdateUserPassword(context.Background(), admin.UserID, codersdk.UpdateUserPasswordRequest{ + err := member.UpdateUserPassword(context.Background(), admin.UserID.String(), codersdk.UpdateUserPasswordRequest{ Password: "newpassword", }) require.Error(t, err, "member should not be able to update admin password") @@ -312,7 +312,7 @@ func TestUpdateUserPassword(t *testing.T) { OrganizationID: admin.OrganizationID, }) require.NoError(t, err, "create member") - err = client.UpdateUserPassword(context.Background(), member.ID, codersdk.UpdateUserPasswordRequest{ + err = client.UpdateUserPassword(context.Background(), member.ID.String(), codersdk.UpdateUserPasswordRequest{ Password: "newpassword", }) require.NoError(t, err, "admin should be able to update member password") @@ -339,7 +339,7 @@ func TestGrantRoles(t *testing.T) { }) require.Error(t, err, "org role in site") - _, err = admin.UpdateUserRoles(ctx, uuid.New(), codersdk.UpdateRoles{ + _, err = admin.UpdateUserRoles(ctx, uuid.New().String(), codersdk.UpdateRoles{ Roles: []string{rbac.RoleOrgMember(first.OrganizationID)}, }) require.Error(t, err, "user does not exist") @@ -354,12 +354,12 @@ func TestGrantRoles(t *testing.T) { }) require.Error(t, err, "role in org without membership") - _, err = member.UpdateUserRoles(ctx, first.UserID, codersdk.UpdateRoles{ + _, err = member.UpdateUserRoles(ctx, first.UserID.String(), codersdk.UpdateRoles{ Roles: []string{rbac.RoleMember()}, }) require.Error(t, err, "member cannot change other's roles") - _, err = member.UpdateOrganizationMemberRoles(ctx, first.OrganizationID, first.UserID, codersdk.UpdateRoles{ + _, err = member.UpdateOrganizationMemberRoles(ctx, first.OrganizationID, first.UserID.String(), codersdk.UpdateRoles{ Roles: []string{rbac.RoleMember()}, }) require.Error(t, err, "member cannot change other's org roles") @@ -452,7 +452,7 @@ func TestPutUserSuspend(t *testing.T) { Password: "password", OrganizationID: me.OrganizationID, }) - user, err := client.UpdateUserStatus(context.Background(), user.ID, codersdk.UserStatusSuspended) + user, err := client.UpdateUserStatus(context.Background(), user.Username, codersdk.UserStatusSuspended) require.NoError(t, err) require.Equal(t, user.Status, codersdk.UserStatusSuspended) }) @@ -489,7 +489,7 @@ func TestGetUser(t *testing.T) { client := coderdtest.New(t, nil) firstUser := coderdtest.CreateFirstUser(t, client) - user, err := client.User(context.Background(), firstUser.UserID) + user, err := client.User(context.Background(), firstUser.UserID.String()) require.NoError(t, err) require.Equal(t, firstUser.UserID, user.ID) require.Equal(t, firstUser.OrganizationID, user.OrganizationIDs[0]) @@ -500,10 +500,10 @@ func TestGetUser(t *testing.T) { client := coderdtest.New(t, nil) firstUser := coderdtest.CreateFirstUser(t, client) - exp, err := client.User(context.Background(), firstUser.UserID) + exp, err := client.User(context.Background(), firstUser.UserID.String()) require.NoError(t, err) - user, err := client.UserByIdentifier(context.Background(), exp.Username) + user, err := client.User(context.Background(), exp.Username) require.NoError(t, err) require.Equal(t, exp, user) }) @@ -533,7 +533,7 @@ func TestGetUsers(t *testing.T) { client := coderdtest.New(t, nil) first := coderdtest.CreateFirstUser(t, client) - firstUser, err := client.User(context.Background(), first.UserID) + firstUser, err := client.User(context.Background(), first.UserID.String()) require.NoError(t, err, "") active = append(active, firstUser) @@ -555,7 +555,7 @@ func TestGetUsers(t *testing.T) { require.NoError(t, err) active = append(active, bruno) - _, err = client.UpdateUserStatus(context.Background(), alice.ID, codersdk.UserStatusSuspended) + _, err = client.UpdateUserStatus(context.Background(), alice.Username, codersdk.UserStatusSuspended) require.NoError(t, err) users, err := client.Users(context.Background(), codersdk.UsersRequest{ diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index f7f31e0017637..33cd61ddb1611 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -170,7 +170,7 @@ func TestPostWorkspaceBuild(t *testing.T) { require.Equal(t, workspace.LatestBuild.ID.String(), build.BeforeID.String()) coderdtest.AwaitWorkspaceBuildJob(t, client, build.ID) - workspaces, err := client.WorkspacesByOwner(context.Background(), user.OrganizationID, user.UserID) + workspaces, err := client.WorkspacesByOwner(context.Background(), user.OrganizationID, user.UserID.String()) require.NoError(t, err) require.Len(t, workspaces, 0) }) diff --git a/codersdk/gitsshkey.go b/codersdk/gitsshkey.go index 3cc4333e735e3..922387452691f 100644 --- a/codersdk/gitsshkey.go +++ b/codersdk/gitsshkey.go @@ -24,8 +24,8 @@ type AgentGitSSHKey struct { } // GitSSHKey returns the user's git SSH public key. -func (c *Client) GitSSHKey(ctx context.Context, userID uuid.UUID) (GitSSHKey, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/gitsshkey", uuidOrMe(userID)), nil) +func (c *Client) GitSSHKey(ctx context.Context, userID string) (GitSSHKey, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/gitsshkey", userID), nil) if err != nil { return GitSSHKey{}, xerrors.Errorf("execute request: %w", err) } @@ -40,8 +40,8 @@ func (c *Client) GitSSHKey(ctx context.Context, userID uuid.UUID) (GitSSHKey, er } // RegenerateGitSSHKey will create a new SSH key pair for the user and return it. -func (c *Client) RegenerateGitSSHKey(ctx context.Context, userID uuid.UUID) (GitSSHKey, error) { - res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/gitsshkey", uuidOrMe(userID)), nil) +func (c *Client) RegenerateGitSSHKey(ctx context.Context, userID string) (GitSSHKey, error) { + res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/gitsshkey", userID), nil) if err != nil { return GitSSHKey{}, xerrors.Errorf("execute request: %w", err) } diff --git a/codersdk/organizations.go b/codersdk/organizations.go index ca85dfbbc139e..9e16e16631f98 100644 --- a/codersdk/organizations.go +++ b/codersdk/organizations.go @@ -201,8 +201,8 @@ func (c *Client) WorkspacesByOrganization(ctx context.Context, organizationID uu } // WorkspacesByOwner returns all workspaces contained in the organization owned by the user. -func (c *Client) WorkspacesByOwner(ctx context.Context, organizationID, userID uuid.UUID) ([]Workspace, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/workspaces/%s", organizationID, uuidOrMe(userID)), nil) +func (c *Client) WorkspacesByOwner(ctx context.Context, organizationID uuid.UUID, user string) ([]Workspace, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/workspaces/%s", organizationID, user), nil) if err != nil { return nil, err } @@ -217,8 +217,8 @@ func (c *Client) WorkspacesByOwner(ctx context.Context, organizationID, userID u } // WorkspaceByOwnerAndName returns a workspace by the owner's UUID and the workspace's name. -func (c *Client) WorkspaceByOwnerAndName(ctx context.Context, organization, owner uuid.UUID, name string) (Workspace, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/workspaces/%s/%s", organization, uuidOrMe(owner), name), nil) +func (c *Client) WorkspaceByOwnerAndName(ctx context.Context, organization uuid.UUID, owner string, name string) (Workspace, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/organizations/%s/workspaces/%s/%s", organization, owner, name), nil) if err != nil { return Workspace{}, err } diff --git a/codersdk/roles.go b/codersdk/roles.go index c67255b435b53..305800edc0c43 100644 --- a/codersdk/roles.go +++ b/codersdk/roles.go @@ -45,7 +45,7 @@ func (c *Client) ListOrganizationRoles(ctx context.Context, org uuid.UUID) ([]Ro } func (c *Client) CheckPermissions(ctx context.Context, checks UserPermissionCheckRequest) (UserPermissionCheckResponse, error) { - res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/authorization", uuidOrMe(Me)), checks) + res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/authorization", Me), checks) if err != nil { return nil, err } diff --git a/codersdk/users.go b/codersdk/users.go index 4ea317f72336b..ab9e9adfafa01 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -12,7 +12,7 @@ import ( ) // Me is used as a replacement for your own ID. -var Me = uuid.Nil +var Me = "me" type UserStatus string @@ -199,8 +199,8 @@ func (c *Client) CreateUser(ctx context.Context, req CreateUserRequest) (User, e } // UpdateUserProfile enables callers to update profile information -func (c *Client) UpdateUserProfile(ctx context.Context, userID uuid.UUID, req UpdateUserProfileRequest) (User, error) { - res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/profile", uuidOrMe(userID)), req) +func (c *Client) UpdateUserProfile(ctx context.Context, userID string, req UpdateUserProfileRequest) (User, error) { + res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/profile", userID), req) if err != nil { return User{}, err } @@ -213,8 +213,8 @@ func (c *Client) UpdateUserProfile(ctx context.Context, userID uuid.UUID, req Up } // UpdateUserStatus sets the user status to the given status -func (c *Client) UpdateUserStatus(ctx context.Context, userID uuid.UUID, status UserStatus) (User, error) { - path := fmt.Sprintf("/api/v2/users/%s/status/", uuidOrMe(userID)) +func (c *Client) UpdateUserStatus(ctx context.Context, userID string, status UserStatus) (User, error) { + path := fmt.Sprintf("/api/v2/users/%s/status/", userID) switch status { case UserStatusActive: path += "active" @@ -239,8 +239,8 @@ func (c *Client) UpdateUserStatus(ctx context.Context, userID uuid.UUID, status // UpdateUserPassword updates a user password. // It calls PUT /users/{user}/password -func (c *Client) UpdateUserPassword(ctx context.Context, userID uuid.UUID, req UpdateUserPasswordRequest) error { - res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/password", uuidOrMe(userID)), req) +func (c *Client) UpdateUserPassword(ctx context.Context, userID string, req UpdateUserPasswordRequest) error { + res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/password", userID), req) if err != nil { return err } @@ -253,8 +253,8 @@ func (c *Client) UpdateUserPassword(ctx context.Context, userID uuid.UUID, req U // UpdateUserRoles grants the userID the specified roles. // Include ALL roles the user has. -func (c *Client) UpdateUserRoles(ctx context.Context, userID uuid.UUID, req UpdateRoles) (User, error) { - res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/roles", uuidOrMe(userID)), req) +func (c *Client) UpdateUserRoles(ctx context.Context, userID string, req UpdateRoles) (User, error) { + res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/roles", userID), req) if err != nil { return User{}, err } @@ -268,8 +268,8 @@ func (c *Client) UpdateUserRoles(ctx context.Context, userID uuid.UUID, req Upda // UpdateOrganizationMemberRoles grants the userID the specified roles in an org. // Include ALL roles the user has. -func (c *Client) UpdateOrganizationMemberRoles(ctx context.Context, organizationID, userID uuid.UUID, req UpdateRoles) (OrganizationMember, error) { - res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/organizations/%s/members/%s/roles", organizationID, uuidOrMe(userID)), req) +func (c *Client) UpdateOrganizationMemberRoles(ctx context.Context, organizationID uuid.UUID, userID string, req UpdateRoles) (OrganizationMember, error) { + res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/organizations/%s/members/%s/roles", organizationID, userID), req) if err != nil { return OrganizationMember{}, err } @@ -282,8 +282,8 @@ func (c *Client) UpdateOrganizationMemberRoles(ctx context.Context, organization } // GetUserRoles returns all roles the user has -func (c *Client) GetUserRoles(ctx context.Context, userID uuid.UUID) (UserRoles, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/roles", uuidOrMe(userID)), nil) +func (c *Client) GetUserRoles(ctx context.Context, userID string) (UserRoles, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/roles", userID), nil) if err != nil { return UserRoles{}, err } @@ -296,8 +296,8 @@ func (c *Client) GetUserRoles(ctx context.Context, userID uuid.UUID) (UserRoles, } // CreateAPIKey generates an API key for the user ID provided. -func (c *Client) CreateAPIKey(ctx context.Context, userID uuid.UUID) (*GenerateAPIKeyResponse, error) { - res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/keys", uuidOrMe(userID)), nil) +func (c *Client) CreateAPIKey(ctx context.Context, userID string) (*GenerateAPIKeyResponse, error) { + res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/keys", userID), nil) if err != nil { return nil, err } @@ -341,15 +341,9 @@ func (c *Client) Logout(ctx context.Context) error { return nil } -// User returns a user for the ID provided. -// If the uuid is nil, the current user will be returned. -func (c *Client) User(ctx context.Context, id uuid.UUID) (User, error) { - return c.UserByIdentifier(ctx, uuidOrMe(id)) -} - -// UserByIdentifier returns a user for the username or uuid provided. -func (c *Client) UserByIdentifier(ctx context.Context, ident string) (User, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s", ident), nil) +// User returns a user for the ID/username provided. +func (c *Client) User(ctx context.Context, userIdent string) (User, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s", userIdent), nil) if err != nil { return User{}, err } @@ -387,8 +381,8 @@ func (c *Client) Users(ctx context.Context, req UsersRequest) ([]User, error) { } // OrganizationsByUser returns all organizations the user is a member of. -func (c *Client) OrganizationsByUser(ctx context.Context, userID uuid.UUID) ([]Organization, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations", uuidOrMe(userID)), nil) +func (c *Client) OrganizationsByUser(ctx context.Context, userID string) ([]Organization, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations", userID), nil) if err != nil { return nil, err } @@ -400,8 +394,8 @@ func (c *Client) OrganizationsByUser(ctx context.Context, userID uuid.UUID) ([]O return orgs, json.NewDecoder(res.Body).Decode(&orgs) } -func (c *Client) OrganizationByName(ctx context.Context, userID uuid.UUID, name string) (Organization, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations/%s", uuidOrMe(userID), name), nil) +func (c *Client) OrganizationByName(ctx context.Context, userID string, name string) (Organization, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations/%s", userID, name), nil) if err != nil { return Organization{}, err } @@ -414,8 +408,8 @@ func (c *Client) OrganizationByName(ctx context.Context, userID uuid.UUID, name } // CreateOrganization creates an organization and adds the provided user as an admin. -func (c *Client) CreateOrganization(ctx context.Context, userID uuid.UUID, req CreateOrganizationRequest) (Organization, error) { - res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/organizations", uuidOrMe(userID)), req) +func (c *Client) CreateOrganization(ctx context.Context, userID string, req CreateOrganizationRequest) (Organization, error) { + res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/organizations", userID), req) if err != nil { return Organization{}, err } @@ -446,8 +440,8 @@ func (c *Client) AuthMethods(ctx context.Context) (AuthMethods, error) { } // WorkspacesByUser returns all workspaces a user has access to. -func (c *Client) WorkspacesByUser(ctx context.Context, userID uuid.UUID) ([]Workspace, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/workspaces", uuidOrMe(userID)), nil) +func (c *Client) WorkspacesByUser(ctx context.Context, userID string) ([]Workspace, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/workspaces", userID), nil) if err != nil { return nil, err } @@ -460,13 +454,3 @@ func (c *Client) WorkspacesByUser(ctx context.Context, userID uuid.UUID) ([]Work var workspaces []Workspace return workspaces, json.NewDecoder(res.Body).Decode(&workspaces) } - -// uuidOrMe returns the provided uuid as a string if it's valid, ortherwise -// `me`. -func uuidOrMe(id uuid.UUID) string { - if id == Me { - return "me" - } - - return id.String() -} From c36a7877163e483e1ad795088d4b08b9f7e381bc Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 16 May 2022 15:06:14 -0500 Subject: [PATCH 14/15] rename args --- codersdk/gitsshkey.go | 8 +++---- codersdk/users.go | 56 +++++++++++++++++++++---------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/codersdk/gitsshkey.go b/codersdk/gitsshkey.go index 922387452691f..f20c0666caf0f 100644 --- a/codersdk/gitsshkey.go +++ b/codersdk/gitsshkey.go @@ -24,8 +24,8 @@ type AgentGitSSHKey struct { } // GitSSHKey returns the user's git SSH public key. -func (c *Client) GitSSHKey(ctx context.Context, userID string) (GitSSHKey, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/gitsshkey", userID), nil) +func (c *Client) GitSSHKey(ctx context.Context, user string) (GitSSHKey, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/gitsshkey", user), nil) if err != nil { return GitSSHKey{}, xerrors.Errorf("execute request: %w", err) } @@ -40,8 +40,8 @@ func (c *Client) GitSSHKey(ctx context.Context, userID string) (GitSSHKey, error } // RegenerateGitSSHKey will create a new SSH key pair for the user and return it. -func (c *Client) RegenerateGitSSHKey(ctx context.Context, userID string) (GitSSHKey, error) { - res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/gitsshkey", userID), nil) +func (c *Client) RegenerateGitSSHKey(ctx context.Context, user string) (GitSSHKey, error) { + res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/gitsshkey", user), nil) if err != nil { return GitSSHKey{}, xerrors.Errorf("execute request: %w", err) } diff --git a/codersdk/users.go b/codersdk/users.go index ab9e9adfafa01..75c9088415f46 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -199,8 +199,8 @@ func (c *Client) CreateUser(ctx context.Context, req CreateUserRequest) (User, e } // UpdateUserProfile enables callers to update profile information -func (c *Client) UpdateUserProfile(ctx context.Context, userID string, req UpdateUserProfileRequest) (User, error) { - res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/profile", userID), req) +func (c *Client) UpdateUserProfile(ctx context.Context, user string, req UpdateUserProfileRequest) (User, error) { + res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/profile", user), req) if err != nil { return User{}, err } @@ -208,13 +208,13 @@ func (c *Client) UpdateUserProfile(ctx context.Context, userID string, req Updat if res.StatusCode != http.StatusOK { return User{}, readBodyAsError(res) } - var user User - return user, json.NewDecoder(res.Body).Decode(&user) + var resp User + return resp, json.NewDecoder(res.Body).Decode(&resp) } // UpdateUserStatus sets the user status to the given status -func (c *Client) UpdateUserStatus(ctx context.Context, userID string, status UserStatus) (User, error) { - path := fmt.Sprintf("/api/v2/users/%s/status/", userID) +func (c *Client) UpdateUserStatus(ctx context.Context, user string, status UserStatus) (User, error) { + path := fmt.Sprintf("/api/v2/users/%s/status/", user) switch status { case UserStatusActive: path += "active" @@ -233,14 +233,14 @@ func (c *Client) UpdateUserStatus(ctx context.Context, userID string, status Use return User{}, readBodyAsError(res) } - var user User - return user, json.NewDecoder(res.Body).Decode(&user) + var resp User + return resp, json.NewDecoder(res.Body).Decode(&resp) } // UpdateUserPassword updates a user password. // It calls PUT /users/{user}/password -func (c *Client) UpdateUserPassword(ctx context.Context, userID string, req UpdateUserPasswordRequest) error { - res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/password", userID), req) +func (c *Client) UpdateUserPassword(ctx context.Context, user string, req UpdateUserPasswordRequest) error { + res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/password", user), req) if err != nil { return err } @@ -253,8 +253,8 @@ func (c *Client) UpdateUserPassword(ctx context.Context, userID string, req Upda // UpdateUserRoles grants the userID the specified roles. // Include ALL roles the user has. -func (c *Client) UpdateUserRoles(ctx context.Context, userID string, req UpdateRoles) (User, error) { - res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/roles", userID), req) +func (c *Client) UpdateUserRoles(ctx context.Context, user string, req UpdateRoles) (User, error) { + res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/users/%s/roles", user), req) if err != nil { return User{}, err } @@ -262,14 +262,14 @@ func (c *Client) UpdateUserRoles(ctx context.Context, userID string, req UpdateR if res.StatusCode != http.StatusOK { return User{}, readBodyAsError(res) } - var user User - return user, json.NewDecoder(res.Body).Decode(&user) + var resp User + return resp, json.NewDecoder(res.Body).Decode(&resp) } // UpdateOrganizationMemberRoles grants the userID the specified roles in an org. // Include ALL roles the user has. -func (c *Client) UpdateOrganizationMemberRoles(ctx context.Context, organizationID uuid.UUID, userID string, req UpdateRoles) (OrganizationMember, error) { - res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/organizations/%s/members/%s/roles", organizationID, userID), req) +func (c *Client) UpdateOrganizationMemberRoles(ctx context.Context, organizationID uuid.UUID, user string, req UpdateRoles) (OrganizationMember, error) { + res, err := c.request(ctx, http.MethodPut, fmt.Sprintf("/api/v2/organizations/%s/members/%s/roles", organizationID, user), req) if err != nil { return OrganizationMember{}, err } @@ -282,8 +282,8 @@ func (c *Client) UpdateOrganizationMemberRoles(ctx context.Context, organization } // GetUserRoles returns all roles the user has -func (c *Client) GetUserRoles(ctx context.Context, userID string) (UserRoles, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/roles", userID), nil) +func (c *Client) GetUserRoles(ctx context.Context, user string) (UserRoles, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/roles", user), nil) if err != nil { return UserRoles{}, err } @@ -296,8 +296,8 @@ func (c *Client) GetUserRoles(ctx context.Context, userID string) (UserRoles, er } // CreateAPIKey generates an API key for the user ID provided. -func (c *Client) CreateAPIKey(ctx context.Context, userID string) (*GenerateAPIKeyResponse, error) { - res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/keys", userID), nil) +func (c *Client) CreateAPIKey(ctx context.Context, user string) (*GenerateAPIKeyResponse, error) { + res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/keys", user), nil) if err != nil { return nil, err } @@ -381,8 +381,8 @@ func (c *Client) Users(ctx context.Context, req UsersRequest) ([]User, error) { } // OrganizationsByUser returns all organizations the user is a member of. -func (c *Client) OrganizationsByUser(ctx context.Context, userID string) ([]Organization, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations", userID), nil) +func (c *Client) OrganizationsByUser(ctx context.Context, user string) ([]Organization, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations", user), nil) if err != nil { return nil, err } @@ -394,8 +394,8 @@ func (c *Client) OrganizationsByUser(ctx context.Context, userID string) ([]Orga return orgs, json.NewDecoder(res.Body).Decode(&orgs) } -func (c *Client) OrganizationByName(ctx context.Context, userID string, name string) (Organization, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations/%s", userID, name), nil) +func (c *Client) OrganizationByName(ctx context.Context, user string, name string) (Organization, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/organizations/%s", user, name), nil) if err != nil { return Organization{}, err } @@ -408,8 +408,8 @@ func (c *Client) OrganizationByName(ctx context.Context, userID string, name str } // CreateOrganization creates an organization and adds the provided user as an admin. -func (c *Client) CreateOrganization(ctx context.Context, userID string, req CreateOrganizationRequest) (Organization, error) { - res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/organizations", userID), req) +func (c *Client) CreateOrganization(ctx context.Context, user string, req CreateOrganizationRequest) (Organization, error) { + res, err := c.request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/organizations", user), req) if err != nil { return Organization{}, err } @@ -440,8 +440,8 @@ func (c *Client) AuthMethods(ctx context.Context) (AuthMethods, error) { } // WorkspacesByUser returns all workspaces a user has access to. -func (c *Client) WorkspacesByUser(ctx context.Context, userID string) ([]Workspace, error) { - res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/workspaces", userID), nil) +func (c *Client) WorkspacesByUser(ctx context.Context, user string) ([]Workspace, error) { + res, err := c.request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/workspaces", user), nil) if err != nil { return nil, err } From c22892319953241146afefa9548afb9f4f88fafd Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 16 May 2022 15:16:13 -0500 Subject: [PATCH 15/15] Fix tests --- cli/userstatus.go | 4 ++-- cli/userstatus_test.go | 4 ++-- coderd/autobuild/executor/lifecycle_executor_test.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/userstatus.go b/cli/userstatus.go index ffed9063573f2..152584d8244d5 100644 --- a/cli/userstatus.go +++ b/cli/userstatus.go @@ -48,7 +48,7 @@ func createUserStatusCommand(sdkStatus codersdk.UserStatus) *cobra.Command { return xerrors.Errorf("user identifier cannot be an empty string") } - user, err := client.UserByIdentifier(cmd.Context(), identifier) + user, err := client.User(cmd.Context(), identifier) if err != nil { return xerrors.Errorf("fetch user: %w", err) } @@ -72,7 +72,7 @@ func createUserStatusCommand(sdkStatus codersdk.UserStatus) *cobra.Command { return err } - _, err = client.UpdateUserStatus(cmd.Context(), user.ID, sdkStatus) + _, err = client.UpdateUserStatus(cmd.Context(), user.ID.String(), sdkStatus) if err != nil { return xerrors.Errorf("%s user: %w", verb, err) } diff --git a/cli/userstatus_test.go b/cli/userstatus_test.go index f48d7057744c0..700c08616d84b 100644 --- a/cli/userstatus_test.go +++ b/cli/userstatus_test.go @@ -44,7 +44,7 @@ func TestUserStatus(t *testing.T) { require.NoError(t, err, "suspend user") // Check the user status - otherUser, err = client.User(context.Background(), otherUser.ID) + otherUser, err = client.User(context.Background(), otherUser.Username) require.NoError(t, err, "fetch suspended user") require.Equal(t, otherUser.Status, codersdk.UserStatusSuspended, "suspended user") @@ -57,7 +57,7 @@ func TestUserStatus(t *testing.T) { require.NoError(t, err, "suspend user") // Check the user status - otherUser, err = client.User(context.Background(), otherUser.ID) + otherUser, err = client.User(context.Background(), otherUser.ID.String()) require.NoError(t, err, "fetch active user") require.Equal(t, otherUser.Status, codersdk.UserStatusActive, "active user") }) diff --git a/coderd/autobuild/executor/lifecycle_executor_test.go b/coderd/autobuild/executor/lifecycle_executor_test.go index 51f3864e16e38..445be2d8889c3 100644 --- a/coderd/autobuild/executor/lifecycle_executor_test.go +++ b/coderd/autobuild/executor/lifecycle_executor_test.go @@ -78,7 +78,7 @@ func TestExecutorAutostartTemplateUpdated(t *testing.T) { require.Empty(t, workspace.AutostartSchedule) // Given: the workspace template has been updated - orgs, err := client.OrganizationsByUser(ctx, workspace.OwnerID) + orgs, err := client.OrganizationsByUser(ctx, workspace.OwnerID.String()) require.NoError(t, err) require.Len(t, orgs, 1)