| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- // Package validator предоставляет кастомные валидаторы на базе go-playground/validator.
- // Реализованы валидации: uuid, slug, latitude, longitude, place_type, user_role,
- // currency, user_status, place_status, service_status, booking_status, datetime.
- // Экспортирует функции Validate (структуры) и ValidateVar (одно поле).
- package validator
- import (
- "regexp"
- "time"
- "github.com/go-playground/validator/v10"
- )
- var (
- validate *validator.Validate
- uuidRegex = regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)
- slugRegex = regexp.MustCompile(`^[a-z0-9-]+$`)
- currencyRegex = regexp.MustCompile(`^[A-Z]{3}$`)
- )
- func init() {
- validate = validator.New()
- // Custom validators
- _ = validate.RegisterValidation("uuid", validateUUID)
- _ = validate.RegisterValidation("slug", validateSlug)
- _ = validate.RegisterValidation("latitude", validateLatitude)
- _ = validate.RegisterValidation("longitude", validateLongitude)
- _ = validate.RegisterValidation("place_type", validatePlaceType)
- _ = validate.RegisterValidation("user_role", validateUserRole)
- _ = validate.RegisterValidation("currency", validateCurrency)
- _ = validate.RegisterValidation("user_status", validateUserStatus)
- _ = validate.RegisterValidation("place_status", validatePlaceStatus)
- _ = validate.RegisterValidation("service_status", validateServiceStatus)
- _ = validate.RegisterValidation("booking_status", validateBookingStatus)
- _ = validate.RegisterValidation("datetime", validateDateTime)
- }
- // Validate validates a struct and returns ValidationErrors if any
- func Validate(s interface{}) error {
- return validate.Struct(s)
- }
- // ValidateVar validates a single variable
- func ValidateVar(field interface{}, tag string) error {
- return validate.Var(field, tag)
- }
- // ValidationErrors — алиас для go-playground/validator.ValidationErrors.
- // Позволяет использовать errors.As в хендлерах для проверки ошибок валидации.
- type ValidationErrors = validator.ValidationErrors
- // Custom validators
- func validateUUID(fl validator.FieldLevel) bool {
- return uuidRegex.MatchString(fl.Field().String())
- }
- func validateSlug(fl validator.FieldLevel) bool {
- return slugRegex.MatchString(fl.Field().String())
- }
- func validateLatitude(fl validator.FieldLevel) bool {
- lat := fl.Field().Float()
- return lat >= -90 && lat <= 90
- }
- func validateLongitude(fl validator.FieldLevel) bool {
- lng := fl.Field().Float()
- return lng >= -180 && lng <= 180
- }
- func validatePlaceType(fl validator.FieldLevel) bool {
- v := fl.Field().String()
- return v == "place" || v == "studio"
- }
- func validateUserRole(fl validator.FieldLevel) bool {
- roles := map[string]bool{
- "customer": true, "landlord": true, "executor": true,
- "moderator": true, "superadmin": true,
- }
- return roles[fl.Field().String()]
- }
- func validateCurrency(fl validator.FieldLevel) bool {
- return currencyRegex.MatchString(fl.Field().String())
- }
- func validateUserStatus(fl validator.FieldLevel) bool {
- statuses := map[string]bool{"active": true, "banned": true, "pending_verification": true}
- return statuses[fl.Field().String()]
- }
- func validatePlaceStatus(fl validator.FieldLevel) bool {
- statuses := map[string]bool{
- "draft": true, "pending_moderation": true, "published": true,
- "rejected": true, "archived": true,
- }
- return statuses[fl.Field().String()]
- }
- func validateServiceStatus(fl validator.FieldLevel) bool {
- statuses := map[string]bool{"draft": true, "published": true, "archived": true}
- return statuses[fl.Field().String()]
- }
- func validateBookingStatus(fl validator.FieldLevel) bool {
- statuses := map[string]bool{"pending": true, "confirmed": true, "cancelled": true, "completed": true}
- return statuses[fl.Field().String()]
- }
- func validateDateTime(fl validator.FieldLevel) bool {
- _, err := time.Parse(time.RFC3339, fl.Field().String())
- return err == nil
- }
|