mirror of
https://github.com/hatchet-dev/hatchet.git
synced 2025-12-30 21:29:44 -06:00
119 lines
2.9 KiB
Go
119 lines
2.9 KiB
Go
package validator
|
|
|
|
import (
|
|
"encoding/json"
|
|
"regexp"
|
|
"time"
|
|
"unicode"
|
|
|
|
"github.com/Masterminds/semver/v3"
|
|
"github.com/go-playground/validator/v10"
|
|
"github.com/google/uuid"
|
|
"github.com/robfig/cron/v3"
|
|
|
|
"github.com/hatchet-dev/hatchet/internal/cel"
|
|
"github.com/hatchet-dev/hatchet/pkg/client/types"
|
|
)
|
|
|
|
var NameRegex = regexp.MustCompile("^[a-zA-Z0-9\\.\\-_]+$") //nolint:gosimple
|
|
|
|
func newValidator() *validator.Validate {
|
|
validate := validator.New()
|
|
|
|
celParser := cel.NewCELParser()
|
|
cronParser := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)
|
|
|
|
_ = validate.RegisterValidation("hatchetName", func(fl validator.FieldLevel) bool {
|
|
return NameRegex.MatchString(fl.Field().String())
|
|
})
|
|
|
|
_ = validate.RegisterValidation("password", func(fl validator.FieldLevel) bool {
|
|
return passwordValidation(fl.Field().String())
|
|
})
|
|
|
|
_ = validate.RegisterValidation("uuid", func(fl validator.FieldLevel) bool {
|
|
return IsValidUUID(fl.Field().String())
|
|
})
|
|
|
|
_ = validate.RegisterValidation("cron", func(fl validator.FieldLevel) bool {
|
|
_, err := cronParser.Parse(fl.Field().String())
|
|
|
|
return err == nil
|
|
})
|
|
|
|
_ = validate.RegisterValidation("actionId", func(fl validator.FieldLevel) bool {
|
|
action, err := types.ParseActionID(fl.Field().String())
|
|
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
return action.Service != "" && action.Verb != ""
|
|
})
|
|
|
|
_ = validate.RegisterValidation("semver", func(fl validator.FieldLevel) bool {
|
|
_, err := semver.NewVersion(fl.Field().String())
|
|
|
|
return err == nil
|
|
})
|
|
|
|
_ = validate.RegisterValidation("json", func(fl validator.FieldLevel) bool {
|
|
return isValidJSON(fl.Field().String())
|
|
})
|
|
|
|
_ = validate.RegisterValidation("duration", func(fl validator.FieldLevel) bool {
|
|
_, err := time.ParseDuration(fl.Field().String())
|
|
|
|
return err == nil
|
|
})
|
|
|
|
_ = validate.RegisterValidation("celworkflowrunstr", func(fl validator.FieldLevel) bool {
|
|
_, err := celParser.ParseWorkflowString(fl.Field().String())
|
|
|
|
return err == nil
|
|
})
|
|
|
|
_ = validate.RegisterValidation("celsteprunstr", func(fl validator.FieldLevel) bool {
|
|
_, err := celParser.ParseStepRun(fl.Field().String())
|
|
|
|
return err == nil
|
|
})
|
|
|
|
_ = validate.RegisterValidation("future", func(fl validator.FieldLevel) bool {
|
|
if t, ok := fl.Field().Interface().(time.Time); ok {
|
|
return t.After(time.Now())
|
|
}
|
|
return false
|
|
})
|
|
|
|
return validate
|
|
}
|
|
|
|
func passwordValidation(pw string) bool {
|
|
pwLen := len(pw)
|
|
var hasNumber, hasUpper, hasLower bool
|
|
|
|
for _, char := range pw {
|
|
switch {
|
|
case unicode.IsNumber(char):
|
|
hasNumber = true
|
|
case unicode.IsUpper(char):
|
|
hasUpper = true
|
|
case unicode.IsLower(char):
|
|
hasLower = true
|
|
}
|
|
}
|
|
|
|
return hasNumber && hasUpper && hasLower && pwLen >= 8 && pwLen <= 32
|
|
}
|
|
|
|
func IsValidUUID(u string) bool {
|
|
_, err := uuid.Parse(u)
|
|
return err == nil
|
|
}
|
|
|
|
func isValidJSON(s string) bool {
|
|
var js map[string]interface{}
|
|
return json.Unmarshal([]byte(s), &js) == nil
|
|
}
|