package middleware import ( "fmt" "regexp" "github.com/go-playground/validator/v10" ) // PasswordValidator validates password complexity requirements type PasswordValidator struct{} // Validate checks if a password meets complexity requirements: // - Minimum 8 characters // - At least one uppercase letter // - At least one lowercase letter // - At least one number // - At least one special character func (v *PasswordValidator) Validate(fl validator.FieldLevel) bool { password := fl.Field().String() // Check minimum length if len(password) < 8 { return false } // Check for uppercase hasUpper := regexp.MustCompile(`[A-Z]`).MatchString(password) if !hasUpper { return false } // Check for lowercase hasLower := regexp.MustCompile(`[a-z]`).MatchString(password) if !hasLower { return false } // Check for number hasNumber := regexp.MustCompile(`[0-9]`).MatchString(password) if !hasNumber { return false } // Check for special character hasSpecial := regexp.MustCompile(`[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]`).MatchString(password) if !hasSpecial { return false } return true } // GetPasswordRequirements returns a human-readable list of password requirements func GetPasswordRequirements() []string { return []string{ "At least 8 characters long", "At least one uppercase letter (A-Z)", "At least one lowercase letter (a-z)", "At least one number (0-9)", "At least one special character (!@#$%^&*()_+-=[]{}|;':\",./<>?)", } } // ValidatePassword checks a password and returns an error if it doesn't meet requirements func ValidatePassword(password string) error { if len(password) < 8 { return fmt.Errorf("password must be at least 8 characters long") } if !regexp.MustCompile(`[A-Z]`).MatchString(password) { return fmt.Errorf("password must contain at least one uppercase letter") } if !regexp.MustCompile(`[a-z]`).MatchString(password) { return fmt.Errorf("password must contain at least one lowercase letter") } if !regexp.MustCompile(`[0-9]`).MatchString(password) { return fmt.Errorf("password must contain at least one number") } if !regexp.MustCompile(`[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]`).MatchString(password) { return fmt.Errorf("password must contain at least one special character") } return nil } // RegisterPasswordValidation registers the password validator with the validator instance func RegisterPasswordValidation(v *validator.Validate) error { return v.RegisterValidation("passwordcomplex", func(fl validator.FieldLevel) bool { pv := &PasswordValidator{} return pv.Validate(fl) }) }