fix(cabana): enforce the 4-character password minimum on the Administrators form

The form's min:4 rule never applied: the model validator skips string
min and max. storePassword now refuses a typed password under 4
characters with a 422 on the field, next to the 72-byte check (D-11).
Found by TestAdministratorsPasswordAndIdentity.
This commit is contained in:
Jakub Zych
2026-10-22 12:00:18 +02:00
parent 536ea8c1bf
commit 461cb21b3e

View File

@@ -8,6 +8,7 @@ import (
"strconv"
"strings"
"time"
"unicode/utf8"
"git.golem15.com/golem15/summercms/modules/backpack"
"git.golem15.com/golem15/summercms/modules/bouncer"
@@ -841,13 +842,24 @@ func submittedPassword(ctx context.Context) string {
return plain
}
// adminPasswordMinChars is the shortest password the Administrators form
// accepts, in characters (D-11).
const adminPasswordMinChars = 4
// storePassword hashes a typed password onto user and reports whether one
// was typed. A password over bcrypt's 72-byte limit is a 422 on the field.
// was typed. A password under adminPasswordMinChars characters or over
// bcrypt's 72-byte limit is a 422 on the field. The length is checked here
// because the form's min:4 rule is a string rule, which the model validator
// does not apply.
func (c usersAdmin) storePassword(ctx context.Context, user *BackendUser) (bool, error) {
plain := submittedPassword(ctx)
if plain == "" {
return false, nil
}
if utf8.RuneCountInString(plain) < adminPasswordMinChars {
message := accountMessage(ctx, c.translator(), "min.string", "password", map[string]string{"min": strconv.Itoa(adminPasswordMinChars)})
return false, &ValidationError{Details: map[string]any{"password": []string{message}}}
}
if len(plain) > passwordMaxBytes {
message := accountMessage(ctx, c.translator(), "max.string", "password", map[string]string{"max": strconv.Itoa(passwordMaxBytes)})
return false, &ValidationError{Details: map[string]any{"password": []string{message}}}