package validation import ( "math" "reflect" "strings" ) type Error struct { Message string } func (e Error) Error() string { return e.Message } func (e Error) SetMessage(message string) Error { e.Message = message return e } var ErrBadRequest = Error{Message: "Bad Request"} // ExistKey checks if a key exists in the map func ExistKey(key string, mapItem map[string]interface{}, message string) error { var ok bool if _, ok = mapItem[key]; !ok { return ErrBadRequest.SetMessage(message) } return nil } // NotBlank checks if a value is not blank (not nil, not empty string, not empty slice) func NotBlank(key string, mapItem map[string]interface{}, message string) error { if v, ok := mapItem[key]; ok { // Check for nil value if v == nil { return ErrBadRequest.SetMessage(message) } // Check for empty string if str, isString := v.(string); isString && str == "" { return ErrBadRequest.SetMessage(message) } // Check for empty slice if arr, isSlice := v.([]interface{}); isSlice && len(arr) == 0 { return ErrBadRequest.SetMessage(message) } } return nil } // IsString checks if a value is a string type func IsString(key string, mapItem map[string]interface{}, message string) error { if str, ok := mapItem[key]; ok { if reflect.TypeOf(str).Kind() != reflect.String { return ErrBadRequest.SetMessage(message) } } return nil } // IsInt checks if a value is a valid integer (float64 that can be converted to int) func IsInt(key string, mapItem map[string]interface{}, message string) error { if i, ok := mapItem[key]; ok { if val, okFloat := i.(float64); okFloat { if val != float64(int(val)) || val > float64(math.MaxUint32) { return ErrBadRequest.SetMessage(message) } } else { return ErrBadRequest.SetMessage(message) } } return nil } // IsFloat64 checks if a value is a float64 type func IsFloat64(key string, mapItem map[string]interface{}, message string) error { if i, ok := mapItem[key]; ok { if _, okFloat := i.(float64); !okFloat { return ErrBadRequest.SetMessage(message) } } return nil } // IsBool checks if a value is a boolean type func IsBool(key string, mapItem map[string]interface{}, message string) error { if b, ok := mapItem[key]; ok { if reflect.TypeOf(b).Kind() != reflect.Bool { return ErrBadRequest.SetMessage(message) } } return nil } // AtLeastOneFieldMustBePresent checks if at least one of the specified fields is present func AtLeastOneFieldMustBePresent(keys string, mapItem map[string]interface{}, message string) error { keySlice := strings.Split(keys, ",") for _, k := range keySlice { if _, ok := mapItem[k]; ok { return nil } } return ErrBadRequest.SetMessage(message) } // UnexpectedField checks if there are any unexpected fields in the map func UnexpectedField(keys string, mapItem map[string]interface{}, message string) error { keySlice := strings.Split(keys, ",") keySet := make(map[string]bool) for _, key := range keySlice { keySet[key] = true } for k := range mapItem { if ok := keySet[k]; !ok { return ErrBadRequest.SetMessage(message) } } return nil } // MaxRange checks if a numeric value is not greater than the maximum func MaxRange(key string, max int, mapItem map[string]interface{}, message string) error { if val, ok := mapItem[key]; ok { if i, okInt := val.(float64); okInt && i > float64(max) { return ErrBadRequest.SetMessage(message) } } return nil } // MinRange checks if a numeric value is not less than the minimum func MinRange(key string, min int, mapItem map[string]interface{}, message string) error { if val, ok := mapItem[key]; ok { if i, okInt := val.(float64); okInt && i < float64(min) { return ErrBadRequest.SetMessage(message) } } return nil } // Contains checks if a value is present in a slice func Contains(limitedSoftwareTypes []int, currentSoftwareType int) bool { for _, v := range limitedSoftwareTypes { if v == currentSoftwareType { return true } } return false }