feat(backend): disallow some names due to potential confusion or potential errors

This commit is contained in:
sam 2023-08-10 18:26:53 +02:00
parent eba31f8bda
commit c92f4c4ba7
No known key found for this signature in database
GPG key ID: B4EF20DDE721CAA1
3 changed files with 38 additions and 8 deletions

View file

@ -3,6 +3,7 @@ package db
import ( import (
"context" "context"
"regexp" "regexp"
"strings"
"time" "time"
"emperror.dev/errors" "emperror.dev/errors"
@ -40,11 +41,19 @@ const (
// member names must match this regex // member names must match this regex
var memberNameRegex = regexp.MustCompile("^[^@\\?!#/\\\\[\\]\"\\{\\}'$%&()+<=>^|~`,]{1,100}$") var memberNameRegex = regexp.MustCompile("^[^@\\?!#/\\\\[\\]\"\\{\\}'$%&()+<=>^|~`,]{1,100}$")
// List of member names that cannot be used because they would break routing or be inaccessible due to page conflicts.
var invalidMemberNames = []string{
".",
"..",
"edit",
}
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. for i := range invalidMemberNames {
if name == "." || name == ".." { if strings.EqualFold(name, invalidMemberNames[i]) {
return false return false
} }
}
return memberNameRegex.MatchString(name) return memberNameRegex.MatchString(name)
} }

View file

@ -6,6 +6,7 @@ import (
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"regexp" "regexp"
"strings"
"time" "time"
"codeberg.org/pronounscc/pronouns.cc/backend/common" "codeberg.org/pronounscc/pronouns.cc/backend/common"
@ -138,12 +139,22 @@ const (
// 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) { // List of usernames that cannot be used, because they could create confusion, conflict with other pages, or cause bugs.
// This name would break routing, but periods should still be allowed in names otherwise. var invalidUsernames = []string{
if username == ".." { "..",
return ErrInvalidUsername "admin",
} "administrator",
"mod",
"moderator",
"api",
"page",
"pronouns",
"settings",
"pronouns.cc",
"pronounscc",
}
func UsernameValid(username string) (err error) {
if !usernameRegex.MatchString(username) { if !usernameRegex.MatchString(username) {
if len(username) < 2 { if len(username) < 2 {
return ErrUsernameTooShort return ErrUsernameTooShort
@ -153,6 +164,13 @@ func UsernameValid(username string) (err error) {
return ErrInvalidUsername return ErrInvalidUsername
} }
for i := range invalidUsernames {
if strings.EqualFold(username, invalidUsernames[i]) {
return ErrBannedUsername
}
}
return nil return nil
} }
@ -163,6 +181,7 @@ const (
ErrInvalidUsername = errors.Sentinel("username contains invalid characters") ErrInvalidUsername = errors.Sentinel("username contains invalid characters")
ErrUsernameTooShort = errors.Sentinel("username is too short") ErrUsernameTooShort = errors.Sentinel("username is too short")
ErrUsernameTooLong = errors.Sentinel("username is too long") ErrUsernameTooLong = errors.Sentinel("username is too long")
ErrBannedUsername = errors.Sentinel("username is banned")
) )
const ( const (

View file

@ -232,6 +232,8 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error {
return server.APIError{Code: server.ErrUsernameTaken} return server.APIError{Code: server.ErrUsernameTaken}
case db.ErrInvalidUsername: case db.ErrInvalidUsername:
return server.APIError{Code: server.ErrInvalidUsername} return server.APIError{Code: server.ErrInvalidUsername}
case db.ErrBannedUsername:
return server.APIError{Code: server.ErrInvalidUsername, Details: "That username cannot be used."}
default: default:
return errors.Wrap(err, "updating username") return errors.Wrap(err, "updating username")
} }