mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
feat: Add users create and list commands (#1111)
This allows for *extremely basic* user management.
This commit is contained in:
90
cli/usercreate.go
Normal file
90
cli/usercreate.go
Normal file
@ -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
|
||||
}
|
42
cli/usercreate_test.go
Normal file
42
cli/usercreate_test.go
Normal file
@ -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
|
||||
})
|
||||
}
|
46
cli/userlist.go
Normal file
46
cli/userlist.go
Normal file
@ -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
|
||||
},
|
||||
}
|
||||
}
|
30
cli/userlist_test.go
Normal file
30
cli/userlist_test.go
Normal file
@ -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
|
||||
}
|
@ -6,5 +6,6 @@ func users() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "users",
|
||||
}
|
||||
cmd.AddCommand(userCreate(), userList())
|
||||
return cmd
|
||||
}
|
||||
|
@ -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
|
||||
|
7
coderd/database/dump.sql
generated
7
coderd/database/dump.sql
generated
@ -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 (
|
||||
|
@ -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)
|
||||
);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
@ -60,7 +59,6 @@ type CreateUserRequest struct {
|
||||
type UpdateUserProfileRequest struct {
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Username string `json:"username" validate:"required,username"`
|
||||
Name *string `json:"name"`
|
||||
}
|
||||
|
||||
// LoginWithPasswordRequest enables callers to authenticate with email and password.
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user