make username case-insensitive
Marco Andronaco andronacomarco@gmail.com
Sat, 12 Oct 2024 23:35:14 +0200
2 files changed,
20 insertions(+),
12 deletions(-)
M
src/app/functions.go
→
src/app/functions.go
@@ -20,13 +20,16 @@ maxUsernameLength = 10
) var ( - validUsername = regexp.MustCompile(`^[a-z0-9._-]+$`) + validUsername = regexp.MustCompile(`(?i)^[a-z0-9._-]+$`) validEmail = regexp.MustCompile(`^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$`) ) -func sanitizeUsername(username string) (string, error) { - username = strings.ToLower(username) +func getUserByName(username string, excluding uint) (user User, err error) { + err = db.Model(&User{}).Where("upper(username) == upper(?) AND id != ?", username, excluding).First(&user).Error + return +} +func sanitizeUsername(username string) (string, error) { if !validUsername.MatchString(username) || len(username) < minUsernameLength || len(username) > maxUsernameLength { return "", errors.New("invalid username") }@@ -57,7 +60,7 @@ if err != nil {
http.Error(w, "Could not generate session cookie.", http.StatusInternalServerError) } - ks.Set(cookie.Value, userID, duration) + ks.Set("session:"+cookie.Value, userID, duration) http.SetCookie(w, cookie) }@@ -103,7 +106,7 @@ cookie, err := r.Cookie("session_token")
if err != nil { return } - return ks.Get(cookie.Value) + return ks.Get("session:" + cookie.Value) } // Middleware to check if the user is logged in
M
src/app/handlers.go
→
src/app/handlers.go
@@ -50,6 +50,12 @@ http.Error(w, "Invalid email.", http.StatusBadRequest)
return } + _, err = getUserByName(username, 0) + if err == nil { + http.Error(w, "This username is already registered.", http.StatusConflict) + return + } + hashedPassword, salt, err := g.HashPassword(r.FormValue("password")) if err != nil { http.Error(w, "Invalid password.", http.StatusBadRequest)@@ -65,7 +71,7 @@ }
db.Create(&user) if user.ID == 0 { - http.Error(w, "Username or email already exists.", http.StatusConflict) + http.Error(w, "This email is already registered.", http.StatusConflict) return }@@ -78,10 +84,9 @@ username := r.FormValue("username")
password := r.FormValue("password") remember := r.FormValue("remember") - var user User - db.Where("username = ?", username).First(&user) + user, err := getUserByName(username, 0) - if user.ID == 0 || !g.CheckPassword(password, user.Salt, user.PasswordHash) { + if err != nil || !g.CheckPassword(password, user.Salt, user.PasswordHash) { http.Error(w, "Invalid credentials", http.StatusUnauthorized) return }@@ -112,7 +117,7 @@ http.Error(w, "Could not generate reset token.", http.StatusInternalServerError)
return } - ks.Set(resetToken, user.ID, time.Hour) + ks.Set("reset:"+resetToken, user.ID, time.Hour) sendResetEmail(user.Email, resetToken) http.Redirect(w, r, "/login", http.StatusFound)@@ -121,7 +126,7 @@ }
func getResetPasswordConfirmHandler(w http.ResponseWriter, r *http.Request) { token := r.URL.Query().Get("token") - _, err := ks.Get(token) + _, err := ks.Get("reset:" + token) if err != nil { http.Error(w, "Token is invalid or expired.", http.StatusUnauthorized) return@@ -132,7 +137,7 @@ }
func postResetPasswordConfirmHandler(w http.ResponseWriter, r *http.Request) { token := r.URL.Query().Get("token") - userID, err := ks.Get(token) + userID, err := ks.Get("reset:" + token) if err != nil { http.Error(w, "Token is invalid or expired.", http.StatusUnauthorized) return