@@ -360,6 +360,64 @@ func (api *api) putUserSuspend(rw http.ResponseWriter, r *http.Request) {
360
360
httpapi .Write (rw , http .StatusOK , convertUser (suspendedUser , organizations ))
361
361
}
362
362
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
+
363
421
func (api * api ) userRoles (rw http.ResponseWriter , r * http.Request ) {
364
422
user := httpmw .UserParam (r )
365
423
0 commit comments