fix(message validation): validate duplicated topics
Fixes https://emqx.atlassian.net/browse/EMQX-12254
This commit is contained in:
parent
1e64e531f0
commit
ffedce014f
|
@ -65,6 +65,7 @@ fields(validation) ->
|
||||||
#{
|
#{
|
||||||
desc => ?DESC("topics"),
|
desc => ?DESC("topics"),
|
||||||
converter => fun ensure_array/2,
|
converter => fun ensure_array/2,
|
||||||
|
validator => fun validate_unique_topics/1,
|
||||||
required => true
|
required => true
|
||||||
}
|
}
|
||||||
)},
|
)},
|
||||||
|
@ -269,3 +270,23 @@ do_validate_unique_schema_checks(
|
||||||
end;
|
end;
|
||||||
do_validate_unique_schema_checks([_Check | Rest], Seen, Duplicated) ->
|
do_validate_unique_schema_checks([_Check | Rest], Seen, Duplicated) ->
|
||||||
do_validate_unique_schema_checks(Rest, Seen, Duplicated).
|
do_validate_unique_schema_checks(Rest, Seen, Duplicated).
|
||||||
|
|
||||||
|
validate_unique_topics(Topics) ->
|
||||||
|
Grouped = maps:groups_from_list(
|
||||||
|
fun(T) -> T end,
|
||||||
|
Topics
|
||||||
|
),
|
||||||
|
DuplicatedMap = maps:filter(
|
||||||
|
fun(_T, Ts) -> length(Ts) > 1 end,
|
||||||
|
Grouped
|
||||||
|
),
|
||||||
|
case maps:keys(DuplicatedMap) of
|
||||||
|
[] ->
|
||||||
|
ok;
|
||||||
|
Duplicated ->
|
||||||
|
Msg = iolist_to_binary([
|
||||||
|
<<"duplicated topics: ">>,
|
||||||
|
lists:join(", ", Duplicated)
|
||||||
|
]),
|
||||||
|
{error, Msg}
|
||||||
|
end.
|
||||||
|
|
|
@ -232,6 +232,65 @@ check_test_() ->
|
||||||
|
|
||||||
duplicated_check_test_() ->
|
duplicated_check_test_() ->
|
||||||
[
|
[
|
||||||
|
{"duplicated topics 1",
|
||||||
|
?_assertThrow(
|
||||||
|
{_Schema, [
|
||||||
|
#{
|
||||||
|
reason := <<"duplicated topics: t/1">>,
|
||||||
|
kind := validation_error,
|
||||||
|
path := "message_validation.validations.1.topics"
|
||||||
|
}
|
||||||
|
]},
|
||||||
|
parse_and_check([
|
||||||
|
validation(
|
||||||
|
<<"foo">>,
|
||||||
|
[schema_check(json, <<"a">>)],
|
||||||
|
#{<<"topics">> => [<<"t/1">>, <<"t/1">>]}
|
||||||
|
)
|
||||||
|
])
|
||||||
|
)},
|
||||||
|
{"duplicated topics 2",
|
||||||
|
?_assertThrow(
|
||||||
|
{_Schema, [
|
||||||
|
#{
|
||||||
|
reason := <<"duplicated topics: t/1">>,
|
||||||
|
kind := validation_error,
|
||||||
|
path := "message_validation.validations.1.topics"
|
||||||
|
}
|
||||||
|
]},
|
||||||
|
parse_and_check([
|
||||||
|
validation(
|
||||||
|
<<"foo">>,
|
||||||
|
[schema_check(json, <<"a">>)],
|
||||||
|
#{<<"topics">> => [<<"t/1">>, <<"t/#">>, <<"t/1">>]}
|
||||||
|
)
|
||||||
|
])
|
||||||
|
)},
|
||||||
|
{"duplicated topics 3",
|
||||||
|
?_assertThrow(
|
||||||
|
{_Schema, [
|
||||||
|
#{
|
||||||
|
reason := <<"duplicated topics: t/1, t/2">>,
|
||||||
|
kind := validation_error,
|
||||||
|
path := "message_validation.validations.1.topics"
|
||||||
|
}
|
||||||
|
]},
|
||||||
|
parse_and_check([
|
||||||
|
validation(
|
||||||
|
<<"foo">>,
|
||||||
|
[schema_check(json, <<"a">>)],
|
||||||
|
#{
|
||||||
|
<<"topics">> => [
|
||||||
|
<<"t/1">>,
|
||||||
|
<<"t/#">>,
|
||||||
|
<<"t/1">>,
|
||||||
|
<<"t/2">>,
|
||||||
|
<<"t/2">>
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
])
|
||||||
|
)},
|
||||||
{"duplicated sql checks are not checked",
|
{"duplicated sql checks are not checked",
|
||||||
?_assertMatch(
|
?_assertMatch(
|
||||||
[#{<<"checks">> := [_, _]}],
|
[#{<<"checks">> := [_, _]}],
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Added a validation to prevent duplicated topics when configuring a message validation.
|
Loading…
Reference in New Issue