// Copyright (c) 2021 Gitpod GmbH. All rights reserved. // Licensed under the GNU Affero General Public License (AGPL). // See License.AGPL.txt in the project root for license information. package config import ( "encoding/json" "fmt" "io" "strings" "github.com/go-playground/validator/v10" ) type ValidationResult struct { Valid bool `json:"valid"` Warnings []string `json:"warn,omitempty"` Fatal []string `json:"fatal,omitempty"` } func Validate(version ConfigVersion, cfg interface{}) (r *ValidationResult, err error) { defer func() { if r != nil { r.Valid = len(r.Fatal) == 0 } }() validate := validator.New() err = version.LoadValidationFuncs(validate) if err != nil { return nil, err } var res ValidationResult warnings, conflicts := version.CheckDeprecated(cfg) for k, v := range warnings { res.Warnings = append(res.Warnings, fmt.Sprintf("Deprecated config parameter: %s=%v", k, v)) } res.Fatal = append(res.Fatal, conflicts...) err = validate.Struct(cfg) if err != nil { validationErrors := err.(validator.ValidationErrors) if len(validationErrors) > 0 { for _, v := range validationErrors { switch v.Tag() { case "required": res.Fatal = append(res.Fatal, fmt.Sprintf("Field '%s' is required", v.Namespace())) case "required_if", "required_unless", "required_with": tag := strings.Replace(v.Tag(), "_", " ", -1) res.Fatal = append(res.Fatal, fmt.Sprintf("Field '%s' is %s '%s'", v.Namespace(), tag, v.Param())) case "startswith": res.Fatal = append(res.Fatal, fmt.Sprintf("Field '%s' must start with '%s'", v.Namespace(), v.Param())) case "block_new_users_passlist": res.Fatal = append(res.Fatal, fmt.Sprintf("Field '%s' failed. If 'Enabled = true', there must be at least one fully-qualified domain name in the passlist", v.Namespace())) default: // General error message res.Fatal = append(res.Fatal, fmt.Sprintf("Field '%s' failed %s validation", v.Namespace(), v.Tag())) } } return &res, nil } } return &res, nil } // Marshal marshals this result to JSON func (r *ValidationResult) Marshal(w io.Writer) { enc := json.NewEncoder(w) enc.SetIndent("", " ") enc.Encode(r) }