github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/system/validation/validation.go (about)

     1  // This file is part of the Smart Home
     2  // Program complex distribution https://github.com/e154/smart-home
     3  // Copyright (C) 2016-2023, Filippov Alex
     4  //
     5  // This library is free software: you can redistribute it and/or
     6  // modify it under the terms of the GNU Lesser General Public
     7  // License as published by the Free Software Foundation; either
     8  // version 3 of the License, or (at your option) any later version.
     9  //
    10  // This library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13  // Library General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public
    16  // License along with this library.  If not, see
    17  // <https://www.gnu.org/licenses/>.
    18  
    19  package validation
    20  
    21  import (
    22  	"context"
    23  	"reflect"
    24  	"strings"
    25  
    26  	"github.com/go-playground/locales/en"
    27  	"github.com/go-playground/locales/ru"
    28  	ut "github.com/go-playground/universal-translator"
    29  	"github.com/go-playground/validator/v10"
    30  	en_translations "github.com/go-playground/validator/v10/translations/en"
    31  	"go.uber.org/fx"
    32  
    33  	"github.com/e154/smart-home/common/logger"
    34  	m "github.com/e154/smart-home/models"
    35  )
    36  
    37  var (
    38  	log = logger.MustGetLogger("validation")
    39  )
    40  
    41  // Validate ...
    42  type Validate struct {
    43  	validate *validator.Validate
    44  	trans    ut.Translator
    45  	config   *m.AppConfig
    46  	lang     string
    47  }
    48  
    49  // NewValidate ...
    50  func NewValidate(lc fx.Lifecycle,
    51  	config *m.AppConfig) (v *Validate) {
    52  	v = &Validate{
    53  		lang: config.Lang,
    54  	}
    55  
    56  	lc.Append(fx.Hook{
    57  		OnStart: func(ctx context.Context) error {
    58  			return v.Start(ctx)
    59  		},
    60  	})
    61  
    62  	return
    63  }
    64  
    65  // Start ...
    66  func (v *Validate) Start(_ context.Context) (err error) {
    67  
    68  	log.Info("start ...")
    69  
    70  	_en := en.New()
    71  	uni := ut.New(_en, _en, ru.New())
    72  
    73  	var ok bool
    74  	if v.trans, ok = uni.GetTranslator(v.lang); !ok {
    75  		v.trans, _ = uni.GetTranslator("en")
    76  	}
    77  
    78  	v.validate = validator.New()
    79  	v.validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
    80  		tag := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
    81  		if tag == "-" {
    82  			return ""
    83  		}
    84  		return tag
    85  	})
    86  
    87  	err = en_translations.RegisterDefaultTranslations(v.validate, v.trans)
    88  
    89  	return
    90  }
    91  
    92  // ValidVar ...
    93  func (v *Validate) ValidVar(s interface{}, key, tag string) (ok bool, errs validator.ValidationErrorsTranslations) {
    94  	err := v.validate.Var(s, tag)
    95  	if ok = err == nil; !ok {
    96  		if validationErrors, valid := err.(validator.ValidationErrors); valid {
    97  			errs = validationErrors.Translate(v.trans)
    98  			errs[key] = errs[""]
    99  			delete(errs, "")
   100  		}
   101  	}
   102  	return
   103  }
   104  
   105  // Valid ...
   106  func (v *Validate) Valid(s interface{}) (ok bool, errs validator.ValidationErrorsTranslations) {
   107  	err := v.validate.Struct(s)
   108  	if ok = err == nil; !ok {
   109  		if validationErrors, valid := err.(validator.ValidationErrors); valid {
   110  			errs = validationErrors.Translate(v.trans)
   111  		}
   112  		return
   113  	}
   114  	return
   115  }