From e8a8416e44f2e0c810bfce3b2eb12608764ff594 Mon Sep 17 00:00:00 2001 From: Thales Macedo Garitezi Date: Mon, 18 Mar 2024 15:52:30 -0300 Subject: [PATCH] feat(message_validation): impose restrictions on validation name --- .../src/emqx_message_validation_schema.erl | 22 ++++++++++++++++- .../test/emqx_message_validation_tests.erl | 24 +++++++++++++++++++ rebar.config | 2 +- rel/i18n/emqx_message_validation_schema.hocon | 2 +- 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/apps/emqx_message_validation/src/emqx_message_validation_schema.erl b/apps/emqx_message_validation/src/emqx_message_validation_schema.erl index 998e11302..ce4f9265d 100644 --- a/apps/emqx_message_validation/src/emqx_message_validation_schema.erl +++ b/apps/emqx_message_validation/src/emqx_message_validation_schema.erl @@ -18,6 +18,8 @@ api_schema/1 ]). +-export([validate_name/1]). + %%------------------------------------------------------------------------------ %% Type declarations %%------------------------------------------------------------------------------ @@ -48,7 +50,15 @@ fields(validation) -> {tags, emqx_schema:tags_schema()}, {description, emqx_schema:description_schema()}, {enable, mk(boolean(), #{desc => ?DESC("config_enable"), default => true})}, - {name, mk(binary(), #{required => true, desc => ?DESC("name")})}, + {name, + mk( + binary(), + #{ + required => true, + validator => fun validate_name/1, + desc => ?DESC("name") + } + )}, {topics, mk( hoconsc:union([binary(), hoconsc:array(binary())]), @@ -186,6 +196,16 @@ ensure_array(undefined, _) -> undefined; ensure_array(L, _) when is_list(L) -> L; ensure_array(B, _) -> [B]. +validate_name(Name) -> + %% see `MAP_KEY_RE' in hocon_tconf + RE = <<"^[A-Za-z0-9]+[A-Za-z0-9-_]*$">>, + case re:run(Name, RE, [{capture, none}]) of + match -> + ok; + nomatch -> + {error, <<"must conform to regex: ", RE/binary>>} + end. + validate_sql(SQL) -> case emqx_message_validation:parse_sql_check(SQL) of {ok, _Parsed} -> diff --git a/apps/emqx_message_validation/test/emqx_message_validation_tests.erl b/apps/emqx_message_validation/test/emqx_message_validation_tests.erl index d57b8e4e8..a50922ca5 100644 --- a/apps/emqx_message_validation/test/emqx_message_validation_tests.erl +++ b/apps/emqx_message_validation/test/emqx_message_validation_tests.erl @@ -177,6 +177,30 @@ schema_test_() -> )} ]. +invalid_names_test_() -> + [ + {InvalidName, + ?_assertThrow( + {_Schema, [ + #{ + reason := <<"must conform to regex:", _/binary>>, + kind := validation_error, + path := "message_validation.validations.1.name" + } + ]}, + parse_and_check([validation(InvalidName, [sql_check()])]) + )} + || InvalidName <- [ + <<"">>, + <<"_name">>, + <<"name$">>, + <<"name!">>, + <<"some name">>, + <<"nãme"/utf8>>, + <<"test_哈哈"/utf8>> + ] + ]. + check_test_() -> [ {"denied by payload 1", diff --git a/rebar.config b/rebar.config index 3f58749bf..8f383a72e 100644 --- a/rebar.config +++ b/rebar.config @@ -129,7 +129,7 @@ emqx_exproto_pb ]}. -{eunit_opts, [verbose]}. +{eunit_opts, [verbose, {print_depth, 100}]}. {project_plugins, [ {erlfmt, "1.3.0"}, diff --git a/rel/i18n/emqx_message_validation_schema.hocon b/rel/i18n/emqx_message_validation_schema.hocon index bf1524cc1..be746368a 100644 --- a/rel/i18n/emqx_message_validation_schema.hocon +++ b/rel/i18n/emqx_message_validation_schema.hocon @@ -55,7 +55,7 @@ emqx_message_validation_schema { """Topic filter(s)""" name.desc: - """The name for this validation. Must be unique among all validations.""" + """The name for this validation. Must be unique among all validations. It must be a combination of alphanumeric characters and underscores, and cannot start with neither number nor an underscore.""" name.desc: """Name"""