Add functionality to update password with password hash (#15343)

* Add functionality to update password with password hash

This can be used to update a user's password with a direct password
hash instead of providing the password in plaintext.

* Use test helper for local mode
Этот коммит содержится в:
Gabe Jackson
2020-08-26 11:28:00 -04:00
коммит произвёл GitHub
родитель e83462637e
Коммит 90ef61f74c
19 изменённых файлов: 243 добавлений и 137 удалений

Просмотреть файл

@@ -1492,18 +1492,31 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) {
}
var err *model.AppError
if c.Params.UserId == c.App.Session().UserId {
currentPassword := props["current_password"]
if len(currentPassword) <= 0 {
c.SetInvalidParam("current_password")
return
}
err = c.App.UpdatePasswordAsUser(c.Params.UserId, currentPassword, newPassword)
} else if c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
err = c.App.UpdatePasswordByUserIdSendEmail(c.Params.UserId, newPassword, c.App.T("api.user.reset_password.method"))
// There are two main update flows depending on whether the provided password
// is already hashed or not.
if props["already_hashed"] == "true" {
if c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
err = c.App.UpdateHashedPasswordByUserId(c.Params.UserId, newPassword)
} else if c.Params.UserId == c.App.Session().UserId {
err = model.NewAppError("updatePassword", "api.user.update_password.user_and_hashed.app_error", nil, "", http.StatusUnauthorized)
} else {
err = model.NewAppError("updatePassword", "api.user.update_password.context.app_error", nil, "", http.StatusForbidden)
}
} else {
err = model.NewAppError("updatePassword", "api.user.update_password.context.app_error", nil, "", http.StatusForbidden)
if c.Params.UserId == c.App.Session().UserId {
currentPassword := props["current_password"]
if len(currentPassword) <= 0 {
c.SetInvalidParam("current_password")
return
}
err = c.App.UpdatePasswordAsUser(c.Params.UserId, currentPassword, newPassword)
} else if c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
err = c.App.UpdatePasswordByUserIdSendEmail(c.Params.UserId, newPassword, c.App.T("api.user.reset_password.method"))
} else {
err = model.NewAppError("updatePassword", "api.user.update_password.context.app_error", nil, "", http.StatusForbidden)
}
}
if err != nil {

Просмотреть файл

@@ -25,6 +25,7 @@ func (api *API) InitUserLocal() {
api.BaseRoutes.User.Handle("/roles", api.ApiLocal(updateUserRoles)).Methods("PUT")
api.BaseRoutes.User.Handle("/mfa", api.ApiLocal(updateUserMfa)).Methods("PUT")
api.BaseRoutes.User.Handle("/active", api.ApiLocal(updateUserActive)).Methods("PUT")
api.BaseRoutes.User.Handle("/password", api.ApiLocal(updatePassword)).Methods("PUT")
api.BaseRoutes.User.Handle("/convert_to_bot", api.ApiLocal(convertUserToBot)).Methods("POST")
api.BaseRoutes.User.Handle("/email/verify/member", api.ApiLocal(verifyUserEmailWithoutToken)).Methods("POST")

Просмотреть файл

@@ -2806,6 +2806,29 @@ func TestUpdateUserPassword(t *testing.T) {
CheckNoError(t, resp)
}
func TestUpdateUserHashedPassword(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
client := th.Client
password := "SuperSecurePass23!"
passwordHash := "$2a$10$CiS1iWVPUj7rQNdY6XW53.DmaPLsETIvmW2p0asp4Dqpofs10UL5W"
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
pass, resp := client.UpdateUserHashedPassword(th.BasicUser.Id, passwordHash)
CheckNoError(t, resp)
require.True(t, pass)
})
_, resp := client.Login(th.BasicUser.Email, password)
CheckNoError(t, resp)
// Standard users should never be updating their passwords with already-
// hashed passwords.
pass, resp := client.UpdateUserHashedPassword(th.BasicUser.Id, passwordHash)
CheckUnauthorizedStatus(t, resp)
require.False(t, pass)
}
func TestResetPassword(t *testing.T) {
t.Skip("test disabled during old build server changes, should be investigated")