Skip to content

Commit 2a9b9be

Browse files
committed
Merge branch 'main' of github.com:coder/coder into bq/fe/update-user-password
2 parents d35139c + 57bb108 commit 2a9b9be

File tree

26 files changed

+372
-126
lines changed

26 files changed

+372
-126
lines changed

cli/cliui/agent.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55
"fmt"
66
"io"
7+
"os"
8+
"os/signal"
79
"sync"
810
"time"
911

@@ -46,6 +48,23 @@ func Agent(ctx context.Context, writer io.Writer, opts AgentOptions) error {
4648
spin.Start()
4749
defer spin.Stop()
4850

51+
ctx, cancelFunc := context.WithCancel(ctx)
52+
defer cancelFunc()
53+
stopSpin := make(chan os.Signal, 1)
54+
signal.Notify(stopSpin, os.Interrupt)
55+
defer signal.Stop(stopSpin)
56+
go func() {
57+
select {
58+
case <-ctx.Done():
59+
return
60+
case <-stopSpin:
61+
}
62+
signal.Stop(stopSpin)
63+
spin.Stop()
64+
// nolint:revive
65+
os.Exit(1)
66+
}()
67+
4968
ticker := time.NewTicker(opts.FetchInterval)
5069
defer ticker.Stop()
5170
timer := time.NewTimer(opts.WarnInterval)

cli/login.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,19 @@ func login() *cobra.Command {
117117
if err != nil {
118118
return xerrors.Errorf("specify password prompt: %w", err)
119119
}
120+
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
121+
Text: "Confirm " + cliui.Styles.Field.Render("password") + ":",
122+
Secret: true,
123+
Validate: func(s string) error {
124+
if s != password {
125+
return xerrors.Errorf("Passwords do not match")
126+
}
127+
return nil
128+
},
129+
})
130+
if err != nil {
131+
return xerrors.Errorf("confirm password prompt: %w", err)
132+
}
120133

121134
_, err = client.CreateFirstUser(cmd.Context(), codersdk.CreateFirstUserRequest{
122135
Email: email,

cli/login_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func TestLogin(t *testing.T) {
4343
"username", "testuser",
4444
"email", "user@coder.com",
4545
"password", "password",
46+
"password", "password", // Confirm.
4647
}
4748
for i := 0; i < len(matches); i += 2 {
4849
match := matches[i]
@@ -54,6 +55,44 @@ func TestLogin(t *testing.T) {
5455
<-doneChan
5556
})
5657

58+
t.Run("InitialUserTTYConfirmPasswordFailAndReprompt", func(t *testing.T) {
59+
t.Parallel()
60+
ctx, cancel := context.WithCancel(context.Background())
61+
defer cancel()
62+
client := coderdtest.New(t, nil)
63+
// The --force-tty flag is required on Windows, because the `isatty` library does not
64+
// accurately detect Windows ptys when they are not attached to a process:
65+
// https://github.com/mattn/go-isatty/issues/59
66+
doneChan := make(chan struct{})
67+
root, _ := clitest.New(t, "login", "--force-tty", client.URL.String())
68+
pty := ptytest.New(t)
69+
root.SetIn(pty.Input())
70+
root.SetOut(pty.Output())
71+
go func() {
72+
defer close(doneChan)
73+
err := root.ExecuteContext(ctx)
74+
require.ErrorIs(t, err, context.Canceled)
75+
}()
76+
77+
matches := []string{
78+
"first user?", "yes",
79+
"username", "testuser",
80+
"email", "user@coder.com",
81+
"password", "mypass",
82+
"password", "wrongpass", // Confirm.
83+
}
84+
for i := 0; i < len(matches); i += 2 {
85+
match := matches[i]
86+
value := matches[i+1]
87+
pty.ExpectMatch(match)
88+
pty.WriteLine(value)
89+
}
90+
pty.ExpectMatch("Passwords do not match")
91+
pty.ExpectMatch("password") // Re-prompt password.
92+
cancel()
93+
<-doneChan
94+
})
95+
5796
t.Run("ExistingUserValidTokenTTY", func(t *testing.T) {
5897
t.Parallel()
5998
client := coderdtest.New(t, nil)

coderd/httpmw/userparam.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,6 @@ func ExtractUserParam(db database.Store) func(http.Handler) http.Handler {
7676
}
7777
}
7878

79-
apiKey := APIKey(r)
80-
if apiKey.UserID != user.ID {
81-
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
82-
Message: "getting non-personal users isn't supported yet",
83-
})
84-
return
85-
}
86-
8779
ctx := context.WithValue(r.Context(), userParamContextKey{}, user)
8880
next.ServeHTTP(rw, r.WithContext(ctx))
8981
})

coderd/users.go

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -361,29 +361,14 @@ func (api *api) putUserSuspend(rw http.ResponseWriter, r *http.Request) {
361361
}
362362

363363
func (api *api) putUserPassword(rw http.ResponseWriter, r *http.Request) {
364-
user := httpmw.UserParam(r)
365-
366-
var params codersdk.UpdateUserPasswordRequest
364+
var (
365+
user = httpmw.UserParam(r)
366+
params codersdk.UpdateUserPasswordRequest
367+
)
367368
if !httpapi.Read(rw, r, &params) {
368369
return
369370
}
370371

371-
// Check if the new password and the confirmation match
372-
if params.Password != params.ConfirmPassword {
373-
requestErrors := []httpapi.Error{
374-
{
375-
Field: "confirm_new_password",
376-
Detail: "The value does not match the new password",
377-
},
378-
}
379-
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
380-
Message: fmt.Sprintf("The new password and the new password confirmation don't match"),
381-
Errors: requestErrors,
382-
})
383-
return
384-
}
385-
386-
// Hash password and update it in the database
387372
hashedPassword, err := userpassword.Hash(params.Password)
388373
if err != nil {
389374
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{

coderd/users_test.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -290,35 +290,38 @@ func TestUpdateUserProfile(t *testing.T) {
290290
func TestUpdateUserPassword(t *testing.T) {
291291
t.Parallel()
292292

293-
t.Run("DifferentPasswordConfirmation", func(t *testing.T) {
293+
t.Run("MemberCantUpdateAdminPassword", func(t *testing.T) {
294294
t.Parallel()
295295
client := coderdtest.New(t, nil)
296-
coderdtest.CreateFirstUser(t, client)
297-
err := client.UpdateUserPassword(context.Background(), codersdk.Me, codersdk.UpdateUserPasswordRequest{
298-
Password: "newpassword",
299-
ConfirmPassword: "wrongconfirmation",
296+
admin := coderdtest.CreateFirstUser(t, client)
297+
member := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID)
298+
err := member.UpdateUserPassword(context.Background(), admin.UserID, codersdk.UpdateUserPasswordRequest{
299+
Password: "newpassword",
300300
})
301-
var apiErr *codersdk.Error
302-
require.ErrorAs(t, err, &apiErr)
303-
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
301+
require.Error(t, err, "member should not be able to update admin password")
304302
})
305303

306-
t.Run("Success", func(t *testing.T) {
304+
t.Run("AdminCanUpdateMemberPassword", func(t *testing.T) {
307305
t.Parallel()
308306
client := coderdtest.New(t, nil)
309-
coderdtest.CreateFirstUser(t, client)
310-
err := client.UpdateUserPassword(context.Background(), codersdk.Me, codersdk.UpdateUserPasswordRequest{
311-
Password: "newpassword",
312-
ConfirmPassword: "newpassword",
307+
admin := coderdtest.CreateFirstUser(t, client)
308+
member, err := client.CreateUser(context.Background(), codersdk.CreateUserRequest{
309+
Email: "coder@coder.com",
310+
Username: "coder",
311+
Password: "password",
312+
OrganizationID: admin.OrganizationID,
313313
})
314-
require.NoError(t, err, "update password request should be successful")
315-
316-
// Check if the user can login using the new password
314+
require.NoError(t, err, "create member")
315+
err = client.UpdateUserPassword(context.Background(), member.ID, codersdk.UpdateUserPasswordRequest{
316+
Password: "newpassword",
317+
})
318+
require.NoError(t, err, "admin should be able to update member password")
319+
// Check if the member can login using the new password
317320
_, err = client.LoginWithPassword(context.Background(), codersdk.LoginWithPasswordRequest{
318-
Email: coderdtest.FirstUserParams.Email,
321+
Email: "coder@coder.com",
319322
Password: "newpassword",
320323
})
321-
require.NoError(t, err, "login should be successful")
324+
require.NoError(t, err, "member should login successfully with the new password")
322325
})
323326
}
324327

codersdk/users.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ type UpdateUserProfileRequest struct {
7373
}
7474

7575
type UpdateUserPasswordRequest struct {
76-
Password string `json:"password" validate:"required"`
77-
ConfirmPassword string `json:"confirm_new_password" validate:"required"`
76+
Password string `json:"password" validate:"required"`
7877
}
7978

8079
type UpdateRoles struct {

docs/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Follow](https://img.shields.io/twitter/follow/CoderHQ?label=%40CoderHQ&style=soc
1010

1111
Provision remote development environments with Terraform.
1212

13+
![Kubernetes workspace in Coder v2](./screenshot.png)
14+
1315
## Highlights
1416

1517
- Automate development environments for Linux, Windows, and macOS
@@ -100,6 +102,6 @@ Read the [contributing docs](./CONTRIBUTING.md).
100102

101103
<!--- Add your row by date (mm/dd/yyyy), most recent date at end of list --->
102104

103-
| Name | Start Date | First PR Date |Organization| GitHub User Link |
104-
| ------------- | :--------: | :-----------: |:----------:| ------------------------------: |
105-
| Mathias Fredriksson | 04/25/2022 | 04/25/2022 | [Coder](https://github.com/coder) | [mafredri](https://github.com/mafredri) |
105+
| Name | Start Date | First PR Date | Organization | GitHub User Link |
106+
| ------------------- | :--------: | :-----------: | :-------------------------------: | --------------------------------------: |
107+
| Mathias Fredriksson | 04/25/2022 | 04/25/2022 | [Coder](https://github.com/coder) | [mafredri](https://github.com/mafredri) |

docs/screenshot.png

520 KB
Loading

examples/docker-local/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ resource "docker_container" "workspace" {
4242
name = "coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}-root"
4343
dns = ["1.1.1.1"]
4444
command = ["sh", "-c", coder_agent.dev.init_script]
45-
env = ["CODER_TOKEN=${coder_agent.dev.token}"]
45+
env = ["CODER_AGENT_TOKEN=${coder_agent.dev.token}"]
4646
volumes {
4747
container_path = "/home/coder/"
4848
volume_name = docker_volume.coder_volume.name

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy