diff --git a/internal/validator/user.go b/internal/validator/user.go index a7e05edb5cc..53220148596 100644 --- a/internal/validator/user.go +++ b/internal/validator/user.go @@ -6,6 +6,7 @@ package validator // import "miniflux.app/v2/internal/validator" import ( "slices" "strings" + "unicode" "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" @@ -22,6 +23,10 @@ func ValidateUserCreationWithPassword(store *storage.Storage, request *model.Use return locale.NewLocalizedError("error.user_already_exists") } + if err := validateUsername(request.Username); err != nil { + return err + } + if err := validatePassword(request.Password); err != nil { return err } @@ -146,6 +151,23 @@ func validatePassword(password string) *locale.LocalizedError { return nil } +// validateUsername return an error if the `username` argument contains +// a character that isn't alphanumerical nor `_` and `-`. +func validateUsername(username string) *locale.LocalizedError { + if strings.ContainsFunc(username, func(r rune) bool { + if unicode.IsLetter(r) || unicode.IsNumber(r) { + return false + } + if r == '_' || r == '-' || r == '@' || r == '.' { + return false + } + return true + }) { + return locale.NewLocalizedError("error.invalid_username") + } + return nil +} + func validateTheme(theme string) *locale.LocalizedError { themes := model.Themes() if _, found := themes[theme]; !found { diff --git a/internal/validator/validator_test.go b/internal/validator/validator_test.go index 7121a111f99..cfa562c7c98 100644 --- a/internal/validator/validator_test.go +++ b/internal/validator/validator_test.go @@ -4,6 +4,7 @@ package validator // import "miniflux.app/v2/internal/validator" import "testing" +import "miniflux.app/v2/internal/locale" func TestIsValidURL(t *testing.T) { scenarios := map[string]bool{ @@ -77,3 +78,25 @@ func TestIsValidDomain(t *testing.T) { } } } + +func TestValidateUsername(t *testing.T) { + scenarios := map[string]*locale.LocalizedError{ + "jvoisin": nil, + "j.voisin": nil, + "j@vois.in": nil, + "invalid username": locale.NewLocalizedError("error.invalid_username"), + } + + for username, expected := range scenarios { + result := validateUsername(username) + if expected == nil { + if result != nil { + t.Errorf(`got an unexpected error for %q instead of nil: %v`, username, result) + } + } else { + if result == nil { + t.Errorf(`expected an error, got nil.`) + } + } + } +}