From cba9b5c408461972f39ea74e89f042e21e7f4a60 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Tue, 17 Feb 2026 16:14:01 -0800 Subject: [PATCH] Add password complexity requirements Require at least one uppercase letter, one lowercase letter, and one digit in addition to the existing 8-character minimum. Fixes #31 Co-Authored-By: Claude Opus 4.6 --- internal/handlers/public/auth.go | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/internal/handlers/public/auth.go b/internal/handlers/public/auth.go index d61a06b..6a245b1 100644 --- a/internal/handlers/public/auth.go +++ b/internal/handlers/public/auth.go @@ -4,6 +4,7 @@ import ( "net/http" "net/url" "strings" + "unicode" "github.com/gin-gonic/gin" "github.com/mattnite/forgejo-tickets/internal/auth" @@ -11,6 +12,28 @@ import ( "github.com/rs/zerolog/log" ) +// validatePassword checks password complexity requirements. +func validatePassword(password string) string { + if len(password) < 8 { + return "Password must be at least 8 characters" + } + var hasUpper, hasLower, hasDigit bool + for _, r := range password { + switch { + case unicode.IsUpper(r): + hasUpper = true + case unicode.IsLower(r): + hasLower = true + case unicode.IsDigit(r): + hasDigit = true + } + } + if !hasUpper || !hasLower || !hasDigit { + return "Password must contain at least one uppercase letter, one lowercase letter, and one digit" + } + return "" +} + type AuthHandler struct { deps Dependencies } @@ -85,8 +108,8 @@ func (h *AuthHandler) Register(c *gin.Context) { return } - if len(password) < 8 { - data["Error"] = "Password must be at least 8 characters" + if errMsg := validatePassword(password); errMsg != "" { + data["Error"] = errMsg h.deps.Renderer.Render(c.Writer, c.Request, "register", data) return } @@ -189,10 +212,10 @@ func (h *AuthHandler) ResetPassword(c *gin.Context) { return } - if len(password) < 8 { + if errMsg := validatePassword(password); errMsg != "" { h.deps.Renderer.Render(c.Writer, c.Request, "reset-password", map[string]interface{}{ "Token": token, - "Error": "Password must be at least 8 characters", + "Error": errMsg, }) return }