mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
137 lines
3.8 KiB
Go
137 lines
3.8 KiB
Go
package validation
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// ValidateUsername checks if a username meets requirements
|
|
func ValidateUsername(username string) error {
|
|
u := strings.TrimSpace(username)
|
|
if u == "" {
|
|
return errors.New("username cannot be empty")
|
|
}
|
|
if len(u) < 3 {
|
|
return errors.New("username must be at least 3 characters")
|
|
}
|
|
if len(u) > 32 {
|
|
return errors.New("username cannot exceed 32 characters")
|
|
}
|
|
// Only allow lowercase letters, numbers, hyphen, underscore, dot
|
|
validUsername := regexp.MustCompile(`^[a-z0-9\-_.]+$`)
|
|
if !validUsername.MatchString(u) {
|
|
return errors.New("username can only contain lowercase letters, numbers, and characters: - _ .")
|
|
}
|
|
// Prevent consecutive special chars
|
|
if strings.Contains(u, "--") || strings.Contains(u, "__") || strings.Contains(u, "..") {
|
|
return errors.New("username cannot contain consecutive special characters")
|
|
}
|
|
// Cannot start or end with special chars
|
|
if strings.HasPrefix(u, "-") || strings.HasPrefix(u, "_") || strings.HasPrefix(u, ".") ||
|
|
strings.HasSuffix(u, "-") || strings.HasSuffix(u, "_") || strings.HasSuffix(u, ".") {
|
|
return errors.New("username cannot start or end with special characters")
|
|
}
|
|
// Prevent reserved words
|
|
reserved := []string{"admin", "administrator", "mod", "moderator", "root", "system", "support", "official", "bot"}
|
|
for _, r := range reserved {
|
|
if strings.EqualFold(u, r) {
|
|
return errors.New("username is reserved")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SanitizeRewardName cleans and validates reward names
|
|
func SanitizeRewardName(name string) (string, error) {
|
|
n := strings.TrimSpace(name)
|
|
if n == "" {
|
|
return "", errors.New("reward name cannot be empty")
|
|
}
|
|
if len(n) > 255 {
|
|
return "", errors.New("reward name too long (max 255 characters)")
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
// ValidateRewardType ensures reward type is allowed
|
|
func ValidateRewardType(rewardType string) error {
|
|
allowed := map[string]bool{
|
|
"avatar_static": true,
|
|
"avatar_animated": true,
|
|
"avatar_upload_unlock": true,
|
|
"merch_coupon": true,
|
|
"merch_physical": true,
|
|
"merch_digital": true,
|
|
"custom": true,
|
|
}
|
|
if !allowed[rewardType] {
|
|
return errors.New("invalid reward type")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ValidatePoints checks if points value is reasonable
|
|
func ValidatePoints(points int64) error {
|
|
if points < 0 {
|
|
return errors.New("points cannot be negative")
|
|
}
|
|
if points > 1000000 {
|
|
return errors.New("points value too large (max 1,000,000)")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ValidateXP checks if XP value is reasonable
|
|
func ValidateXP(xp int64) error {
|
|
if xp < 0 {
|
|
return errors.New("XP cannot be negative")
|
|
}
|
|
if xp > 10000000 {
|
|
return errors.New("XP value too large (max 10,000,000)")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ValidateRewardStock checks stock value
|
|
func ValidateRewardStock(stock int) error {
|
|
if stock < -1 {
|
|
return errors.New("stock cannot be less than -1 (use -1 for unlimited)")
|
|
}
|
|
if stock > 100000 {
|
|
return errors.New("stock value too large (max 100,000)")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ValidateAchievementCode checks achievement code format
|
|
func ValidateAchievementCode(code string) error {
|
|
c := strings.TrimSpace(code)
|
|
if c == "" {
|
|
return errors.New("achievement code cannot be empty")
|
|
}
|
|
if len(c) > 64 {
|
|
return errors.New("achievement code too long (max 64 characters)")
|
|
}
|
|
// Only alphanumeric and underscore
|
|
validCode := regexp.MustCompile(`^[a-z0-9_]+$`)
|
|
if !validCode.MatchString(c) {
|
|
return errors.New("achievement code can only contain lowercase letters, numbers, and underscores")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ValidateRedemptionStatus checks if redemption status is valid
|
|
func ValidateRedemptionStatus(status string) error {
|
|
allowed := map[string]bool{
|
|
"pending": true,
|
|
"approved": true,
|
|
"rejected": true,
|
|
"fulfilled": true,
|
|
}
|
|
if !allowed[status] {
|
|
return errors.New("invalid redemption status")
|
|
}
|
|
return nil
|
|
}
|