fix(backend): disallow '.' and '..' in user and member names

This commit is contained in:
Sam 2023-05-12 01:09:02 +02:00
parent 0e9ac347c0
commit 4f43e32fdb
No known key found for this signature in database
GPG key ID: B4EF20DDE721CAA1
2 changed files with 28 additions and 11 deletions

View file

@ -38,6 +38,11 @@ const (
var memberNameRegex = regexp.MustCompile("^[^@\\?!#/\\\\[\\]\"\\{\\}'$%&()+<=>^|~`,]{1,100}$") var memberNameRegex = regexp.MustCompile("^[^@\\?!#/\\\\[\\]\"\\{\\}'$%&()+<=>^|~`,]{1,100}$")
func MemberNameValid(name string) bool { func MemberNameValid(name string) bool {
// These two names will break routing, but periods should still be allowed in names otherwise.
if name == "." || name == ".." {
return false
}
return memberNameRegex.MatchString(name) return memberNameRegex.MatchString(name)
} }

View file

@ -113,6 +113,24 @@ func (u User) NumProviders() (numProviders int) {
// usernames must match this regex // usernames must match this regex
var usernameRegex = regexp.MustCompile(`^[\w-.]{2,40}$`) var usernameRegex = regexp.MustCompile(`^[\w-.]{2,40}$`)
func UsernameValid(username string) (err error) {
// This name would break routing, but periods should still be allowed in names otherwise.
if username == ".." {
return ErrInvalidUsername
}
if !usernameRegex.MatchString(username) {
if len(username) < 2 {
return ErrUsernameTooShort
} else if len(username) > 40 {
return ErrUsernameTooLong
}
return ErrInvalidUsername
}
return nil
}
const ( const (
ErrUserNotFound = errors.Sentinel("user not found") ErrUserNotFound = errors.Sentinel("user not found")
@ -139,14 +157,8 @@ const (
func (db *DB) CreateUser(ctx context.Context, tx pgx.Tx, username string) (u User, err error) { func (db *DB) CreateUser(ctx context.Context, tx pgx.Tx, username string) (u User, err error) {
// check if the username is valid // check if the username is valid
// if not, return an error depending on what failed // if not, return an error depending on what failed
if !usernameRegex.MatchString(username) { if err := UsernameValid(username); err != nil {
if len(username) < 2 { return u, err
return u, ErrUsernameTooShort
} else if len(username) > 40 {
return u, ErrUsernameTooLong
}
return u, ErrInvalidUsername
} }
sql, args, err := sq.Insert("users").Columns("id", "username").Values(xid.New(), username).Suffix("RETURNING *").ToSql() sql, args, err := sq.Insert("users").Columns("id", "username").Values(xid.New(), username).Suffix("RETURNING *").ToSql()
@ -458,7 +470,7 @@ func (db *DB) Username(ctx context.Context, name string) (u User, err error) {
// UsernameTaken checks if the given username is already taken. // UsernameTaken checks if the given username is already taken.
func (db *DB) UsernameTaken(ctx context.Context, username string) (valid, taken bool, err error) { func (db *DB) UsernameTaken(ctx context.Context, username string) (valid, taken bool, err error) {
if !usernameRegex.MatchString(username) { if err := UsernameValid(username); err != nil {
return false, false, nil return false, false, nil
} }
@ -468,8 +480,8 @@ func (db *DB) UsernameTaken(ctx context.Context, username string) (valid, taken
// UpdateUsername validates the given username, then updates the given user's name to it if valid. // UpdateUsername validates the given username, then updates the given user's name to it if valid.
func (db *DB) UpdateUsername(ctx context.Context, tx pgx.Tx, id xid.ID, newName string) error { func (db *DB) UpdateUsername(ctx context.Context, tx pgx.Tx, id xid.ID, newName string) error {
if !usernameRegex.MatchString(newName) { if err := UsernameValid(newName); err != nil {
return ErrInvalidUsername return err
} }
sql, args, err := sq.Update("users").Set("username", newName).Where("id = ?", id).ToSql() sql, args, err := sq.Update("users").Set("username", newName).Where("id = ?", id).ToSql()