add validation
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -111,3 +113,99 @@ func ValidateLeaf(cmd any) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Валидация путей.
|
||||
// Принимает на вход объект и при наличии метода Enabled производит валидацию
|
||||
func ValidatePath(cmd any) error {
|
||||
switch v := cmd.(type) {
|
||||
case interface{ Enabled() error }:
|
||||
return v.Enabled()
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Проверяет, что у команды с output-блоками включён хотя бы один вывод.
|
||||
func ValidateOutput(cmd any) error {
|
||||
if cmd == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(cmd)
|
||||
if v.Kind() == reflect.Pointer {
|
||||
if v.IsNil() {
|
||||
return nil
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Struct {
|
||||
return nil
|
||||
}
|
||||
|
||||
var hasOutputBlocks bool
|
||||
var hasEnabledOutput bool
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Field(i)
|
||||
fieldType := v.Type().Field(i)
|
||||
|
||||
switch fieldType.Type {
|
||||
case reflect.TypeOf(CSVOutput{}):
|
||||
hasOutputBlocks = true
|
||||
if enabled, ok := callEnabled(field); ok && enabled {
|
||||
hasEnabledOutput = true
|
||||
}
|
||||
|
||||
case reflect.TypeOf(JSONOutput{}):
|
||||
hasOutputBlocks = true
|
||||
if enabled, ok := callEnabled(field); ok && enabled {
|
||||
hasEnabledOutput = true
|
||||
}
|
||||
|
||||
case reflect.TypeOf(BodyOutput{}):
|
||||
hasOutputBlocks = true
|
||||
if enabled, ok := callEnabled(field); ok && enabled {
|
||||
hasEnabledOutput = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if hasOutputBlocks && !hasEnabledOutput {
|
||||
return errors.New("you must specify at least one output path: --csv, --json or --body")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Вызов Enabled у поля
|
||||
// Возвращает результат Enabled() и флаг успешности поиска метода
|
||||
func callEnabled(v reflect.Value) (bool, bool) {
|
||||
if !v.IsValid() {
|
||||
return false, false
|
||||
}
|
||||
|
||||
// Пробуем метод у самого значения
|
||||
if method := v.MethodByName("Enabled"); method.IsValid() {
|
||||
if method.Type().NumIn() == 0 &&
|
||||
method.Type().NumOut() == 1 &&
|
||||
method.Type().Out(0).Kind() == reflect.Bool {
|
||||
out := method.Call(nil)
|
||||
return out[0].Bool(), true
|
||||
}
|
||||
}
|
||||
|
||||
// Пробуем метод у указателя
|
||||
if v.CanAddr() {
|
||||
if method := v.Addr().MethodByName("Enabled"); method.IsValid() {
|
||||
if method.Type().NumIn() == 0 &&
|
||||
method.Type().NumOut() == 1 &&
|
||||
method.Type().Out(0).Kind() == reflect.Bool {
|
||||
out := method.Call(nil)
|
||||
return out[0].Bool(), true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false, false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user