From 93dd7d46c554373d84c13a0f9a5f75b479a24d4d Mon Sep 17 00:00:00 2001 From: JimMoen Date: Fri, 8 Apr 2022 16:39:35 +0800 Subject: [PATCH 1/8] refactor: fields `meta` ref to dashboard_swagger --- apps/emqx_authn/src/emqx_authn_api.erl | 12 +++--------- apps/emqx_authz/src/emqx_authz_api_mnesia.erl | 10 +++------- apps/emqx_dashboard/src/emqx_dashboard_swagger.erl | 7 ++++++- apps/emqx_management/src/emqx_mgmt_api_alarms.erl | 9 +++------ apps/emqx_management/src/emqx_mgmt_api_banned.erl | 8 ++------ apps/emqx_management/src/emqx_mgmt_api_clients.erl | 8 ++------ apps/emqx_management/src/emqx_mgmt_api_topics.erl | 8 ++------ 7 files changed, 21 insertions(+), 41 deletions(-) diff --git a/apps/emqx_authn/src/emqx_authn_api.erl b/apps/emqx_authn/src/emqx_authn_api.erl index 878e879ed..d1d8cbc6a 100644 --- a/apps/emqx_authn/src/emqx_authn_api.erl +++ b/apps/emqx_authn/src/emqx_authn_api.erl @@ -24,7 +24,7 @@ -include_lib("emqx/include/logger.hrl"). -include_lib("emqx/include/emqx_authentication.hrl"). --import(hoconsc, [mk/2, ref/1]). +-import(hoconsc, [mk/2, ref/1, ref/2]). -import(emqx_dashboard_swagger, [error_codes/2]). -define(BAD_REQUEST, 'BAD_REQUEST'). @@ -146,13 +146,7 @@ fields(response_user) -> {is_superuser, mk(boolean(), #{default => false, required => false})} ]; fields(response_users) -> - paginated_list_type(ref(response_user)); -fields(pagination_meta) -> - [ - {page, pos_integer()}, - {limit, pos_integer()}, - {count, non_neg_integer()} - ]. + paginated_list_type(ref(response_user)). schema("/authentication") -> #{ @@ -1316,7 +1310,7 @@ binfmt(Fmt, Args) -> iolist_to_binary(io_lib:format(Fmt, Args)). paginated_list_type(Type) -> [ {data, hoconsc:array(Type)}, - {meta, ref(pagination_meta)} + {meta, ref(emqx_dashboard_swagger, meta)} ]. authenticator_array_example() -> diff --git a/apps/emqx_authz/src/emqx_authz_api_mnesia.erl b/apps/emqx_authz/src/emqx_authz_api_mnesia.erl index dcdcf6878..addb11584 100644 --- a/apps/emqx_authz/src/emqx_authz_api_mnesia.erl +++ b/apps/emqx_authz/src/emqx_authz_api_mnesia.erl @@ -383,7 +383,7 @@ fields(rules_for_username) -> fields(username_response_data) -> [ {data, mk(array(ref(rules_for_username)), #{})}, - {meta, ref(meta)} + {meta, ref(emqx_dashboard_swagger, meta)} ]; fields(rules_for_clientid) -> fields(rules) ++ @@ -391,14 +391,10 @@ fields(rules_for_clientid) -> fields(clientid_response_data) -> [ {data, mk(array(ref(rules_for_clientid)), #{})}, - {meta, ref(meta)} + {meta, ref(emqx_dashboard_swagger, meta)} ]; fields(rules) -> - [{rules, mk(array(ref(rule_item)))}]; -fields(meta) -> - emqx_dashboard_swagger:fields(page) ++ - emqx_dashboard_swagger:fields(limit) ++ - [{count, mk(integer(), #{example => 1})}]. + [{rules, mk(array(ref(rule_item)))}]. %%-------------------------------------------------------------------- %% HTTP API diff --git a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl index a6a2d1bc4..72a1aeb2a 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl @@ -135,7 +135,12 @@ fields(limit) -> <<")">> ]), Meta = #{in => query, desc => Desc, default => ?DEFAULT_ROW, example => 50}, - [{limit, hoconsc:mk(range(1, ?MAX_ROW_LIMIT), Meta)}]. + [{limit, hoconsc:mk(range(1, ?MAX_ROW_LIMIT), Meta)}]; +fields(count) -> + Meta = #{desc => <<"Results count.">>, required => true}, + [{count, hoconsc:mk(range(0, inf), Meta)}]; +fields(meta) -> + fields(page) ++ fields(limit) ++ fields(count). -spec schema_with_example(hocon_schema:type(), term()) -> hocon_schema:field_schema_map(). schema_with_example(Type, Example) -> diff --git a/apps/emqx_management/src/emqx_mgmt_api_alarms.erl b/apps/emqx_management/src/emqx_mgmt_api_alarms.erl index 5c455b4e4..cc9b073b1 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_alarms.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_alarms.erl @@ -53,7 +53,7 @@ schema("/alarms") -> responses => #{ 200 => [ {data, hoconsc:mk(hoconsc:array(hoconsc:ref(?MODULE, alarm)), #{})}, - {meta, hoconsc:mk(hoconsc:ref(?MODULE, meta), #{})} + {meta, hoconsc:mk(hoconsc:ref(emqx_dashboard_swagger, meta), #{})} ] } }, @@ -98,11 +98,8 @@ fields(alarm) -> desc => ?DESC(deactivate_at), example => <<"2021-10-31T10:52:52.548+08:00">> })} - ]; -fields(meta) -> - emqx_dashboard_swagger:fields(page) ++ - emqx_dashboard_swagger:fields(limit) ++ - [{count, hoconsc:mk(integer(), #{example => 1})}]. + ]. + %%%============================================================================================== %% parameters trans alarms(get, #{query_string := QString}) -> diff --git a/apps/emqx_management/src/emqx_mgmt_api_banned.erl b/apps/emqx_management/src/emqx_mgmt_api_banned.erl index 1354b9ac8..fc9ece871 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_banned.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_banned.erl @@ -62,7 +62,7 @@ schema("/banned") -> responses => #{ 200 => [ {data, hoconsc:mk(hoconsc:array(hoconsc:ref(ban)), #{})}, - {meta, hoconsc:mk(hoconsc:ref(meta), #{})} + {meta, hoconsc:mk(hoconsc:ref(emqx_dashboard_swagger, meta), #{})} ] } }, @@ -147,11 +147,7 @@ fields(ban) -> required => false, example => <<"2021-10-25T21:53:47+08:00">> })} - ]; -fields(meta) -> - emqx_dashboard_swagger:fields(page) ++ - emqx_dashboard_swagger:fields(limit) ++ - [{count, hoconsc:mk(integer(), #{example => 1})}]. + ]. banned(get, #{query_string := Params}) -> Response = emqx_mgmt_api:paginate(?TAB, Params, ?FORMAT_FUN), diff --git a/apps/emqx_management/src/emqx_mgmt_api_clients.erl b/apps/emqx_management/src/emqx_mgmt_api_clients.erl index 393af6b5d..8330c11b4 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_clients.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_clients.erl @@ -203,7 +203,7 @@ schema("/clients") -> responses => #{ 200 => [ {data, hoconsc:mk(hoconsc:array(hoconsc:ref(?MODULE, client)), #{})}, - {meta, hoconsc:mk(hoconsc:ref(?MODULE, meta), #{})} + {meta, hoconsc:mk(hoconsc:ref(emqx_dashboard_swagger, meta), #{})} ], 400 => emqx_dashboard_swagger:error_codes( @@ -518,11 +518,7 @@ fields(subscribe) -> fields(unsubscribe) -> [ {topic, hoconsc:mk(binary(), #{desc => <<"Topic">>})} - ]; -fields(meta) -> - emqx_dashboard_swagger:fields(page) ++ - emqx_dashboard_swagger:fields(limit) ++ - [{count, hoconsc:mk(integer(), #{example => 1})}]. + ]. %%%============================================================================================== %% parameters trans diff --git a/apps/emqx_management/src/emqx_mgmt_api_topics.erl b/apps/emqx_management/src/emqx_mgmt_api_topics.erl index ef07cabe3..3b54a3bee 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_topics.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_topics.erl @@ -60,7 +60,7 @@ schema("/topics") -> responses => #{ 200 => [ {data, hoconsc:mk(hoconsc:array(hoconsc:ref(topic)), #{})}, - {meta, hoconsc:mk(hoconsc:ref(meta), #{})} + {meta, hoconsc:mk(hoconsc:ref(emqx_dashboard_swagger, meta), #{})} ] } } @@ -91,11 +91,7 @@ fields(topic) -> desc => <<"Node">>, required => true })} - ]; -fields(meta) -> - emqx_dashboard_swagger:fields(page) ++ - emqx_dashboard_swagger:fields(limit) ++ - [{count, hoconsc:mk(integer(), #{example => 1})}]. + ]. %%%============================================================================================== %% parameters trans From cf671f10e74c9096d12f03fa10a42f4568571df6 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Mon, 11 Apr 2022 11:35:30 +0800 Subject: [PATCH 2/8] fix(swagger): string example use binary --- apps/emqx_dashboard/src/emqx_dashboard_swagger.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl index 72a1aeb2a..cc4166193 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl @@ -579,7 +579,7 @@ hocon_schema_to_spec(Atom, _LocalModule) when is_atom(Atom) -> typename_to_spec("user_id_type()", _Mod) -> #{type => string, enum => [clientid, username]}; typename_to_spec("term()", _Mod) -> - #{type => string}; + #{type => string, example => <<"any">>}; typename_to_spec("boolean()", _Mod) -> #{type => boolean}; typename_to_spec("binary()", _Mod) -> From 88c98bb310e0bfa74f43c210bc7e268d6f0637f9 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Mon, 11 Apr 2022 15:41:27 +0800 Subject: [PATCH 3/8] fix(authn): api required fields --- apps/emqx_authn/src/emqx_authn.erl | 14 ++++---- apps/emqx_authn/src/emqx_authn_api.erl | 28 ++++++++-------- .../src/emqx_authn_password_hashing.erl | 32 +++++++++++-------- .../src/simple_authn/emqx_authn_http.erl | 6 ++-- .../src/simple_authn/emqx_authn_jwt.erl | 20 ++++++++---- .../src/simple_authn/emqx_authn_mnesia.erl | 5 +-- .../src/simple_authn/emqx_authn_mongodb.erl | 2 ++ .../src/simple_authn/emqx_authn_mysql.erl | 3 +- .../src/simple_authn/emqx_authn_pgsql.erl | 3 +- .../src/simple_authn/emqx_authn_redis.erl | 1 + .../src/emqx_connector_mongo.erl | 5 ++- .../src/emqx_connector_redis.erl | 4 +++ 12 files changed, 74 insertions(+), 49 deletions(-) diff --git a/apps/emqx_authn/src/emqx_authn.erl b/apps/emqx_authn/src/emqx_authn.erl index 70e662cc3..79d269a55 100644 --- a/apps/emqx_authn/src/emqx_authn.erl +++ b/apps/emqx_authn/src/emqx_authn.erl @@ -29,14 +29,14 @@ providers() -> [ - {{'password_based', 'built_in_database'}, emqx_authn_mnesia}, - {{'password_based', mysql}, emqx_authn_mysql}, - {{'password_based', postgresql}, emqx_authn_pgsql}, - {{'password_based', mongodb}, emqx_authn_mongodb}, - {{'password_based', redis}, emqx_authn_redis}, - {{'password_based', 'http'}, emqx_authn_http}, + {{password_based, built_in_database}, emqx_authn_mnesia}, + {{password_based, mysql}, emqx_authn_mysql}, + {{password_based, postgresql}, emqx_authn_pgsql}, + {{password_based, mongodb}, emqx_authn_mongodb}, + {{password_based, redis}, emqx_authn_redis}, + {{password_based, http}, emqx_authn_http}, {jwt, emqx_authn_jwt}, - {{scram, 'built_in_database'}, emqx_enhanced_authn_scram_mnesia} + {{scram, built_in_database}, emqx_enhanced_authn_scram_mnesia} ]. check_configs(C) when is_map(C) -> diff --git a/apps/emqx_authn/src/emqx_authn_api.erl b/apps/emqx_authn/src/emqx_authn_api.erl index d1d8cbc6a..8f2f2dab7 100644 --- a/apps/emqx_authn/src/emqx_authn_api.erl +++ b/apps/emqx_authn/src/emqx_authn_api.erl @@ -128,21 +128,22 @@ roots() -> fields(request_user_create) -> [ - {user_id, binary()} + {user_id, mk(binary(), #{required => true})} | fields(request_user_update) ]; fields(request_user_update) -> [ - {password, binary()}, + {password, mk(binary(), #{required => true})}, {is_superuser, mk(boolean(), #{default => false, required => false})} ]; fields(request_move) -> - [{position, binary()}]; + [{position, mk(binary(), #{required => true})}]; fields(request_import_users) -> - [{filename, binary()}]; + %% TODO: add file update + [{filename, mk(binary(), #{required => true})}]; fields(response_user) -> [ - {user_id, binary()}, + {user_id, mk(binary(), #{required => true})}, {is_superuser, mk(boolean(), #{default => false, required => false})} ]; fields(response_users) -> @@ -425,10 +426,8 @@ schema("/authentication/:id/users") -> description => <<"List users in authenticator in global authentication chain">>, parameters => [ param_auth_id(), - {page, - mk(pos_integer(), #{in => query, desc => <<"Page Index">>, required => false})}, - {limit, - mk(pos_integer(), #{in => query, desc => <<"Page Limit">>, required => false})}, + ref(emqx_dashboard_swagger, page), + ref(emqx_dashboard_swagger, limit), {like_username, mk(binary(), #{ in => query, @@ -477,10 +476,8 @@ schema("/listeners/:listener_id/authentication/:id/users") -> parameters => [ param_listener_id(), param_auth_id(), - {page, - mk(pos_integer(), #{in => query, desc => <<"Page Index">>, required => false})}, - {limit, - mk(pos_integer(), #{in => query, desc => <<"Page Limit">>, required => false})} + ref(emqx_dashboard_swagger, page), + ref(emqx_dashboard_swagger, limit) ], responses => #{ 200 => emqx_dashboard_swagger:schema_with_example( @@ -581,7 +578,8 @@ param_auth_id() -> id, mk(binary(), #{ in => path, - desc => <<"Authenticator ID">> + desc => <<"Authenticator ID">>, + required => true }) }. @@ -591,6 +589,7 @@ param_listener_id() -> mk(binary(), #{ in => path, desc => <<"Listener ID">>, + required => true, example => emqx_listeners:id_example() }) }. @@ -1177,6 +1176,7 @@ update_config(Path, ConfigRequest) -> get_raw_config_with_defaults(ConfKeyPath) -> NConfKeyPath = [atom_to_binary(Key, utf8) || Key <- ConfKeyPath], RawConfig = emqx_map_lib:deep_get(NConfKeyPath, emqx_config:get_raw([]), []), + %% TODO: check plain unexcepted ensure_list(fill_defaults(RawConfig)). find_config(AuthenticatorID, AuthenticatorsConfig) -> diff --git a/apps/emqx_authn/src/emqx_authn_password_hashing.erl b/apps/emqx_authn/src/emqx_authn_password_hashing.erl index 959d9030a..6824f69d9 100644 --- a/apps/emqx_authn/src/emqx_authn_password_hashing.erl +++ b/apps/emqx_authn/src/emqx_authn_password_hashing.erl @@ -68,21 +68,31 @@ roots() -> [pbkdf2, bcrypt, bcrypt_rw, other_algorithms]. fields(bcrypt_rw) -> fields(bcrypt) ++ - [{salt_rounds, fun salt_rounds/1}]; + [ + {salt_rounds, + sc( + integer(), + #{ + default => 10, + example => 10, + desc => "Salt rounds for BCRYPT password generation." + } + )} + ]; fields(bcrypt) -> - [{name, sc(bcrypt, #{desc => "BCRYPT password hashing."})}]; + [{name, sc(bcrypt, #{required => true, desc => "BCRYPT password hashing."})}]; fields(pbkdf2) -> [ - {name, sc(pbkdf2, #{desc => "PBKDF2 password hashing."})}, + {name, sc(pbkdf2, #{required => true, desc => "PBKDF2 password hashing."})}, {mac_fun, sc( hoconsc:enum([md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512]), - #{desc => "Specifies mac_fun for PBKDF2 hashing algorithm."} + #{required => true, desc => "Specifies mac_fun for PBKDF2 hashing algorithm."} )}, {iterations, sc( integer(), - #{desc => "Iteration count for PBKDF2 hashing algorithm."} + #{required => true, desc => "Iteration count for PBKDF2 hashing algorithm."} )}, {dk_length, fun dk_length/1} ]; @@ -91,10 +101,7 @@ fields(other_algorithms) -> {name, sc( hoconsc:enum([plain, md5, sha, sha256, sha512]), - #{ - desc => - "Simple password hashing algorithm." - } + #{required => true, desc => "Simple password hashing algorithm."} )}, {salt_position, fun salt_position/1} ]. @@ -115,11 +122,6 @@ salt_position(default) -> prefix; salt_position(desc) -> "Salt position for PLAIN, MD5, SHA, SHA256 and SHA512 algorithms."; salt_position(_) -> undefined. -salt_rounds(type) -> integer(); -salt_rounds(default) -> 10; -salt_rounds(desc) -> "Salt rounds for BCRYPT password generation."; -salt_rounds(_) -> undefined. - dk_length(type) -> integer(); dk_length(required) -> @@ -130,6 +132,7 @@ dk_length(desc) -> dk_length(_) -> undefined. +%% for simple_authn/emqx_authn_mnesia type_rw(type) -> hoconsc:union(rw_refs()); type_rw(default) -> @@ -139,6 +142,7 @@ type_rw(desc) -> type_rw(_) -> undefined. +%% for other authn resources type_ro(type) -> hoconsc:union(ro_refs()); type_ro(default) -> diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl index 3dee4c2a3..d870d2a06 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl @@ -57,12 +57,12 @@ roots() -> fields(get) -> [ - {method, #{type => get, default => post, desc => "HTTP method."}}, + {method, #{type => get, required => true, default => post, desc => "HTTP method."}}, {headers, fun headers_no_content_type/1} ] ++ common_fields(); fields(post) -> [ - {method, #{type => post, default => post, desc => "HTTP method."}}, + {method, #{type => post, required => true, default => post, desc => "HTTP method."}}, {headers, fun headers/1} ] ++ common_fields(). @@ -75,7 +75,7 @@ desc(_) -> common_fields() -> [ - {mechanism, emqx_authn_schema:mechanism('password_based')}, + {mechanism, emqx_authn_schema:mechanism(password_based)}, {backend, emqx_authn_schema:backend(http)}, {url, fun url/1}, {body, diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl index 6b0924760..b296e32a6 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl @@ -55,20 +55,22 @@ roots() -> fields('hmac-based') -> [ - {use_jwks, sc(hoconsc:enum([false]), #{desc => ""})}, - {algorithm, sc(hoconsc:enum(['hmac-based']), #{desc => "Signing algorithm."})}, + {use_jwks, sc(hoconsc:enum([false]), #{required => true, desc => ""})}, + {algorithm, + sc(hoconsc:enum(['hmac-based']), #{required => true, desc => "Signing algorithm."})}, {secret, fun secret/1}, {secret_base64_encoded, fun secret_base64_encoded/1} ] ++ common_fields(); fields('public-key') -> [ - {use_jwks, sc(hoconsc:enum([false]), #{desc => ""})}, - {algorithm, sc(hoconsc:enum(['public-key']), #{desc => "Signing algorithm."})}, + {use_jwks, sc(hoconsc:enum([false]), #{required => true, desc => ""})}, + {algorithm, + sc(hoconsc:enum(['public-key']), #{required => true, desc => "Signing algorithm."})}, {certificate, fun certificate/1} ] ++ common_fields(); fields('jwks') -> [ - {use_jwks, sc(hoconsc:enum([true]), #{desc => ""})}, + {use_jwks, sc(hoconsc:enum([true]), #{required => true, desc => ""})}, {endpoint, fun endpoint/1}, {pool_size, fun pool_size/1}, {refresh_interval, fun refresh_interval/1}, @@ -78,7 +80,8 @@ fields('jwks') -> hoconsc:ref(?MODULE, ssl_disable) ]), desc => "Enable/disable SSL.", - default => #{<<"enable">> => false} + default => #{<<"enable">> => false}, + required => false }} ] ++ common_fields(); fields(ssl_enable) -> @@ -114,6 +117,7 @@ common_fields() -> secret(type) -> binary(); secret(desc) -> "The key to verify the JWT Token using HMAC algorithm."; +secret(required) -> true; secret(_) -> undefined. secret_base64_encoded(type) -> boolean(); @@ -123,10 +127,12 @@ secret_base64_encoded(_) -> undefined. certificate(type) -> string(); certificate(desc) -> "The certificate used for signing the token."; +certificate(required) -> ture; certificate(_) -> undefined. endpoint(type) -> string(); endpoint(desc) -> "JWKs endpoint."; +endpoint(required) -> true; endpoint(_) -> undefined. refresh_interval(type) -> integer(); @@ -168,6 +174,8 @@ verify_claims(converter) -> fun(VerifyClaims) -> [{to_binary(K), V} || {K, V} <- maps:to_list(VerifyClaims)] end; +verify_claims(required) -> + false; verify_claims(_) -> undefined. diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl index 9d6d1820a..7971ce049 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl @@ -103,8 +103,8 @@ roots() -> [?CONF_NS]. fields(?CONF_NS) -> [ - {mechanism, emqx_authn_schema:mechanism('password_based')}, - {backend, emqx_authn_schema:backend('built_in_database')}, + {mechanism, emqx_authn_schema:mechanism(password_based)}, + {backend, emqx_authn_schema:backend(built_in_database)}, {user_id_type, fun user_id_type/1}, {password_hash_algorithm, fun emqx_authn_password_hashing:type_rw/1} ] ++ emqx_authn_schema:common_fields(). @@ -117,6 +117,7 @@ desc(_) -> user_id_type(type) -> user_id_type(); user_id_type(desc) -> "Authenticate by client ID or username."; user_id_type(default) -> <<"username">>; +user_id_type(required) -> true; user_id_type(_) -> undefined. %%------------------------------------------------------------------------------ diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl index c177316db..f5ceaa577 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl @@ -83,6 +83,7 @@ common_fields() -> collection(type) -> binary(); collection(desc) -> "Collection used to store authentication data."; +collection(required) -> true; collection(_) -> undefined. selector(type) -> @@ -97,6 +98,7 @@ selector(_) -> password_hash_field(type) -> binary(); password_hash_field(desc) -> "Document field that contains password hash."; +password_hash_field(required) -> false; password_hash_field(_) -> undefined. salt_field(type) -> binary(); diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl index 11e670f4f..4152bd888 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl @@ -48,7 +48,7 @@ roots() -> [?CONF_NS]. fields(?CONF_NS) -> [ - {mechanism, emqx_authn_schema:mechanism('password_based')}, + {mechanism, emqx_authn_schema:mechanism(password_based)}, {backend, emqx_authn_schema:backend(mysql)}, {password_hash_algorithm, fun emqx_authn_password_hashing:type_ro/1}, {query, fun query/1}, @@ -63,6 +63,7 @@ desc(_) -> query(type) -> string(); query(desc) -> "SQL query used to lookup client data."; +query(required) -> true; query(_) -> undefined. query_timeout(type) -> emqx_schema:duration_ms(); diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl index 34239cb87..3a9f390dd 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl @@ -54,7 +54,7 @@ roots() -> [?CONF_NS]. fields(?CONF_NS) -> [ - {mechanism, emqx_authn_schema:mechanism('password_based')}, + {mechanism, emqx_authn_schema:mechanism(password_based)}, {backend, emqx_authn_schema:backend(postgresql)}, {password_hash_algorithm, fun emqx_authn_password_hashing:type_ro/1}, {query, fun query/1} @@ -69,6 +69,7 @@ desc(_) -> query(type) -> string(); query(desc) -> "`SQL` query for looking up authentication data."; +query(required) -> true; query(_) -> undefined. %%------------------------------------------------------------------------------ diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl index 1d37db10a..b29f0acdf 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl @@ -79,6 +79,7 @@ common_fields() -> cmd(type) -> string(); cmd(desc) -> "Redis query."; +cmd(required) -> true; cmd(_) -> undefined. %%------------------------------------------------------------------------------ diff --git a/apps/emqx_connector/src/emqx_connector_mongo.erl b/apps/emqx_connector/src/emqx_connector_mongo.erl index ca5143d44..51da5d68e 100644 --- a/apps/emqx_connector/src/emqx_connector_mongo.erl +++ b/apps/emqx_connector/src/emqx_connector_mongo.erl @@ -56,6 +56,7 @@ roots() -> fields(single) -> [ {mongo_type, #{type => single, default => single, + required => true, desc => ?DESC("single_mongo_type")}} , {server, fun server/1} , {w_mode, fun w_mode/1} @@ -63,6 +64,7 @@ fields(single) -> fields(rs) -> [ {mongo_type, #{type => rs, default => rs, + required => true, desc => ?DESC("rs_mongo_type")}} , {servers, fun servers/1} , {w_mode, fun w_mode/1} @@ -72,6 +74,7 @@ fields(rs) -> fields(sharded) -> [ {mongo_type, #{type => sharded, default => sharded, + required => true, desc => ?DESC("sharded_mongo_type")}} , {servers, fun servers/1} , {w_mode, fun w_mode/1} @@ -336,7 +339,7 @@ max_overflow(_) -> undefined. replica_set_name(type) -> binary(); replica_set_name(desc) -> ?DESC("replica_set_name"); -replica_set_name(required) -> false; +replica_set_name(required) -> true; replica_set_name(_) -> undefined. srv_record(type) -> boolean(); diff --git a/apps/emqx_connector/src/emqx_connector_redis.erl b/apps/emqx_connector/src/emqx_connector_redis.erl index 77180391c..2fb7afad0 100644 --- a/apps/emqx_connector/src/emqx_connector_redis.erl +++ b/apps/emqx_connector/src/emqx_connector_redis.erl @@ -57,6 +57,7 @@ fields(single) -> [ {server, fun server/1} , {redis_type, #{type => hoconsc:enum([single]), default => single, + required => true, desc => ?DESC("single") }} ] ++ @@ -66,6 +67,7 @@ fields(cluster) -> [ {servers, fun servers/1} , {redis_type, #{type => hoconsc:enum([cluster]), default => cluster, + required => true, desc => ?DESC("cluster") }} ] ++ @@ -75,6 +77,7 @@ fields(sentinel) -> [ {servers, fun servers/1} , {redis_type, #{type => hoconsc:enum([sentinel]), default => sentinel, + required => true, desc => ?DESC("sentinel") }} , {sentinel, #{type => string(), desc => ?DESC("sentinel_desc") @@ -210,6 +213,7 @@ redis_fields() -> , {password, fun emqx_connector_schema_lib:password/1} , {database, #{type => integer(), default => 0, + required => true, desc => ?DESC("database") }} , {auto_reconnect, fun emqx_connector_schema_lib:auto_reconnect/1} From 14a97d777dc79ddd8f495437d8949b0e83de0b02 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Mon, 11 Apr 2022 18:20:45 +0800 Subject: [PATCH 4/8] fix(authz): api required fields --- apps/emqx/src/emqx_schema.erl | 2 + apps/emqx_authz/src/emqx_authz_api_schema.erl | 38 +++++++++++++------ apps/emqx_authz/src/emqx_authz_schema.erl | 23 +++++++---- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl index 1079443f3..3595fd999 100644 --- a/apps/emqx/src/emqx_schema.erl +++ b/apps/emqx/src/emqx_schema.erl @@ -315,6 +315,7 @@ fields("authorization") -> hoconsc:enum([allow, deny]), #{ default => allow, + required => true, %% TODO: make sources a reference link desc => "Default access control action if the user or client matches no ACL rules,\n" @@ -328,6 +329,7 @@ fields("authorization") -> hoconsc:enum([ignore, disconnect]), #{ default => ignore, + required => true, desc => "The action when the authorization check rejects an operation." } )}, diff --git a/apps/emqx_authz/src/emqx_authz_api_schema.erl b/apps/emqx_authz/src/emqx_authz_api_schema.erl index 78c8539ae..badf029b0 100644 --- a/apps/emqx_authz/src/emqx_authz_api_schema.erl +++ b/apps/emqx_authz/src/emqx_authz_api_schema.erl @@ -30,7 +30,8 @@ fields(http) -> {url, fun url/1}, {method, #{ type => enum([get, post]), - default => get + default => get, + required => true }}, {headers, fun headers/1}, {body, map([{fuzzy, term(), binary()}])}, @@ -45,8 +46,8 @@ fields(http) -> maps:from_list(emqx_connector_http:fields(config)) ) ); -fields('built_in_database') -> - authz_common_fields('built_in_database'); +fields(built_in_database) -> + authz_common_fields(built_in_database); fields(mongo_single) -> authz_mongo_common_fields() ++ emqx_connector_mongo:fields(single); @@ -58,11 +59,11 @@ fields(mongo_sharded) -> emqx_connector_mongo:fields(sharded); fields(mysql) -> authz_common_fields(mysql) ++ - [{query, #{type => binary()}}] ++ + [{query, mk(binary(), #{required => true})}] ++ emqx_connector_mysql:fields(config); fields(postgresql) -> authz_common_fields(postgresql) ++ - [{query, #{type => binary()}}] ++ + [{query, mk(binary(), #{required => true})}] ++ proplists:delete(named_queries, emqx_connector_pgsql:fields(config)); fields(redis_single) -> authz_redis_common_fields() ++ @@ -107,6 +108,8 @@ url(_) -> undefined. headers(type) -> map(); +headers(desc) -> + "List of HTTP headers."; headers(converter) -> fun(Headers) -> maps:merge(default_headers(), transform_header_name(Headers)) @@ -153,10 +156,19 @@ authz_mongo_common_fields() -> ]. collection(type) -> binary(); +collection(desc) -> "Collection used to store authentication data."; +collection(required) -> true; collection(_) -> undefined. -selector(type) -> map(); -selector(_) -> undefined. +selector(type) -> + map(); +selector(desc) -> + "Statement that is executed during the authentication process. " + "Commands can support following wildcards:\n" + " - `${username}`: substituted with client's username\n" + " - `${clientid}`: substituted with the clientid"; +selector(_) -> + undefined. %%------------------------------------------------------------------------------ %% Redis type funcs @@ -164,10 +176,11 @@ selector(_) -> undefined. authz_redis_common_fields() -> authz_common_fields(redis) ++ [ - {cmd, #{ - type => binary(), - example => <<"HGETALL mqtt_authz">> - }} + {cmd, + mk(binary(), #{ + required => true, + example => <<"HGETALL mqtt_authz">> + })} ]. %%------------------------------------------------------------------------------ @@ -179,6 +192,7 @@ authz_common_fields(Type) when is_atom(Type) -> {type, #{ type => enum([Type]), default => Type, + required => true, in => body }} ]. @@ -207,7 +221,7 @@ authz_sources_types(Type) -> end ++ [ http, - 'built_in_database', + built_in_database, mysql, postgresql, file diff --git a/apps/emqx_authz/src/emqx_authz_schema.erl b/apps/emqx_authz/src/emqx_authz_schema.erl index 0123ee951..936a9c74f 100644 --- a/apps/emqx_authz/src/emqx_authz_schema.erl +++ b/apps/emqx_authz/src/emqx_authz_schema.erl @@ -96,7 +96,7 @@ fields("authorization") -> ]; fields(file) -> [ - {type, #{type => file, desc => "Backend type."}}, + {type, #{type => file, required => true, desc => "Backend type."}}, {enable, #{ type => boolean(), default => true, @@ -118,17 +118,17 @@ fields(file) -> ]; fields(http_get) -> [ - {method, #{type => get, default => get, desc => "HTTP method."}}, + {method, #{type => get, default => get, required => true, desc => "HTTP method."}}, {headers, fun headers_no_content_type/1} ] ++ http_common_fields(); fields(http_post) -> [ - {method, #{type => post, default => post, desc => "HTTP method."}}, + {method, #{type => post, default => post, required => true, desc => "HTTP method."}}, {headers, fun headers/1} ] ++ http_common_fields(); fields(mnesia) -> [ - {type, #{type => 'built_in_database', desc => "Backend type."}}, + {type, #{type => 'built_in_database', required => true, desc => "Backend type."}}, {enable, #{ type => boolean(), default => true, @@ -147,7 +147,7 @@ fields(mysql) -> fields(postgresql) -> [ {query, query()}, - {type, #{type => postgresql, desc => "Backend type."}}, + {type, #{type => postgresql, required => true, desc => "Backend type."}}, {enable, #{ type => boolean(), desc => "Enable this backend.", @@ -213,10 +213,16 @@ http_common_fields() -> mongo_common_fields() -> [ {collection, #{ - type => atom(), desc => "`MongoDB` collection containing the authorization data." + type => atom(), + required => true, + desc => "`MongoDB` collection containing the authorization data." }}, - {selector, #{type => map(), desc => "MQL query used to select the authorization record."}}, - {type, #{type => mongodb, desc => "Database backend."}}, + {selector, #{ + type => map(), + required => true, + desc => "MQL query used to select the authorization record." + }}, + {type, #{type => mongodb, required => true, desc => "Database backend."}}, {enable, #{ type => boolean(), default => true, @@ -335,6 +341,7 @@ query() -> #{ type => binary(), desc => "Database query used to retrieve authorization data.", + required => true, validator => fun(S) -> case size(S) > 0 of true -> ok; From c67e565755818ebb2ee527fdc8224a53e508836c Mon Sep 17 00:00:00 2001 From: JimMoen Date: Tue, 12 Apr 2022 12:51:52 +0800 Subject: [PATCH 5/8] fix(authn): merge default header after check config --- apps/emqx_authn/src/emqx_authn_api.erl | 22 ++++++++++++++++--- .../src/simple_authn/emqx_authn_http.erl | 5 +++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/apps/emqx_authn/src/emqx_authn_api.erl b/apps/emqx_authn/src/emqx_authn_api.erl index 8f2f2dab7..c785bf0f6 100644 --- a/apps/emqx_authn/src/emqx_authn_api.erl +++ b/apps/emqx_authn/src/emqx_authn_api.erl @@ -1175,8 +1175,7 @@ update_config(Path, ConfigRequest) -> get_raw_config_with_defaults(ConfKeyPath) -> NConfKeyPath = [atom_to_binary(Key, utf8) || Key <- ConfKeyPath], - RawConfig = emqx_map_lib:deep_get(NConfKeyPath, emqx_config:get_raw([]), []), - %% TODO: check plain unexcepted + RawConfig = emqx:get_raw_config(NConfKeyPath, []), ensure_list(fill_defaults(RawConfig)). find_config(AuthenticatorID, AuthenticatorsConfig) -> @@ -1194,7 +1193,24 @@ find_config(AuthenticatorID, AuthenticatorsConfig) -> fill_defaults(Configs) when is_list(Configs) -> lists:map(fun fill_defaults/1, Configs); fill_defaults(Config) -> - emqx_authn:check_config(Config, #{only_fill_defaults => true}). + emqx_authn:check_config(merge_default_headers(Config), #{only_fill_defaults => true}). + +merge_default_headers(Config) -> + case maps:find(<<"headers">>, Config) of + {ok, Headers} -> + NewHeaders = + case Config of + #{<<"method">> := <<"get">>} -> + (emqx_authn_http:headers_no_content_type(converter))(Headers); + #{<<"method">> := <<"post">>} -> + (emqx_authn_http:headers(converter))(Headers); + _ -> + Headers + end, + Config#{<<"headers">> => NewHeaders}; + error -> + Config + end. convert_certs(#{ssl := SSL} = Config) when SSL =/= undefined -> Config#{ssl := emqx_tls_lib:drop_invalid_certs(SSL)}; diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl index d870d2a06..d13f2c69f 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl @@ -32,6 +32,11 @@ validations/0 ]). +-export([ + headers_no_content_type/1, + headers/1 +]). + -export([ refs/0, create/2, From 341973880d1df464c620ccdc3f3797eae5af10f5 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Tue, 12 Apr 2022 18:42:08 +0800 Subject: [PATCH 6/8] fix(authz): refine authz-http api with default headers --- apps/emqx/include/emqx_access_control.hrl | 20 +++++ apps/emqx/src/emqx_schema.erl | 5 +- apps/emqx_authz/include/emqx_authz.hrl | 7 ++ apps/emqx_authz/src/emqx_authz_api_schema.erl | 77 +++++++++++++------ apps/emqx_authz/src/emqx_authz_schema.erl | 45 ++++------- 5 files changed, 95 insertions(+), 59 deletions(-) create mode 100644 apps/emqx/include/emqx_access_control.hrl diff --git a/apps/emqx/include/emqx_access_control.hrl b/apps/emqx/include/emqx_access_control.hrl new file mode 100644 index 000000000..4d5ba8179 --- /dev/null +++ b/apps/emqx/include/emqx_access_control.hrl @@ -0,0 +1,20 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2022 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +%% config root name all auth providers have to agree on. +-define(EMQX_AUTHORIZATION_CONFIG_ROOT_NAME, "authorization"). +-define(EMQX_AUTHORIZATION_CONFIG_ROOT_NAME_ATOM, authorization). +-define(EMQX_AUTHORIZATION_CONFIG_ROOT_NAME_BINARY, <<"authorization">>). diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl index 3595fd999..04f20cf0d 100644 --- a/apps/emqx/src/emqx_schema.erl +++ b/apps/emqx/src/emqx_schema.erl @@ -24,6 +24,7 @@ -elvis([{elvis_style, invalid_dynamic_call, disable}]). -include("emqx_authentication.hrl"). +-include("emqx_access_control.hrl"). -include_lib("typerefl/include/types.hrl"). -type duration() :: integer(). @@ -159,9 +160,9 @@ roots(high) -> )}, %% NOTE: authorization schema here is only to keep emqx app prue %% the full schema for EMQX node is injected in emqx_conf_schema. - {"authorization", + {?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME, sc( - ref("authorization"), + ref(?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME), #{} )} ]; diff --git a/apps/emqx_authz/include/emqx_authz.hrl b/apps/emqx_authz/include/emqx_authz.hrl index a3fe2d1f9..5c7602658 100644 --- a/apps/emqx_authz/include/emqx_authz.hrl +++ b/apps/emqx_authz/include/emqx_authz.hrl @@ -14,6 +14,8 @@ %% limitations under the License. %%-------------------------------------------------------------------- +-include_lib("emqx/include/emqx_access_control.hrl"). + -define(APP, emqx_authz). -define(ALLOW_DENY(A), @@ -45,6 +47,11 @@ -define(RE_PLACEHOLDER, "\\$\\{[a-z0-9_]+\\}"). +%% has to be the same as the root field name defined in emqx_schema +-define(CONF_NS, ?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME). +-define(CONF_NS_ATOM, ?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME_ATOM). +-define(CONF_NS_BINARY, ?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME_BINARY). + %% API examples -define(USERNAME_RULES_EXAMPLE, #{ username => user1, diff --git a/apps/emqx_authz/src/emqx_authz_api_schema.erl b/apps/emqx_authz/src/emqx_authz_api_schema.erl index badf029b0..b4ea40ccc 100644 --- a/apps/emqx_authz/src/emqx_authz_api_schema.erl +++ b/apps/emqx_authz/src/emqx_authz_api_schema.erl @@ -16,36 +16,32 @@ -module(emqx_authz_api_schema). +-include("emqx_authz.hrl"). -include_lib("typerefl/include/types.hrl"). -include_lib("emqx_connector/include/emqx_connector.hrl"). -import(hoconsc, [mk/2, enum/1]). -import(emqx_schema, [mk_duration/2]). --export([fields/1, authz_sources_types/1]). +-export([ + fields/1, + authz_sources_types/1 +]). -fields(http) -> - authz_common_fields(http) ++ - [ - {url, fun url/1}, - {method, #{ - type => enum([get, post]), - default => get, - required => true - }}, - {headers, fun headers/1}, - {body, map([{fuzzy, term(), binary()}])}, - {request_timeout, mk_duration("Request timeout", #{default => "30s"})} - ] ++ - maps:to_list( - maps:without( - [ - base_url, - pool_type - ], - maps:from_list(emqx_connector_http:fields(config)) - ) - ); +%%------------------------------------------------------------------------------ +%% Hocon Schema +%%------------------------------------------------------------------------------ + +fields(http_get) -> + [ + {method, #{type => get, default => get, required => true}}, + {headers, fun headers_no_content_type/1} + ] ++ authz_http_common_fields(); +fields(http_post) -> + [ + {method, #{type => post, default => post, required => true}}, + {headers, fun headers/1} + ] ++ authz_http_common_fields(); fields(built_in_database) -> authz_common_fields(built_in_database); fields(mongo_single) -> @@ -101,6 +97,23 @@ fields(position) -> %%------------------------------------------------------------------------------ %% http type funcs +authz_http_common_fields() -> + authz_common_fields(http) ++ + [ + {url, fun url/1}, + {body, map([{fuzzy, term(), binary()}])}, + {request_timeout, mk_duration("Request timeout", #{default => "30s"})} + ] ++ + maps:to_list( + maps:without( + [ + base_url, + pool_type + ], + maps:from_list(emqx_connector_http:fields(config)) + ) + ). + url(type) -> binary(); url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")]; url(required) -> true; @@ -119,6 +132,19 @@ headers(default) -> headers(_) -> undefined. +headers_no_content_type(type) -> + map(); +headers_no_content_type(desc) -> + "List of HTTP headers."; +headers_no_content_type(converter) -> + fun(Headers) -> + maps:merge(default_headers_no_content_type(), transform_header_name(Headers)) + end; +headers_no_content_type(default) -> + default_headers_no_content_type(); +headers_no_content_type(_) -> + undefined. + %% headers default_headers() -> maps:put( @@ -208,9 +234,11 @@ enable(_) -> undefined. authz_sources_types(Type) -> case Type of simple -> - [mongodb, redis]; + [http, mongodb, redis]; detailed -> [ + http_get, + http_post, mongo_single, mongo_rs, mongo_sharded, @@ -220,7 +248,6 @@ authz_sources_types(Type) -> ] end ++ [ - http, built_in_database, mysql, postgresql, diff --git a/apps/emqx_authz/src/emqx_authz_schema.erl b/apps/emqx_authz/src/emqx_authz_schema.erl index 936a9c74f..011b1585d 100644 --- a/apps/emqx_authz/src/emqx_authz_schema.erl +++ b/apps/emqx_authz/src/emqx_authz_schema.erl @@ -16,6 +16,7 @@ -module(emqx_authz_schema). +-include("emqx_authz.hrl"). -include_lib("typerefl/include/types.hrl"). -include_lib("emqx_connector/include/emqx_connector.hrl"). @@ -40,9 +41,6 @@ headers/1 ]). --import(emqx_schema, [mk_duration/2]). --include_lib("hocon/include/hoconsc.hrl"). - %%-------------------------------------------------------------------- %% Hocon Schema %%-------------------------------------------------------------------- @@ -197,7 +195,9 @@ http_common_fields() -> [ {url, fun url/1}, {request_timeout, - mk_duration("Request timeout", #{default => "30s", desc => "Request timeout."})}, + emqx_schema:mk_duration("Request timeout", #{ + default => "30s", desc => "Request timeout." + })}, {body, #{type => map(), required => false, desc => "HTTP request body."}} ] ++ maps:to_list( @@ -232,8 +232,7 @@ mongo_common_fields() -> validations() -> [ - {check_ssl_opts, fun check_ssl_opts/1}, - {check_headers, fun check_headers/1} + {check_ssl_opts, fun check_ssl_opts/1} ]. headers(type) -> @@ -259,6 +258,13 @@ headers_no_content_type(converter) -> end; headers_no_content_type(default) -> default_headers_no_content_type(); +headers_no_content_type(validator) -> + fun(Headers) -> + case lists:keyfind(<<"content-type">>, 1, Headers) of + false -> ok; + _ -> {error, do_not_include_content_type} + end + end; headers_no_content_type(_) -> undefined. @@ -297,6 +303,7 @@ transform_header_name(Headers) -> Headers ). +%% TODO: fix me, not work check_ssl_opts(Conf) -> case hocon_maps:get("config.url", Conf) of undefined -> @@ -315,25 +322,6 @@ check_ssl_opts(Conf) -> end end. -check_headers(Conf) -> - case hocon_maps:get("config.method", Conf) of - undefined -> - true; - Method0 -> - Method = to_bin(Method0), - Headers = hocon_maps:get("config.headers", Conf), - case Method of - <<"post">> -> - true; - _ when Headers =:= undefined -> true; - _ when is_list(Headers) -> - case lists:member(<<"content-type">>, Headers) of - false -> true; - true -> {Method0, do_not_include_content_type} - end - end - end. - union_array(Item) when is_list(Item) -> hoconsc:array(hoconsc:union(Item)). @@ -376,10 +364,3 @@ to_list(A) when is_atom(A) -> atom_to_list(A); to_list(B) when is_binary(B) -> binary_to_list(B). - -to_bin(A) when is_atom(A) -> - atom_to_binary(A); -to_bin(B) when is_binary(B) -> - B; -to_bin(L) when is_list(L) -> - list_to_binary(L). From bf54f571fb8b27e76ada4ca75137d96ce4211d60 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Tue, 19 Apr 2022 16:47:44 +0800 Subject: [PATCH 7/8] style: erlfmt emqx_management --- apps/emqx_management/src/emqx_mgmt_api_configs.erl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/emqx_management/src/emqx_mgmt_api_configs.erl b/apps/emqx_management/src/emqx_mgmt_api_configs.erl index 4769d42f5..46012e755 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_configs.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_configs.erl @@ -105,9 +105,11 @@ schema("/configs_reset/:rootname") -> post => #{ tags => [conf], description => - <<"Reset the config entry specified by the query string parameter `conf_path`.
\n" - "- For a config entry that has default value, this resets it to the default value;\n" - "- For a config entry that has no default value, an error 400 will be returned">>, + << + "Reset the config entry specified by the query string parameter `conf_path`.
\n" + "- For a config entry that has default value, this resets it to the default value;\n" + "- For a config entry that has no default value, an error 400 will be returned" + >>, %% We only return "200" rather than the new configs that has been changed, as %% the schema of the changed configs is depends on the request parameter %% `conf_path`, it cannot be defined here. From db29080cd552f7a7f6a2fdc4287a517cadb3dd91 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Tue, 19 Apr 2022 16:48:16 +0800 Subject: [PATCH 8/8] chore: add erlfmt app name and update git blame ignore revs --- git-blame-ignore-revs | 1 + scripts/check-format.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/git-blame-ignore-revs b/git-blame-ignore-revs index d76cf9165..aa78ef23b 100644 --- a/git-blame-ignore-revs +++ b/git-blame-ignore-revs @@ -23,5 +23,6 @@ acb3544d4b112121b5d9414237d2af7860ccc2a3 f1acfece6b79ed69b491da03783a7adaa7627b96 # reformat apps/emqx_management aa7807baebfa5d8678025e43f386bcd9b3259d6a +bf54f571fb8b27e76ada4ca75137d96ce4211d60 # reformat apps/emqx_slow_subs 83511f8a4c1570a2c89d9c6c5b6f462520199ed8 diff --git a/scripts/check-format.sh b/scripts/check-format.sh index 9b5ada731..81108192b 100755 --- a/scripts/check-format.sh +++ b/scripts/check-format.sh @@ -13,6 +13,7 @@ APPS+=( 'apps/emqx_authn' 'apps/emqx_authz' ) APPS+=( 'lib-ee/emqx_enterprise_conf' 'lib-ee/emqx_license' ) APPS+=( 'apps/emqx_exhook') APPS+=( 'apps/emqx_retainer' 'apps/emqx_slow_subs') +APPS+=( 'apps/emqx_management') for app in "${APPS[@]}"; do echo "$app ..."