Merge pull request #8512 from terry-xiaoyu/binary_file_validator

fix: add type binary_file to emqx_rule_validator
This commit is contained in:
Xinyu Liu 2022-07-20 21:17:28 +08:00 committed by GitHub
commit b30cc6a2a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 10 deletions

View File

@ -3,6 +3,7 @@
{VSN, {VSN,
[{"4.3.11", [{"4.3.11",
[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, [{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_validator,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}]},
{"4.3.10", {"4.3.10",
[{load_module,emqx_rule_validator,brutal_purge,soft_purge,[]}, [{load_module,emqx_rule_validator,brutal_purge,soft_purge,[]},
@ -165,6 +166,7 @@
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.3.11", [{"4.3.11",
[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, [{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_validator,brutal_purge,soft_purge,[]},
{load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}]}, {load_module,emqx_rule_engine_api,brutal_purge,soft_purge,[]}]},
{"4.3.10", {"4.3.10",
[{load_module,emqx_rule_validator,brutal_purge,soft_purge,[]}, [{load_module,emqx_rule_validator,brutal_purge,soft_purge,[]},

View File

@ -33,7 +33,7 @@
}. }.
-type data_type() :: string | password | number | boolean -type data_type() :: string | password | number | boolean
| object | array | file | cfgselect. | object | array | file | binary_file | cfgselect.
-type params_spec() :: #{name() => spec()} | any. -type params_spec() :: #{name() => spec()} | any.
-type params() :: #{binary() => term()}. -type params() :: #{binary() => term()}.
@ -46,6 +46,7 @@
, object , object
, array , array
, file , file
, binary_file
, cfgselect %% TODO: [5.0] refactor this , cfgselect %% TODO: [5.0] refactor this
]). ]).
@ -84,8 +85,8 @@ validate_spec(ParamsSepc) ->
%% Internal Functions %% Internal Functions
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------
validate_value(Val, #{type := Types} = Spec) when is_list(Types) -> validate_value(Val, #{type := Union} = Spec) when is_list(Union) ->
validate_types(Val, Types, Spec); validate_union(Val, Union, Spec);
validate_value(Val, #{enum := Enum}) -> validate_value(Val, #{enum := Enum}) ->
validate_enum(Val, Enum); validate_enum(Val, Enum);
validate_value(Val, #{type := object} = Spec) -> validate_value(Val, #{type := object} = Spec) ->
@ -93,17 +94,22 @@ validate_value(Val, #{type := object} = Spec) ->
validate_value(Val, #{type := Type} = Spec) -> validate_value(Val, #{type := Type} = Spec) ->
validate_type(Val, Type, Spec). validate_type(Val, Type, Spec).
validate_types(Val, [], _Spec) -> validate_union(Val, Union, _Spec) ->
throw({invalid_data_type, Val}); do_validate_union(Val, Union, Union, _Spec).
validate_types(Val, [Type | Types], Spec) ->
do_validate_union(Val, Union, [], _Spec) ->
throw({invalid_data_type, {union, {Val, Union}}});
do_validate_union(Val, Union, [Type | Types], Spec) ->
try try
validate_type(Val, Type, Spec) validate_type(Val, Type, Spec)
catch _:_ -> catch _:_ ->
validate_types(Val, Types, Spec) do_validate_union(Val, Union, Types, Spec)
end. end.
validate_type(Val, file, _Spec) -> validate_type(Val, file, _Spec) ->
validate_file(Val); validate_file(Val);
validate_type(Val, binary_file, _Spec) ->
validate_binary_file(Val);
validate_type(Val, String, Spec) when String =:= string; validate_type(Val, String, Spec) when String =:= string;
String =:= password -> String =:= password ->
validate_string(Val, reg_exp(maps:get(format, Spec, any))); validate_string(Val, reg_exp(maps:get(format, Spec, any)));
@ -118,6 +124,8 @@ validate_type(Val, cfgselect, _Spec) ->
%% TODO: [5.0] refactor this. %% TODO: [5.0] refactor this.
Val. Val.
validate_enum(Val, BoolEnum) when BoolEnum == [true, false]; BoolEnum == [false, true] ->
validate_boolean(Val);
validate_enum(Val, Enum) -> validate_enum(Val, Enum) ->
case lists:member(Val, Enum) of case lists:member(Val, Enum) of
true -> Val; true -> Val;
@ -147,6 +155,10 @@ validate_boolean(false) -> false;
validate_boolean(<<"false">>) -> false; validate_boolean(<<"false">>) -> false;
validate_boolean(Val) -> throw({invalid_data_type, {boolean, Val}}). validate_boolean(Val) -> throw({invalid_data_type, {boolean, Val}}).
validate_binary_file(#{<<"file">> := _, <<"filename">> := _} = Val) ->
Val;
validate_binary_file(Val) ->
throw({invalid_data_type, {binary_file, Val}}).
validate_file(Val) when is_map(Val) -> Val; validate_file(Val) when is_map(Val) -> Val;
validate_file(Val) when is_list(Val) -> Val; validate_file(Val) when is_list(Val) -> Val;
validate_file(Val) when is_binary(Val) -> Val; validate_file(Val) when is_binary(Val) -> Val;
@ -163,6 +175,14 @@ do_validate_spec(Name, #{type := object} = Spec) ->
fun (not_found) -> throw({required_field_missing, {schema, {in, Name}}}); fun (not_found) -> throw({required_field_missing, {schema, {in, Name}}});
(Schema) -> validate_spec(Schema) (Schema) -> validate_spec(Schema)
end); end);
do_validate_spec(Name, #{type := cfgselect} = Spec) ->
find_field(items, Spec,
fun (not_found) -> throw({required_field_missing, {items, {in, Name}}});
(Items) ->
maps:map(fun(_K, Schema) ->
validate_spec(Schema)
end, Items)
end);
do_validate_spec(Name, #{type := array} = Spec) -> do_validate_spec(Name, #{type := array} = Spec) ->
find_field(items, Spec, find_field(items, Spec,
fun (not_found) -> throw({required_field_missing, {items, {in, Name}}}); fun (not_found) -> throw({required_field_missing, {items, {in, Name}}});

View File

@ -70,6 +70,32 @@
} }
} }
}, },
type_cfgselect => #{
type => cfgselect,
enum => [<<"upload">>, <<"path">>],
default => <<"upload">>,
items =>
#{
upload =>
#{
kerberos_keytab =>
#{
order => 6,
type => binary_file,
default => #{file => <<"">>, filename => <<"no_keytab.key">>}
}
},
path =>
#{
kerberos_keytab_path =>
#{
order => 7,
type => string,
default => <<"">>
}
}
}
},
type_array => #{ type_array => #{
type => array, type => array,
required => true, required => true,
@ -88,7 +114,7 @@ t_validate_spec_the_complex(_) ->
t_validate_spec_invalid_1(_) -> t_validate_spec_invalid_1(_) ->
?assertThrow({required_field_missing, {type, _}}, ?assertThrow({required_field_missing, {type, _}},
emqx_rule_validator:validate_spec(#{ emqx_rule_validator:validate_spec(#{
type_enum_number => #{ a => #{
required => true required => true
} }
})). })).
@ -96,15 +122,23 @@ t_validate_spec_invalid_1(_) ->
t_validate_spec_invalid_2(_) -> t_validate_spec_invalid_2(_) ->
?assertThrow({required_field_missing, {schema, _}}, ?assertThrow({required_field_missing, {schema, _}},
emqx_rule_validator:validate_spec(#{ emqx_rule_validator:validate_spec(#{
type_enum_number => #{ a => #{
type => object type => object
} }
})). })).
t_validate_spec_invalid_2_1(_) ->
?assertThrow({required_field_missing, {items, _}},
emqx_rule_validator:validate_spec(#{
a => #{
type => cfgselect
}
})).
t_validate_spec_invalid_3(_) -> t_validate_spec_invalid_3(_) ->
?assertThrow({required_field_missing, {items, _}}, ?assertThrow({required_field_missing, {items, _}},
emqx_rule_validator:validate_spec(#{ emqx_rule_validator:validate_spec(#{
type_enum_number => #{ a => #{
type => array type => array
} }
})). })).
@ -162,6 +196,22 @@ t_validate_params_fill_default(_) ->
?assertMatch(#{<<"abc">> := 1, <<"eee">> := <<"hello">>}, ?assertMatch(#{<<"abc">> := 1, <<"eee">> := <<"hello">>},
emqx_rule_validator:validate_params(Params, Specs)). emqx_rule_validator:validate_params(Params, Specs)).
t_validate_params_binary_file(_) ->
Params = #{<<"kfile">> => #{<<"file">> => <<"foo">>, <<"filename">> => <<"foo.key">>}},
Specs = #{<<"kfile">> => #{
type => binary_file,
required => true
}},
?assertMatch(#{<<"kfile">> := #{<<"file">> := <<"foo">>, <<"filename">> := <<"foo.key">>}},
emqx_rule_validator:validate_params(Params, Specs)),
Params1 = #{<<"kfile">> => #{<<"file">> => <<"foo">>}},
Specs1 = #{<<"kfile">> => #{
type => binary_file,
required => true
}},
?assertThrow({invalid_data_type, {binary_file, #{<<"file">> := <<"foo">>}}},
emqx_rule_validator:validate_params(Params1, Specs1)).
t_validate_params_the_complex(_) -> t_validate_params_the_complex(_) ->
Params = #{ Params = #{
<<"string_required">> => <<"hello">>, <<"string_required">> => <<"hello">>,
@ -173,6 +223,8 @@ t_validate_params_the_complex(_) ->
<<"string_required">> => <<"hello2">>, <<"string_required">> => <<"hello2">>,
<<"type_number">> => 1.3 <<"type_number">> => 1.3
}, },
<<"type_cfgselect">> => <<"upload">>,
<<"kerberos_keytab">> => #{<<"file">> => <<"foo">>, <<"filename">> => <<"foo.key">>},
<<"type_array">> => [<<"ok">>, <<"no">>] <<"type_array">> => [<<"ok">>, <<"no">>]
}, },
?assertMatch( ?assertMatch(
@ -186,6 +238,8 @@ t_validate_params_the_complex(_) ->
<<"string_required">> := <<"hello2">>, <<"string_required">> := <<"hello2">>,
<<"type_number">> := 1.3 <<"type_number">> := 1.3
}, },
<<"kerberos_keytab">> := #{<<"file">> := <<"foo">>, <<"filename">> := <<"foo.key">>},
<<"type_cfgselect">> := <<"upload">>,
<<"type_array">> := [<<"ok">>, <<"no">>] <<"type_array">> := [<<"ok">>, <<"no">>]
}, },
emqx_rule_validator:validate_params(Params, ?VALID_SPEC)). emqx_rule_validator:validate_params(Params, ?VALID_SPEC)).