package utils import ( "regexp" "strings" "github.com/go-playground/validator/v10" ) var validate *validator.Validate // InitValidator initializes the validator func InitValidator() { validate = validator.New() // Register custom validators validate.RegisterValidation("phone", validatePhone) validate.RegisterValidation("nrp", validateNRP) } // ValidateStruct validates a struct func ValidateStruct(s interface{}) error { if validate == nil { InitValidator() } return validate.Struct(s) } // validatePhone validates Indonesian phone numbers func validatePhone(fl validator.FieldLevel) bool { phone := fl.Field().String() if phone == "" { return true // Allow empty (use required tag separately) } // Remove spaces and dashes phone = strings.ReplaceAll(phone, " ", "") phone = strings.ReplaceAll(phone, "-", "") // Check if starts with 0 or +62 or 62 pattern := `^(0|\+?62)[0-9]{8,12}$` matched, _ := regexp.MatchString(pattern, phone) return matched } // validateNRP validates NRP (Nomor Registrasi Pokok) func validateNRP(fl validator.FieldLevel) bool { nrp := fl.Field().String() if nrp == "" { return true // Allow empty (use required tag separately) } // NRP format: 10 digits pattern := `^[0-9]{10}$` matched, _ := regexp.MatchString(pattern, nrp) return matched } // IsValidEmail checks if email is valid func IsValidEmail(email string) bool { pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` matched, _ := regexp.MatchString(pattern, email) return matched } // IsValidURL checks if URL is valid func IsValidURL(url string) bool { pattern := `^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(/.*)?$` matched, _ := regexp.MatchString(pattern, url) return matched } // SanitizeString removes potentially dangerous characters func SanitizeString(s string) string { // Remove control characters s = strings.Map(func(r rune) rune { if r < 32 && r != '\n' && r != '\r' && r != '\t' { return -1 } return r }, s) return strings.TrimSpace(s) }