diff --git a/apps/emqx_gateway_jt808/src/emqx_jt808_schema.erl b/apps/emqx_gateway_jt808/src/emqx_jt808_schema.erl index 70e9753bd..3e0c31f5d 100644 --- a/apps/emqx_gateway_jt808/src/emqx_jt808_schema.erl +++ b/apps/emqx_gateway_jt808/src/emqx_jt808_schema.erl @@ -62,13 +62,32 @@ fields(anonymous_true) -> [ {allow_anonymous, sc(hoconsc:union([true]), #{desc => ?DESC(allow_anonymous), required => true})} - ]; + ] ++ fields_reg_auth_required(false); fields(anonymous_false) -> [ {allow_anonymous, - sc(hoconsc:union([false]), #{desc => ?DESC(allow_anonymous), required => true})}, - {registry, fun registry_url/1}, - {authentication, fun authentication_url/1} + sc(hoconsc:union([false]), #{desc => ?DESC(allow_anonymous), required => true})} + ] ++ fields_reg_auth_required(true). + +fields_reg_auth_required(Required) -> + [ + {registry, + sc(binary(), #{ + desc => ?DESC(registry_url), + validator => [?NOT_EMPTY("the value of the field 'registry' cannot be empty")], + required => Required + })}, + {authentication, + sc( + binary(), + #{ + desc => ?DESC(authentication_url), + validator => [ + ?NOT_EMPTY("the value of the field 'authentication' cannot be empty") + ], + required => Required + } + )} ]. jt808_frame_max_length(type) -> @@ -82,18 +101,6 @@ jt808_frame_max_length(required) -> jt808_frame_max_length(_) -> undefined. -registry_url(type) -> binary(); -registry_url(desc) -> ?DESC(?FUNCTION_NAME); -registry_url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")]; -registry_url(required) -> false; -registry_url(_) -> undefined. - -authentication_url(type) -> binary(); -authentication_url(desc) -> ?DESC(?FUNCTION_NAME); -authentication_url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")]; -authentication_url(required) -> false; -authentication_url(_) -> undefined. - up_topic(type) -> binary(); up_topic(desc) -> ?DESC(?FUNCTION_NAME); up_topic(default) -> ?DEFAULT_UP_TOPIC; diff --git a/apps/emqx_gateway_jt808/test/emqx_jt808_SUITE.erl b/apps/emqx_gateway_jt808/test/emqx_jt808_SUITE.erl index 8644fe66f..20aae1acb 100644 --- a/apps/emqx_gateway_jt808/test/emqx_jt808_SUITE.erl +++ b/apps/emqx_gateway_jt808/test/emqx_jt808_SUITE.erl @@ -62,7 +62,7 @@ gateway.jt808 { } proto { auth { - allow_anonymous = true + allow_anonymous = true } } } @@ -80,6 +80,12 @@ end_per_suite(_Config) -> init_per_testcase(Case = t_case02_anonymous_register_and_auth, Config) -> Apps = boot_apps(Case, ?CONF_ANONYMOUS, Config), [{suite_apps, Apps} | Config]; +init_per_testcase(Case, Config) when + Case =:= t_create_ALLOW_invalid_auth_config; + Case =:= t_create_DISALLOW_invalid_auth_config +-> + Apps = boot_apps(Case, <<>>, Config), + [{suite_apps, Apps} | Config]; init_per_testcase(Case, Config) -> Apps = boot_apps(Case, ?CONF_DEFAULT, Config), [{suite_apps, Apps} | Config]. @@ -2677,3 +2683,74 @@ t_case34_dl_0x8805_single_mm_data_ctrl(_Config) -> {error, timeout} = gen_tcp:recv(Socket, 0, 500), ok = gen_tcp:close(Socket). + +t_create_ALLOW_invalid_auth_config(_Config) -> + test_invalid_config(create, true). + +t_create_DISALLOW_invalid_auth_config(_Config) -> + test_invalid_config(create, false). + +t_update_ALLOW_invalid_auth_config(_Config) -> + test_invalid_config(update, true). + +t_update_DISALLOW_invalid_auth_config(_Config) -> + test_invalid_config(update, false). + +test_invalid_config(CreateOrUpdate, AnonymousAllowed) -> + InvalidConfig = raw_jt808_config(AnonymousAllowed), + UpdateResult = create_or_update(CreateOrUpdate, InvalidConfig), + ?assertMatch( + {error, #{ + kind := validation_error, + reason := matched_no_union_member, + path := "gateway.jt808.proto.auth" + }}, + UpdateResult + ). + +create_or_update(create, InvalidConfig) -> + emqx_gateway_conf:load_gateway(jt808, InvalidConfig); +create_or_update(update, InvalidConfig) -> + emqx_gateway_conf:update_gateway(jt808, InvalidConfig). + +%% Allow: allow anonymous connection, registry and authentication URL not required. +raw_jt808_config(Allow = true) -> + AuthConfig = #{ + <<"auth">> => #{ + <<"allow_anonymous">> => Allow, + %% registry and authentication `NOT REQUIRED`, but can be configured + <<"registry">> => <>, + <<"authentication">> => <>, + <<"BADKEY_registry_url">> => <> + } + }, + emqx_utils_maps:deep_merge(raw_jt808_config(), #{<<"proto">> => AuthConfig}); +%% DisAllow: required registry and authentication URL configuration to auth client. +raw_jt808_config(DisAllow = false) -> + AuthConfig = #{ + <<"auth">> => #{ + <<"allow_anonymous">> => DisAllow + %% registry and authentication are required but missed here + %% + %% <<"registry">> => <>, + %% <<"authentication">> => <> + } + }, + emqx_utils_maps:deep_merge(raw_jt808_config(), #{<<"proto">> => AuthConfig}). + +raw_jt808_config() -> + #{ + <<"enable">> => true, + <<"enable_stats">> => true, + <<"frame">> => #{<<"max_length">> => 8192}, + <<"idle_timeout">> => <<"30s">>, + <<"max_retry_times">> => 3, + <<"message_queue_len">> => 10, + <<"mountpoint">> => <<"jt808/${clientid}/">>, + <<"proto">> => + #{ + <<"dn_topic">> => <<"jt808/${clientid}/${phone}/dn">>, + <<"up_topic">> => <<"jt808/${clientid}/${phone}/up">> + }, + <<"retry_interval">> => <<"8s">> + }.