diff --git a/cli/usercreate.go b/cli/usercreate.go new file mode 100644 index 0000000000000..dce69c080c8ee --- /dev/null +++ b/cli/usercreate.go @@ -0,0 +1,90 @@ +package cli + +import ( + "fmt" + + "github.com/go-playground/validator/v10" + "github.com/spf13/cobra" + "golang.org/x/xerrors" + + "github.com/coder/coder/cli/cliui" + "github.com/coder/coder/codersdk" + "github.com/coder/coder/cryptorand" +) + +func userCreate() *cobra.Command { + var ( + email string + username string + password string + ) + cmd := &cobra.Command{ + Use: "create", + RunE: func(cmd *cobra.Command, args []string) error { + client, err := createClient(cmd) + if err != nil { + return err + } + organization, err := currentOrganization(cmd, client) + if err != nil { + return err + } + if username == "" { + username, err = cliui.Prompt(cmd, cliui.PromptOptions{ + Text: "Username:", + }) + if err != nil { + return err + } + } + if email == "" { + email, err = cliui.Prompt(cmd, cliui.PromptOptions{ + Text: "Email:", + Validate: func(s string) error { + err := validator.New().Var(s, "email") + if err != nil { + return xerrors.New("That's not a valid email address!") + } + return err + }, + }) + if err != nil { + return err + } + } + if password == "" { + password, err = cryptorand.StringCharset(cryptorand.Human, 12) + if err != nil { + return err + } + } + + _, err = client.CreateUser(cmd.Context(), codersdk.CreateUserRequest{ + Email: email, + Username: username, + Password: password, + OrganizationID: organization.ID, + }) + if err != nil { + return err + } + _, _ = fmt.Fprintln(cmd.ErrOrStderr(), `A new user has been created! +Share the instructions below to get them started. +`+cliui.Styles.Placeholder.Render("—————————————————————————————————————————————————")+` +Download the Coder command line for your operating system: +https://github.com/coder/coder/releases + +Run `+cliui.Styles.Code.Render("coder login "+client.URL.String())+` to authenticate. + +Your email is: `+cliui.Styles.Field.Render(email)+` +Your password is: `+cliui.Styles.Field.Render(password)+` + +Create a workspace `+cliui.Styles.Code.Render("coder workspaces create")+`!`) + return nil + }, + } + cmd.Flags().StringVarP(&email, "email", "e", "", "Specifies an email address for the new user.") + cmd.Flags().StringVarP(&username, "username", "u", "", "Specifies a username for the new user.") + cmd.Flags().StringVarP(&password, "password", "p", "", "Specifies a password for the new user.") + return cmd +} diff --git a/cli/usercreate_test.go b/cli/usercreate_test.go new file mode 100644 index 0000000000000..f4b303a318d38 --- /dev/null +++ b/cli/usercreate_test.go @@ -0,0 +1,42 @@ +package cli_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/coder/coder/cli/clitest" + "github.com/coder/coder/coderd/coderdtest" + "github.com/coder/coder/pty/ptytest" +) + +func TestUserCreate(t *testing.T) { + t.Parallel() + t.Run("Prompts", func(t *testing.T) { + t.Parallel() + client := coderdtest.New(t, nil) + coderdtest.CreateFirstUser(t, client) + cmd, root := clitest.New(t, "users", "create") + clitest.SetupConfig(t, client, root) + doneChan := make(chan struct{}) + pty := ptytest.New(t) + cmd.SetIn(pty.Input()) + cmd.SetOut(pty.Output()) + go func() { + defer close(doneChan) + err := cmd.Execute() + require.NoError(t, err) + }() + matches := []string{ + "Username", "dean", + "Email", "dean@coder.com", + } + for i := 0; i < len(matches); i += 2 { + match := matches[i] + value := matches[i+1] + pty.ExpectMatch(match) + pty.WriteLine(value) + } + <-doneChan + }) +} diff --git a/cli/userlist.go b/cli/userlist.go new file mode 100644 index 0000000000000..a96d5c6ce7bf8 --- /dev/null +++ b/cli/userlist.go @@ -0,0 +1,46 @@ +package cli + +import ( + "fmt" + "sort" + "time" + + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" + + "github.com/coder/coder/codersdk" +) + +func userList() *cobra.Command { + return &cobra.Command{ + Use: "list", + Aliases: []string{"ls"}, + RunE: func(cmd *cobra.Command, args []string) error { + client, err := createClient(cmd) + if err != nil { + return err + } + users, err := client.Users(cmd.Context(), codersdk.UsersRequest{}) + if err != nil { + return err + } + sort.Slice(users, func(i, j int) bool { + return users[i].Username < users[j].Username + }) + + tableWriter := table.NewWriter() + tableWriter.SetStyle(table.StyleLight) + tableWriter.Style().Options.SeparateColumns = false + tableWriter.AppendHeader(table.Row{"Username", "Email", "Created At"}) + for _, user := range users { + tableWriter.AppendRow(table.Row{ + user.Username, + user.Email, + user.CreatedAt.Format(time.Stamp), + }) + } + _, err = fmt.Fprintln(cmd.OutOrStdout(), tableWriter.Render()) + return err + }, + } +} diff --git a/cli/userlist_test.go b/cli/userlist_test.go new file mode 100644 index 0000000000000..37baed59d3d67 --- /dev/null +++ b/cli/userlist_test.go @@ -0,0 +1,30 @@ +package cli_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/coder/coder/cli/clitest" + "github.com/coder/coder/coderd/coderdtest" + "github.com/coder/coder/pty/ptytest" +) + +func TestUserList(t *testing.T) { + t.Parallel() + client := coderdtest.New(t, nil) + coderdtest.CreateFirstUser(t, client) + cmd, root := clitest.New(t, "users", "list") + clitest.SetupConfig(t, client, root) + doneChan := make(chan struct{}) + pty := ptytest.New(t) + cmd.SetIn(pty.Input()) + cmd.SetOut(pty.Output()) + go func() { + defer close(doneChan) + err := cmd.Execute() + require.NoError(t, err) + }() + pty.ExpectMatch("coder.com") + <-doneChan +} diff --git a/cli/users.go b/cli/users.go index 7dd3f309d44b3..9ffabfae0b697 100644 --- a/cli/users.go +++ b/cli/users.go @@ -6,5 +6,6 @@ func users() *cobra.Command { cmd := &cobra.Command{ Use: "users", } + cmd.AddCommand(userCreate(), userList()) return cmd } diff --git a/coderd/database/databasefake/databasefake.go b/coderd/database/databasefake/databasefake.go index 0f521117439b4..acf9f0913f3f1 100644 --- a/coderd/database/databasefake/databasefake.go +++ b/coderd/database/databasefake/databasefake.go @@ -207,8 +207,6 @@ func (q *fakeQuerier) GetUsers(_ context.Context, params database.GetUsersParams tmp = append(tmp, users[i]) } else if strings.Contains(user.Username, params.Search) { tmp = append(tmp, users[i]) - } else if strings.Contains(user.Name, params.Search) { - tmp = append(tmp, users[i]) } } users = tmp @@ -1116,8 +1114,6 @@ func (q *fakeQuerier) InsertUser(_ context.Context, arg database.InsertUserParam user := database.User{ ID: arg.ID, Email: arg.Email, - Name: arg.Name, - LoginType: arg.LoginType, HashedPassword: arg.HashedPassword, CreatedAt: arg.CreatedAt, UpdatedAt: arg.UpdatedAt, @@ -1135,7 +1131,6 @@ func (q *fakeQuerier) UpdateUserProfile(_ context.Context, arg database.UpdateUs if user.ID != arg.ID { continue } - user.Name = arg.Name user.Email = arg.Email user.Username = arg.Username q.users[index] = user diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index 0319082ec4ab2..52f7b94fe915e 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -218,13 +218,10 @@ CREATE TABLE templates ( CREATE TABLE users ( id uuid NOT NULL, email text NOT NULL, - name text NOT NULL, - revoked boolean NOT NULL, - login_type login_type NOT NULL, + username text DEFAULT ''::text NOT NULL, hashed_password bytea NOT NULL, created_at timestamp with time zone NOT NULL, - updated_at timestamp with time zone NOT NULL, - username text DEFAULT ''::text NOT NULL + updated_at timestamp with time zone NOT NULL ); CREATE TABLE workspace_agents ( diff --git a/coderd/database/migrations/000001_base.up.sql b/coderd/database/migrations/000001_base.up.sql index 81cd3a4f75b3e..79b37c6c8cfd9 100644 --- a/coderd/database/migrations/000001_base.up.sql +++ b/coderd/database/migrations/000001_base.up.sql @@ -12,13 +12,10 @@ CREATE TYPE login_type AS ENUM ( CREATE TABLE IF NOT EXISTS users ( id uuid NOT NULL, email text NOT NULL, - name text NOT NULL, - revoked boolean NOT NULL, - login_type login_type NOT NULL, + username text DEFAULT ''::text NOT NULL, hashed_password bytea NOT NULL, created_at timestamp with time zone NOT NULL, updated_at timestamp with time zone NOT NULL, - username text DEFAULT ''::text NOT NULL, PRIMARY KEY (id) ); diff --git a/coderd/database/models.go b/coderd/database/models.go index 2857bf391e4ea..56dc8fd77a58c 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -374,13 +374,10 @@ type TemplateVersion struct { type User struct { ID uuid.UUID `db:"id" json:"id"` Email string `db:"email" json:"email"` - Name string `db:"name" json:"name"` - Revoked bool `db:"revoked" json:"revoked"` - LoginType LoginType `db:"login_type" json:"login_type"` + Username string `db:"username" json:"username"` HashedPassword []byte `db:"hashed_password" json:"hashed_password"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` - Username string `db:"username" json:"username"` } type Workspace struct { diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index c1e7025b34936..3f76b362f4bb2 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -1782,7 +1782,7 @@ func (q *sqlQuerier) UpdateTemplateVersionByID(ctx context.Context, arg UpdateTe const getUserByEmailOrUsername = `-- name: GetUserByEmailOrUsername :one SELECT - id, email, name, revoked, login_type, hashed_password, created_at, updated_at, username + id, email, username, hashed_password, created_at, updated_at FROM users WHERE @@ -1803,20 +1803,17 @@ func (q *sqlQuerier) GetUserByEmailOrUsername(ctx context.Context, arg GetUserBy err := row.Scan( &i.ID, &i.Email, - &i.Name, - &i.Revoked, - &i.LoginType, + &i.Username, &i.HashedPassword, &i.CreatedAt, &i.UpdatedAt, - &i.Username, ) return i, err } const getUserByID = `-- name: GetUserByID :one SELECT - id, email, name, revoked, login_type, hashed_password, created_at, updated_at, username + id, email, username, hashed_password, created_at, updated_at FROM users WHERE @@ -1831,13 +1828,10 @@ func (q *sqlQuerier) GetUserByID(ctx context.Context, id uuid.UUID) (User, error err := row.Scan( &i.ID, &i.Email, - &i.Name, - &i.Revoked, - &i.LoginType, + &i.Username, &i.HashedPassword, &i.CreatedAt, &i.UpdatedAt, - &i.Username, ) return i, err } @@ -1858,7 +1852,7 @@ func (q *sqlQuerier) GetUserCount(ctx context.Context) (int64, error) { const getUsers = `-- name: GetUsers :many SELECT - id, email, name, revoked, login_type, hashed_password, created_at, updated_at, username + id, email, username, hashed_password, created_at, updated_at FROM users WHERE @@ -1888,7 +1882,6 @@ WHERE WHEN $2 :: text != '' THEN ( email LIKE concat('%', $2, '%') OR username LIKE concat('%', $2, '%') - OR 'name' LIKE concat('%', $2, '%') ) ELSE true END @@ -1925,13 +1918,10 @@ func (q *sqlQuerier) GetUsers(ctx context.Context, arg GetUsersParams) ([]User, if err := rows.Scan( &i.ID, &i.Email, - &i.Name, - &i.Revoked, - &i.LoginType, + &i.Username, &i.HashedPassword, &i.CreatedAt, &i.UpdatedAt, - &i.Username, ); err != nil { return nil, err } @@ -1951,51 +1941,41 @@ INSERT INTO users ( id, email, - "name", - login_type, - revoked, + username, hashed_password, created_at, - updated_at, - username + updated_at ) VALUES - ($1, $2, $3, $4, FALSE, $5, $6, $7, $8) RETURNING id, email, name, revoked, login_type, hashed_password, created_at, updated_at, username + ($1, $2, $3, $4, $5, $6) RETURNING id, email, username, hashed_password, created_at, updated_at ` type InsertUserParams struct { ID uuid.UUID `db:"id" json:"id"` Email string `db:"email" json:"email"` - Name string `db:"name" json:"name"` - LoginType LoginType `db:"login_type" json:"login_type"` + Username string `db:"username" json:"username"` HashedPassword []byte `db:"hashed_password" json:"hashed_password"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` - Username string `db:"username" json:"username"` } func (q *sqlQuerier) InsertUser(ctx context.Context, arg InsertUserParams) (User, error) { row := q.db.QueryRowContext(ctx, insertUser, arg.ID, arg.Email, - arg.Name, - arg.LoginType, + arg.Username, arg.HashedPassword, arg.CreatedAt, arg.UpdatedAt, - arg.Username, ) var i User err := row.Scan( &i.ID, &i.Email, - &i.Name, - &i.Revoked, - &i.LoginType, + &i.Username, &i.HashedPassword, &i.CreatedAt, &i.UpdatedAt, - &i.Username, ) return i, err } @@ -2005,17 +1985,15 @@ UPDATE users SET email = $2, - "name" = $3, - username = $4, - updated_at = $5 + username = $3, + updated_at = $4 WHERE - id = $1 RETURNING id, email, name, revoked, login_type, hashed_password, created_at, updated_at, username + id = $1 RETURNING id, email, username, hashed_password, created_at, updated_at ` type UpdateUserProfileParams struct { ID uuid.UUID `db:"id" json:"id"` Email string `db:"email" json:"email"` - Name string `db:"name" json:"name"` Username string `db:"username" json:"username"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } @@ -2024,7 +2002,6 @@ func (q *sqlQuerier) UpdateUserProfile(ctx context.Context, arg UpdateUserProfil row := q.db.QueryRowContext(ctx, updateUserProfile, arg.ID, arg.Email, - arg.Name, arg.Username, arg.UpdatedAt, ) @@ -2032,13 +2009,10 @@ func (q *sqlQuerier) UpdateUserProfile(ctx context.Context, arg UpdateUserProfil err := row.Scan( &i.ID, &i.Email, - &i.Name, - &i.Revoked, - &i.LoginType, + &i.Username, &i.HashedPassword, &i.CreatedAt, &i.UpdatedAt, - &i.Username, ) return i, err } diff --git a/coderd/database/queries/users.sql b/coderd/database/queries/users.sql index e16303d791ff5..c8cc39b42ff1f 100644 --- a/coderd/database/queries/users.sql +++ b/coderd/database/queries/users.sql @@ -30,25 +30,21 @@ INSERT INTO users ( id, email, - "name", - login_type, - revoked, + username, hashed_password, created_at, - updated_at, - username + updated_at ) VALUES - ($1, $2, $3, $4, FALSE, $5, $6, $7, $8) RETURNING *; + ($1, $2, $3, $4, $5, $6) RETURNING *; -- name: UpdateUserProfile :one UPDATE users SET email = $2, - "name" = $3, - username = $4, - updated_at = $5 + username = $3, + updated_at = $4 WHERE id = $1 RETURNING *; @@ -84,7 +80,6 @@ WHERE WHEN @search :: text != '' THEN ( email LIKE concat('%', @search, '%') OR username LIKE concat('%', @search, '%') - OR 'name' LIKE concat('%', @search, '%') ) ELSE true END diff --git a/coderd/httpmw/organizationparam_test.go b/coderd/httpmw/organizationparam_test.go index a5bd256a66bbd..2e4a8eddf4414 100644 --- a/coderd/httpmw/organizationparam_test.go +++ b/coderd/httpmw/organizationparam_test.go @@ -40,8 +40,6 @@ func TestOrganizationParam(t *testing.T) { user, err := db.InsertUser(r.Context(), database.InsertUserParams{ ID: userID, Email: "testaccount@coder.com", - Name: "example", - LoginType: database.LoginTypePassword, HashedPassword: hashed[:], Username: username, CreatedAt: database.Now(), diff --git a/coderd/httpmw/templateparam_test.go b/coderd/httpmw/templateparam_test.go index fb3d2324d0490..b4db9925391c3 100644 --- a/coderd/httpmw/templateparam_test.go +++ b/coderd/httpmw/templateparam_test.go @@ -39,8 +39,6 @@ func TestTemplateParam(t *testing.T) { user, err := db.InsertUser(r.Context(), database.InsertUserParams{ ID: userID, Email: "testaccount@coder.com", - Name: "example", - LoginType: database.LoginTypePassword, HashedPassword: hashed[:], Username: username, CreatedAt: database.Now(), diff --git a/coderd/httpmw/templateversionparam_test.go b/coderd/httpmw/templateversionparam_test.go index 7207a14d7bf92..f168661d8bde8 100644 --- a/coderd/httpmw/templateversionparam_test.go +++ b/coderd/httpmw/templateversionparam_test.go @@ -39,8 +39,6 @@ func TestTemplateVersionParam(t *testing.T) { user, err := db.InsertUser(r.Context(), database.InsertUserParams{ ID: userID, Email: "testaccount@coder.com", - Name: "example", - LoginType: database.LoginTypePassword, HashedPassword: hashed[:], Username: username, CreatedAt: database.Now(), diff --git a/coderd/httpmw/workspaceagentparam_test.go b/coderd/httpmw/workspaceagentparam_test.go index 575a144c6efde..c7f931438901d 100644 --- a/coderd/httpmw/workspaceagentparam_test.go +++ b/coderd/httpmw/workspaceagentparam_test.go @@ -39,8 +39,6 @@ func TestWorkspaceAgentParam(t *testing.T) { user, err := db.InsertUser(r.Context(), database.InsertUserParams{ ID: userID, Email: "testaccount@coder.com", - Name: "example", - LoginType: database.LoginTypePassword, HashedPassword: hashed[:], Username: username, CreatedAt: database.Now(), diff --git a/coderd/httpmw/workspacebuildparam_test.go b/coderd/httpmw/workspacebuildparam_test.go index 39722ea644944..0e72e02fcc9b9 100644 --- a/coderd/httpmw/workspacebuildparam_test.go +++ b/coderd/httpmw/workspacebuildparam_test.go @@ -39,8 +39,6 @@ func TestWorkspaceBuildParam(t *testing.T) { user, err := db.InsertUser(r.Context(), database.InsertUserParams{ ID: userID, Email: "testaccount@coder.com", - Name: "example", - LoginType: database.LoginTypePassword, HashedPassword: hashed[:], Username: username, CreatedAt: database.Now(), diff --git a/coderd/httpmw/workspaceparam_test.go b/coderd/httpmw/workspaceparam_test.go index 0f10c0e129ada..b874cabbe26df 100644 --- a/coderd/httpmw/workspaceparam_test.go +++ b/coderd/httpmw/workspaceparam_test.go @@ -39,8 +39,6 @@ func TestWorkspaceParam(t *testing.T) { user, err := db.InsertUser(r.Context(), database.InsertUserParams{ ID: userID, Email: "testaccount@coder.com", - Name: "example", - LoginType: database.LoginTypePassword, HashedPassword: hashed[:], Username: username, CreatedAt: database.Now(), diff --git a/coderd/users.go b/coderd/users.go index 046a26ef74c30..579fcffd7e862 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -233,11 +233,6 @@ func (api *api) putUserProfile(rw http.ResponseWriter, r *http.Request) { if !httpapi.Read(rw, r, ¶ms) { return } - - if params.Name == nil { - params.Name = &user.Name - } - existentUser, err := api.Database.GetUserByEmailOrUsername(r.Context(), database.GetUserByEmailOrUsernameParams{ Email: params.Email, Username: params.Username, @@ -273,7 +268,6 @@ func (api *api) putUserProfile(rw http.ResponseWriter, r *http.Request) { updatedUserProfile, err := api.Database.UpdateUserProfile(r.Context(), database.UpdateUserProfileParams{ ID: user.ID, - Name: *params.Name, Email: params.Email, Username: params.Username, UpdatedAt: database.Now(), @@ -896,7 +890,6 @@ func (api *api) createUser(ctx context.Context, req codersdk.CreateUserRequest) ID: uuid.New(), Email: req.Email, Username: req.Username, - LoginType: database.LoginTypePassword, CreatedAt: database.Now(), UpdatedAt: database.Now(), } @@ -949,7 +942,6 @@ func convertUser(user database.User) codersdk.User { Email: user.Email, CreatedAt: user.CreatedAt, Username: user.Username, - Name: user.Name, } } diff --git a/coderd/users_test.go b/coderd/users_test.go index 6c677da34d115..cb0139d1aed50 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -283,28 +283,6 @@ func TestUpdateUserProfile(t *testing.T) { require.Equal(t, userProfile.Username, me.Username) require.Equal(t, userProfile.Email, "newemail@coder.com") }) - - t.Run("KeepUserName", func(t *testing.T) { - t.Parallel() - client := coderdtest.New(t, nil) - coderdtest.CreateFirstUser(t, client) - me, _ := client.User(context.Background(), codersdk.Me) - newName := "New Name" - firstProfile, _ := client.UpdateUserProfile(context.Background(), codersdk.Me, codersdk.UpdateUserProfileRequest{ - Username: me.Username, - Email: me.Email, - Name: &newName, - }) - t.Log(firstProfile) - userProfile, err := client.UpdateUserProfile(context.Background(), codersdk.Me, codersdk.UpdateUserProfileRequest{ - Username: "newusername", - Email: "newemail@coder.com", - }) - require.NoError(t, err) - require.Equal(t, userProfile.Username, "newusername") - require.Equal(t, userProfile.Email, "newemail@coder.com") - require.Equal(t, userProfile.Name, newName) - }) } func TestUserByName(t *testing.T) { diff --git a/codersdk/users.go b/codersdk/users.go index 283db8c93eb69..da5f8f23fa475 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -34,7 +34,6 @@ type User struct { Email string `json:"email" validate:"required"` CreatedAt time.Time `json:"created_at" validate:"required"` Username string `json:"username" validate:"required"` - Name string `json:"name"` } type CreateFirstUserRequest struct { @@ -58,9 +57,8 @@ type CreateUserRequest struct { } type UpdateUserProfileRequest struct { - Email string `json:"email" validate:"required,email"` - Username string `json:"username" validate:"required,username"` - Name *string `json:"name"` + Email string `json:"email" validate:"required,email"` + Username string `json:"username" validate:"required,username"` } // LoginWithPasswordRequest enables callers to authenticate with email and password. diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index e0c38e4225ba5..1aaa22b3ddb8a 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -81,10 +81,9 @@ export interface UsersRequest { export interface User { readonly email: string readonly username: string - readonly name: string } -// From codersdk/users.go:40:6. +// From codersdk/users.go:39:6. export interface CreateFirstUserRequest { readonly email: string readonly username: string @@ -92,47 +91,46 @@ export interface CreateFirstUserRequest { readonly organization: string } -// From codersdk/users.go:53:6. +// From codersdk/users.go:52:6. export interface CreateUserRequest { readonly email: string readonly username: string readonly password: string } -// From codersdk/users.go:60:6. +// From codersdk/users.go:59:6. export interface UpdateUserProfileRequest { readonly email: string readonly username: string - readonly name?: string } -// From codersdk/users.go:67:6. +// From codersdk/users.go:65:6. export interface LoginWithPasswordRequest { readonly email: string readonly password: string } -// From codersdk/users.go:73:6. +// From codersdk/users.go:71:6. export interface LoginWithPasswordResponse { readonly session_token: string } -// From codersdk/users.go:78:6. +// From codersdk/users.go:76:6. export interface GenerateAPIKeyResponse { readonly key: string } -// From codersdk/users.go:82:6. +// From codersdk/users.go:80:6. export interface CreateOrganizationRequest { readonly name: string } -// From codersdk/users.go:87:6. +// From codersdk/users.go:85:6. export interface CreateWorkspaceRequest { readonly name: string } -// From codersdk/users.go:96:6. +// From codersdk/users.go:94:6. export interface AuthMethods { readonly password: boolean readonly github: boolean