Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2fe1716

Browse files
committed
Add update user password endpoint
1 parent de39cf5 commit 2fe1716

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

coderd/coderd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ func New(options *Options) (http.Handler, func()) {
240240
r.Get("/", api.userByName)
241241
r.Put("/profile", api.putUserProfile)
242242
r.Put("/suspend", api.putUserSuspend)
243+
r.Put("/password", api.putUserPassword)
243244
r.Get("/organizations", api.organizationsByUser)
244245
r.Post("/organizations", api.postOrganizationsByUser)
245246
// These roles apply to the site wide permissions.

coderd/users.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,64 @@ func (api *api) putUserSuspend(rw http.ResponseWriter, r *http.Request) {
360360
httpapi.Write(rw, http.StatusOK, convertUser(suspendedUser, organizations))
361361
}
362362

363+
func (api *api) putUserPassword(rw http.ResponseWriter, r *http.Request) {
364+
user := httpmw.UserParam(r)
365+
366+
var params codersdk.UpdateUserHashedPasswordRequest
367+
if !httpapi.Read(rw, r, &params) {
368+
return
369+
}
370+
371+
// Check if the password is correct
372+
equal, err := userpassword.Compare(string(user.HashedPassword), params.Password)
373+
if err != nil {
374+
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
375+
Message: fmt.Sprintf("compare: %s", err.Error()),
376+
})
377+
}
378+
if !equal {
379+
// This message is the same as above to remove ease in detecting whether
380+
// users are registered or not. Attackers still could with a timing attack.
381+
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
382+
Message: "invalid email or password",
383+
})
384+
return
385+
}
386+
387+
// Check if the new password and the confirmation match
388+
if params.NewPassword != params.ConfirmNewPassword {
389+
errors := []httpapi.Error{
390+
{
391+
Field: "confirm_new_password",
392+
Detail: "The value does not match the new password",
393+
},
394+
}
395+
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
396+
Message: fmt.Sprintf("The new password and the new password confirmation don't match"),
397+
Errors: errors,
398+
})
399+
return
400+
}
401+
402+
// Hash password and update it in the database
403+
hashedPassword, hashError := userpassword.Hash(params.NewPassword)
404+
if hashError != nil {
405+
xerrors.Errorf("hash password: %w", hashError)
406+
return
407+
}
408+
databaseError := api.Database.UpdateUserHashedPassword(r.Context(), database.UpdateUserHashedPasswordParams{
409+
HashedPassword: []byte(hashedPassword),
410+
})
411+
if databaseError != nil {
412+
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
413+
Message: fmt.Sprintf("put user password: %s", err.Error()),
414+
})
415+
return
416+
}
417+
418+
httpapi.Write(rw, http.StatusNoContent, nil)
419+
}
420+
363421
func (api *api) userRoles(rw http.ResponseWriter, r *http.Request) {
364422
user := httpmw.UserParam(r)
365423

codersdk/users.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ type UpdateUserProfileRequest struct {
7272
Username string `json:"username" validate:"required,username"`
7373
}
7474

75+
type UpdateUserHashedPasswordRequest struct {
76+
Password string `json:"password" validate:"required"`
77+
NewPassword string `json:"new_password" validate:"required"`
78+
ConfirmNewPassword string `json:"confirm_new_password" validate:"required"`
79+
}
80+
7581
type UpdateRoles struct {
7682
Roles []string `json:"roles" validate:"required"`
7783
}

0 commit comments

Comments
 (0)