[MM-57942] Fix a panic on password is too long (#27449)

* return error from bcrypt, handle gracefully; remove dead code

* linting

* linting

* i18n

* fix test

* fill out translations
Этот коммит содержится в:
Christopher Poile
2024-07-03 17:58:26 -04:00
коммит произвёл GitHub
родитель 5d2bf1ea1c
Коммит cc5e87ae24
8 изменённых файлов: 54 добавлений и 30 удалений

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

@@ -14,6 +14,8 @@ import (
"time"
"unicode/utf8"
"github.com/pkg/errors"
"golang.org/x/crypto/bcrypt"
"golang.org/x/text/language"
@@ -378,10 +380,6 @@ func (u *User) IsValid() *AppError {
return InvalidUserError("auth_data_pwd", u.Id, *u.AuthData)
}
if len(u.Password) > UserPasswordMaxLength {
return InvalidUserError("password_limit", u.Id, "")
}
if !IsValidLocale(u.Locale) {
return InvalidUserError("locale", u.Id, u.Locale)
}
@@ -430,7 +428,7 @@ func NormalizeEmail(email string) string {
// PreSave will set the Id and Username if missing. It will also fill
// in the CreateAt, UpdateAt times. It will also hash the password. It should
// be run before saving the user to the db.
func (u *User) PreSave() {
func (u *User) PreSave() *AppError {
if u.Id == "" {
u.Id = NewId()
}
@@ -477,7 +475,15 @@ func (u *User) PreSave() {
}
if u.Password != "" {
u.Password = HashPassword(u.Password)
hashed, err := HashPassword(u.Password)
if errors.Is(err, bcrypt.ErrPasswordTooLong) {
return NewAppError("User.PreSave", "model.user.pre_save.password_too_long.app_error",
nil, "user_id="+u.Id, http.StatusBadRequest).Wrap(err)
} else if err != nil {
return NewAppError("User.PreSave", "model.user.pre_save.password_hash.app_error",
nil, "user_id="+u.Id, http.StatusBadRequest).Wrap(err)
}
u.Password = hashed
}
cs := u.GetCustomStatus()
@@ -485,6 +491,8 @@ func (u *User) PreSave() {
cs.PreSave()
u.SetCustomStatus(cs)
}
return nil
}
// PreUpdate should be run before updating the user in the db.
@@ -928,13 +936,13 @@ func (u *UserPatch) SetField(fieldName string, fieldValue string) {
}
// HashPassword generates a hash using the bcrypt.GenerateFromPassword
func HashPassword(password string) string {
func HashPassword(password string) (string, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(password), 10)
if err != nil {
panic(err)
return "", err
}
return string(hash)
return string(hash), nil
}
var validUsernameChars = regexp.MustCompile(`^[a-z0-9\.\-_]+$`)

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

@@ -9,6 +9,8 @@ import (
"strings"
"testing"
"golang.org/x/crypto/bcrypt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -47,12 +49,19 @@ func TestUserDeepCopy(t *testing.T) {
func TestUserPreSave(t *testing.T) {
user := User{Password: "test"}
user.PreSave()
err := user.PreSave()
require.Nil(t, err)
user.Etag(true, true)
assert.NotNil(t, user.Timezone, "Timezone is nil")
assert.Equal(t, user.Timezone["useAutomaticTimezone"], "true", "Timezone is not set to default")
}
func TestUserPreSavePwdTooLong(t *testing.T) {
user := User{Password: strings.Repeat("1234567890", 8)}
err := user.PreSave()
assert.ErrorIs(t, err, bcrypt.ErrPasswordTooLong)
}
func TestUserPreUpdate(t *testing.T) {
user := User{Password: "test"}
user.PreUpdate()