diff --git a/apps/emqx_dashboard/include/emqx_dashboard.hrl b/apps/emqx_dashboard/include/emqx_dashboard.hrl index 12f564fe4..a4af8ae1b 100644 --- a/apps/emqx_dashboard/include/emqx_dashboard.hrl +++ b/apps/emqx_dashboard/include/emqx_dashboard.hrl @@ -16,22 +16,23 @@ -define(ADMIN, emqx_admin). -record(?ADMIN, { - username :: binary(), - pwdhash :: binary(), - description :: binary(), + username :: binary(), + pwdhash :: binary(), + description :: binary(), role = undefined :: atom(), - extra = [] :: term() %% not used so far, for future extension - }). - + %% not used so far, for future extension + extra = [] :: term() +}). -define(ADMIN_JWT, emqx_admin_jwt). -record(?ADMIN_JWT, { - token :: binary(), - username :: binary(), - exptime :: integer(), - extra = [] :: term() %% not used so far, fur future extension - }). + token :: binary(), + username :: binary(), + exptime :: integer(), + %% not used so far, fur future extension + extra = [] :: term() +}). -define(TAB_COLLECT, emqx_collect). @@ -49,27 +50,27 @@ -define(RPC_TIMEOUT, 5000). -endif. --define(DELTA_SAMPLER_LIST, - [ received +-define(DELTA_SAMPLER_LIST, [ + received, %, received_bytes - , sent + sent, %, sent_bytes - , dropped - ]). + dropped +]). --define(GAUGE_SAMPLER_LIST, - [ subscriptions - , topics - , connections - ]). +-define(GAUGE_SAMPLER_LIST, [ + subscriptions, + topics, + connections +]). -define(SAMPLER_LIST, ?GAUGE_SAMPLER_LIST ++ ?DELTA_SAMPLER_LIST). -define(DELTA_SAMPLER_RATE_MAP, #{ - received => received_msg_rate, + received => received_msg_rate, %% In 5.0.0, temporarily comment it to suppress bytes rate %received_bytes => received_bytes_rate, %sent_bytes => sent_bytes_rate, - sent => sent_msg_rate, - dropped => dropped_msg_rate - }). + sent => sent_msg_rate, + dropped => dropped_msg_rate +}). diff --git a/apps/emqx_dashboard/rebar.config b/apps/emqx_dashboard/rebar.config index df2158467..9657d0bbf 100644 --- a/apps/emqx_dashboard/rebar.config +++ b/apps/emqx_dashboard/rebar.config @@ -3,16 +3,25 @@ {deps, [{emqx, {path, "../emqx"}}]}. {edoc_opts, [{preprocess, true}]}. -{erl_opts, [warn_unused_vars, - warn_shadow_vars, - warn_unused_import, - warn_obsolete_guard, - debug_info, - {d, 'APPLICATION', emqx}]}. -{xref_checks, [undefined_function_calls, undefined_functions, - locals_not_used, deprecated_function_calls, - warnings_as_errors, deprecated_functions]}. +{erl_opts, [ + warn_unused_vars, + warn_shadow_vars, + warn_unused_import, + warn_obsolete_guard, + debug_info, + {d, 'APPLICATION', emqx} +]}. +{xref_checks, [ + undefined_function_calls, + undefined_functions, + locals_not_used, + deprecated_function_calls, + warnings_as_errors, + deprecated_functions +]}. {cover_enabled, true}. {cover_opts, [verbose]}. {cover_export_enabled, true}. {eunit_first_files, ["test/emqx_swagger_remote_schema.erl"]}. + +{project_plugins, [erlfmt]}. diff --git a/apps/emqx_dashboard/src/emqx_dashboard.app.src b/apps/emqx_dashboard/src/emqx_dashboard.app.src index 6c7fac306..4acd89464 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard.app.src +++ b/apps/emqx_dashboard/src/emqx_dashboard.app.src @@ -1,15 +1,17 @@ %% -*- mode: erlang -*- -{application, emqx_dashboard, - [{description, "EMQX Web Dashboard"}, - {vsn, "5.0.0"}, % strict semver, bump manually! - {modules, []}, - {registered, [emqx_dashboard_sup]}, - {applications, [kernel,stdlib,mnesia,minirest,emqx]}, - {mod, {emqx_dashboard_app,[]}}, - {env, []}, - {licenses, ["Apache-2.0"]}, - {maintainers, ["EMQX Team "]}, - {links, [{"Homepage", "https://emqx.io/"}, - {"Github", "https://github.com/emqx/emqx-dashboard"} - ]} - ]}. +{application, emqx_dashboard, [ + {description, "EMQX Web Dashboard"}, + % strict semver, bump manually! + {vsn, "5.0.0"}, + {modules, []}, + {registered, [emqx_dashboard_sup]}, + {applications, [kernel, stdlib, mnesia, minirest, emqx]}, + {mod, {emqx_dashboard_app, []}}, + {env, []}, + {licenses, ["Apache-2.0"]}, + {maintainers, ["EMQX Team "]}, + {links, [ + {"Homepage", "https://emqx.io/"}, + {"Github", "https://github.com/emqx/emqx-dashboard"} + ]} +]}. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl index 958e1beae..0650062f8 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl @@ -26,28 +26,32 @@ %% Mnesia bootstrap -export([mnesia/1]). --export([ add_user/3 - , force_add_user/3 - , remove_user/1 - , update_user/2 - , lookup_user/1 - , change_password/2 - , change_password/3 - , all_users/0 - , check/2 - ]). +-export([ + add_user/3, + force_add_user/3, + remove_user/1, + update_user/2, + lookup_user/1, + change_password/2, + change_password/3, + all_users/0, + check/2 +]). --export([ sign_token/2 - , verify_token/1 - , destroy_token_by_username/2 - ]). --export([ hash/1 - , verify_hash/2 - ]). +-export([ + sign_token/2, + verify_token/1, + destroy_token_by_username/2 +]). +-export([ + hash/1, + verify_hash/2 +]). --export([ add_default_user/0 - , default_username/0 - ]). +-export([ + add_default_user/0, + default_username/0 +]). -type emqx_admin() :: #?ADMIN{}. @@ -57,42 +61,52 @@ mnesia(boot) -> ok = mria:create_table(?ADMIN, [ - {type, set}, - {rlog_shard, ?DASHBOARD_SHARD}, - {storage, disc_copies}, - {record_name, ?ADMIN}, - {attributes, record_info(fields, ?ADMIN)}, - {storage_properties, [{ets, [{read_concurrency, true}, - {write_concurrency, true}]}]}]). + {type, set}, + {rlog_shard, ?DASHBOARD_SHARD}, + {storage, disc_copies}, + {record_name, ?ADMIN}, + {attributes, record_info(fields, ?ADMIN)}, + {storage_properties, [ + {ets, [ + {read_concurrency, true}, + {write_concurrency, true} + ]} + ]} + ]). %%-------------------------------------------------------------------- %% API %%-------------------------------------------------------------------- --spec(add_user(binary(), binary(), binary()) -> {ok, map()} | {error, any()}). -add_user(Username, Password, Desc) - when is_binary(Username), is_binary(Password) -> +-spec add_user(binary(), binary(), binary()) -> {ok, map()} | {error, any()}. +add_user(Username, Password, Desc) when + is_binary(Username), is_binary(Password) +-> case legal_username(Username) of true -> return( - mria:transaction(?DASHBOARD_SHARD, fun add_user_/3, [Username, Password, Desc])); + mria:transaction(?DASHBOARD_SHARD, fun add_user_/3, [Username, Password, Desc]) + ); false -> - {error, <<"Bad Username." - " Only upper and lower case letters, numbers and underscores are supported">>} + {error, << + "Bad Username." + " Only upper and lower case letters, numbers and underscores are supported" + >>} end. %% 0 - 9 or A -Z or a - z or $_ legal_username(<<>>) -> false; -legal_username(UserName) -> - nomatch /= re:run(UserName, "^[_a-zA-Z0-9]*$"). +legal_username(UserName) -> nomatch /= re:run(UserName, "^[_a-zA-Z0-9]*$"). %% black-magic: force overwrite a user force_add_user(Username, Password, Desc) -> AddFun = fun() -> - mnesia:write(#?ADMIN{username = Username, - pwdhash = hash(Password), - description = Desc}) - end, + mnesia:write(#?ADMIN{ + username = Username, + pwdhash = hash(Password), + description = Desc + }) + end, case mria:transaction(?DASHBOARD_SHARD, AddFun) of {atomic, ok} -> ok; {aborted, Reason} -> {error, Reason} @@ -101,7 +115,7 @@ force_add_user(Username, Password, Desc) -> %% @private add_user_(Username, Password, Desc) -> case mnesia:wread({?ADMIN, Username}) of - [] -> + [] -> Admin = #?ADMIN{username = Username, pwdhash = hash(Password), description = Desc}, mnesia:write(Admin), #{username => Username, description => Desc}; @@ -109,14 +123,14 @@ add_user_(Username, Password, Desc) -> mnesia:abort(<<"username_already_exist">>) end. --spec(remove_user(binary()) -> {ok, any()} | {error, any()}). +-spec remove_user(binary()) -> {ok, any()} | {error, any()}. remove_user(Username) when is_binary(Username) -> Trans = fun() -> - case lookup_user(Username) of - [] -> mnesia:abort(<<"username_not_found">>); - _ -> mnesia:delete({?ADMIN, Username}) - end - end, + case lookup_user(Username) of + [] -> mnesia:abort(<<"username_not_found">>); + _ -> mnesia:delete({?ADMIN, Username}) + end + end, case return(mria:transaction(?DASHBOARD_SHARD, Trans)) of {ok, Result} -> _ = emqx_dashboard_token:destroy_by_username(Username), @@ -125,7 +139,7 @@ remove_user(Username) when is_binary(Username) -> {error, Reason} end. --spec(update_user(binary(), binary()) -> {ok, map()} | {error, term()}). +-spec update_user(binary(), binary()) -> {ok, map()} | {error, term()}. update_user(Username, Desc) when is_binary(Username) -> return(mria:transaction(?DASHBOARD_SHARD, fun update_user_/2, [Username, Desc])). @@ -140,7 +154,8 @@ verify_hash(Origin, SaltHash) -> true -> ok; false -> error end; - _ -> error + _ -> + error end. sha256(SaltBin, Password) -> @@ -174,7 +189,8 @@ change_password_hash(Username, PasswordHash) -> {ok, Result} -> _ = emqx_dashboard_token:destroy_by_username(Username), {ok, Result}; - {error, Reason} -> {error, Reason} + {error, Reason} -> + {error, Reason} end. update_pwd(Username, Fun) -> @@ -183,30 +199,35 @@ update_pwd(Username, Fun) -> User = case lookup_user(Username) of [Admin] -> Admin; - [] -> - mnesia:abort(<<"username_not_found">>) + [] -> mnesia:abort(<<"username_not_found">>) end, mnesia:write(Fun(User)) end, return(mria:transaction(?DASHBOARD_SHARD, Trans)). - --spec(lookup_user(binary()) -> [emqx_admin()]). +-spec lookup_user(binary()) -> [emqx_admin()]. lookup_user(Username) when is_binary(Username) -> Fun = fun() -> mnesia:read(?ADMIN, Username) end, {atomic, User} = mria:ro_transaction(?DASHBOARD_SHARD, Fun), User. --spec(all_users() -> [map()]). +-spec all_users() -> [map()]. all_users() -> - lists:map(fun(#?ADMIN{username = Username, - description = Desc - }) -> - #{username => Username, - description => Desc - } - end, ets:tab2list(?ADMIN)). --spec(return({atomic | aborted, term()}) -> {ok, term()} | {error, Reason :: binary()}). + lists:map( + fun( + #?ADMIN{ + username = Username, + description = Desc + } + ) -> + #{ + username => Username, + description => Desc + } + end, + ets:tab2list(?ADMIN) + ). +-spec return({atomic | aborted, term()}) -> {ok, term()} | {error, Reason :: binary()}. return({atomic, Result}) -> {ok, Result}; return({aborted, Reason}) -> @@ -220,7 +241,7 @@ check(Username, Password) -> case lookup_user(Username) of [#?ADMIN{pwdhash = PwdHash}] -> case verify_hash(Password, PwdHash) of - ok -> ok; + ok -> ok; error -> {error, <<"password_error">>} end; [] -> @@ -252,7 +273,7 @@ destroy_token_by_username(Username, Token) -> %% Internal functions %%-------------------------------------------------------------------- --spec(add_default_user() -> {ok, map() | empty | default_user_exists } | {error, any()}). +-spec add_default_user() -> {ok, map() | empty | default_user_exists} | {error, any()}. add_default_user() -> add_default_user(binenv(default_username), binenv(default_password)). @@ -264,9 +285,8 @@ binenv(Key) -> add_default_user(Username, Password) when ?EMPTY_KEY(Username) orelse ?EMPTY_KEY(Password) -> {ok, empty}; - add_default_user(Username, Password) -> case lookup_user(Username) of [] -> add_user(Username, Password, <<"administrator">>); - _ -> {ok, default_user_exists} + _ -> {ok, default_user_exists} end. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_api.erl b/apps/emqx_dashboard/src/emqx_dashboard_api.erl index f6f1174f6..e02295b32 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_api.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_api.erl @@ -27,7 +27,7 @@ mk/2, array/1, enum/1 - ]). +]). -export([ api_spec/0, @@ -35,7 +35,7 @@ paths/0, schema/1, namespace/0 - ]). +]). -export([ login/2, @@ -43,7 +43,7 @@ users/2, user/2, change_pwd/2 - ]). +]). -define(EMPTY(V), (V == undefined orelse V == <<>>)). @@ -60,11 +60,13 @@ api_spec() -> emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true, translate_body => true}). paths() -> - [ "/login" - , "/logout" - , "/users" - , "/users/:username" - , "/users/:username/change_pwd"]. + [ + "/login", + "/logout", + "/users", + "/users/:username", + "/users/:username/change_pwd" + ]. schema("/login") -> #{ @@ -101,8 +103,10 @@ schema("/users") -> tags => [<<"dashboard">>], desc => ?DESC(list_users_api), responses => #{ - 200 => mk(array(hoconsc:ref(user)), - #{desc => ?DESC(list_users_api)}) + 200 => mk( + array(hoconsc:ref(user)), + #{desc => ?DESC(list_users_api)} + ) } }, post => #{ @@ -114,7 +118,6 @@ schema("/users") -> } } }; - schema("/users/:username") -> #{ 'operationId' => user, @@ -135,7 +138,8 @@ schema("/users/:username") -> responses => #{ 204 => <<"Delete User successfully">>, 400 => emqx_dashboard_swagger:error_codes( - [?BAD_REQUEST, ?NOT_ALLOWED], ?DESC(login_failed_response400)), + [?BAD_REQUEST, ?NOT_ALLOWED], ?DESC(login_failed_response400) + ), 404 => response_schema(404) } } @@ -151,10 +155,12 @@ schema("/users/:username/change_pwd") -> responses => #{ 204 => <<"Update user password successfully">>, 401 => emqx_dashboard_swagger:error_codes( - [?WRONG_USERNAME_OR_PWD, ?ERROR_PWD_NOT_MATCH], ?DESC(login_failed401)), + [?WRONG_USERNAME_OR_PWD, ?ERROR_PWD_NOT_MATCH], ?DESC(login_failed401) + ), 404 => response_schema(404), 400 => emqx_dashboard_swagger:error_codes( - [?BAD_REQUEST], ?DESC(login_failed_response400)) + [?BAD_REQUEST], ?DESC(login_failed_response400) + ) } } }. @@ -174,26 +180,32 @@ field(username) -> mk(binary(), #{desc => ?DESC(username), 'maxLength' => 100, example => <<"admin">>})}; field(username_in_path) -> {username, - mk(binary(), #{desc => ?DESC(username), 'maxLength' => 100, example => <<"admin">>, - in => path, required => true})}; + mk(binary(), #{ + desc => ?DESC(username), + 'maxLength' => 100, + example => <<"admin">>, + in => path, + required => true + })}; field(password) -> {password, mk(binary(), #{desc => ?DESC(password), 'maxLength' => 100, example => <<"public">>})}; field(description) -> - {description, - mk(binary(), #{desc => ?DESC(user_description), example => <<"administrator">>})}; + {description, mk(binary(), #{desc => ?DESC(user_description), example => <<"administrator">>})}; field(token) -> {token, mk(binary(), #{desc => ?DESC(token)})}; field(license) -> {license, [ - {edition, mk(enum([community, enterprise]), - #{desc => ?DESC(license), example => community})}]}; + {edition, + mk( + enum([community, enterprise]), + #{desc => ?DESC(license), example => community} + )} + ]}; field(version) -> {version, mk(string(), #{desc => ?DESC(version), example => <<"5.0.0">>})}; - field(old_pwd) -> {old_pwd, mk(binary(), #{desc => ?DESC(old_pwd)})}; - field(new_pwd) -> {new_pwd, mk(binary(), #{desc => ?DESC(new_pwd)})}. @@ -207,17 +219,20 @@ login(post, #{body := Params}) -> {ok, Token} -> ?SLOG(info, #{msg => "Dashboard login successfully", username => Username}), Version = iolist_to_binary(proplists:get_value(version, emqx_sys:info())), - {200, #{token => Token, - version => Version, - license => #{edition => emqx_release:edition()} - }}; + {200, #{ + token => Token, + version => Version, + license => #{edition => emqx_release:edition()} + }}; {error, R} -> ?SLOG(info, #{msg => "Dashboard login failed", username => Username, reason => R}), {401, ?WRONG_USERNAME_OR_PWD, <<"Auth filed">>} end. -logout(_, #{body := #{<<"username">> := Username}, - headers := #{<<"authorization">> := <<"Bearer ", Token/binary>>}}) -> +logout(_, #{ + body := #{<<"username">> := Username}, + headers := #{<<"authorization">> := <<"Bearer ", Token/binary>>} +}) -> case emqx_dashboard_admin:destroy_token_by_username(Username, Token) of ok -> ?SLOG(info, #{msg => "Dashboard logout successfully", username => Username}), @@ -229,7 +244,6 @@ logout(_, #{body := #{<<"username">> := Username}, users(get, _Request) -> {200, emqx_dashboard_admin:all_users()}; - users(post, #{body := Params}) -> Desc = maps:get(<<"description">>, Params, <<"">>), Username = maps:get(<<"username">>, Params), @@ -243,8 +257,11 @@ users(post, #{body := Params}) -> ?SLOG(info, #{msg => "Create dashboard success", username => Username}), {200, Result}; {error, Reason} -> - ?SLOG(info, #{msg => "Create dashboard failed", - username => Username, reason => Reason}), + ?SLOG(info, #{ + msg => "Create dashboard failed", + username => Username, + reason => Reason + }), {400, ?BAD_REQUEST, Reason} end end. @@ -257,7 +274,6 @@ user(put, #{bindings := #{username := Username}, body := Params}) -> {error, Reason} -> {404, ?USER_NOT_FOUND, Reason} end; - user(delete, #{bindings := #{username := Username}}) -> case Username == emqx_dashboard_admin:default_username() of true -> diff --git a/apps/emqx_dashboard/src/emqx_dashboard_app.erl b/apps/emqx_dashboard/src/emqx_dashboard_app.erl index 869db84f1..094d1cc67 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_app.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_app.erl @@ -18,9 +18,10 @@ -behaviour(application). --export([ start/2 - , stop/1 - ]). +-export([ + start/2, + stop/1 +]). -include("emqx_dashboard.hrl"). @@ -33,7 +34,8 @@ start(_StartType, _StartArgs) -> {ok, _Result} = emqx_dashboard_admin:add_default_user(), ok = emqx_dashboard_config:add_handler(), {ok, Sup}; - {error, Reason} -> {error, Reason} + {error, Reason} -> + {error, Reason} end. stop(_State) -> diff --git a/apps/emqx_dashboard/src/emqx_dashboard_bad_api.erl b/apps/emqx_dashboard/src/emqx_dashboard_bad_api.erl index 3121174a7..8671eb5b6 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_bad_api.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_bad_api.erl @@ -22,8 +22,10 @@ init(Req0, State) -> ?SLOG(warning, #{msg => "unexpected_api_access", request => Req0}), - Req = cowboy_req:reply(404, + Req = cowboy_req:reply( + 404, #{<<"content-type">> => <<"application/json">>}, <<"{\"code\": \"API_NOT_EXIST\", \"message\": \"Request Path Not Found\"}">>, - Req0), + Req0 + ), {ok, Req, State}. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_cli.erl b/apps/emqx_dashboard/src/emqx_dashboard_cli.erl index 675f015a4..677121d93 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_cli.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_cli.erl @@ -16,17 +16,17 @@ -module(emqx_dashboard_cli). --export([ load/0 - , admins/1 - , unload/0 - ]). +-export([ + load/0, + admins/1, + unload/0 +]). load() -> emqx_ctl:register_command(admins, {?MODULE, admins}, []). admins(["add", Username, Password]) -> admins(["add", Username, Password, ""]); - admins(["add", Username, Password, Desc]) -> case emqx_dashboard_admin:add_user(bin(Username), bin(Password), bin(Desc)) of {ok, _} -> @@ -34,20 +34,20 @@ admins(["add", Username, Password, Desc]) -> {error, Reason} -> emqx_ctl:print("Error: ~p~n", [Reason]) end; - admins(["passwd", Username, Password]) -> - Status = emqx_dashboard_admin:change_password(bin(Username), bin(Password)), + Status = emqx_dashboard_admin:change_password(bin(Username), bin(Password)), emqx_ctl:print("~p~n", [Status]); - admins(["del", Username]) -> - Status = emqx_dashboard_admin:remove_user(bin(Username)), + Status = emqx_dashboard_admin:remove_user(bin(Username)), emqx_ctl:print("~p~n", [Status]); - admins(_) -> emqx_ctl:usage( - [{"admins add ", "Add dashboard user"}, - {"admins passwd ", "Reset dashboard user password"}, - {"admins del ", "Delete dashboard user" }]). + [ + {"admins add ", "Add dashboard user"}, + {"admins passwd ", "Reset dashboard user password"}, + {"admins del ", "Delete dashboard user"} + ] + ). unload() -> emqx_ctl:unregister_command(admins). diff --git a/apps/emqx_dashboard/src/emqx_dashboard_error_code.erl b/apps/emqx_dashboard/src/emqx_dashboard_error_code.erl index 4f2b88c23..e12cc1fc4 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_error_code.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_error_code.erl @@ -18,12 +18,13 @@ -include_lib("emqx/include/http_api.hrl"). --export([ all/0 - , list/0 - , look_up/1 - , description/1 - , format/1 - ]). +-export([ + all/0, + list/0, + look_up/1, + description/1, + format/1 +]). all() -> [Name || {Name, _Description} <- ?ERROR_CODES]. @@ -51,6 +52,6 @@ description(Code, [_ | List]) -> format({Code, Description}) -> #{ - code => Code, + code => Code, description => Description }. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_error_code_api.erl b/apps/emqx_dashboard/src/emqx_dashboard_error_code_api.erl index 3ba260603..ff6f87258 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_error_code_api.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_error_code_api.erl @@ -21,16 +21,18 @@ -include("emqx_dashboard.hrl"). -include_lib("typerefl/include/types.hrl"). --export([ api_spec/0 - , fields/1 - , paths/0 - , schema/1 - , namespace/0 - ]). +-export([ + api_spec/0, + fields/1, + paths/0, + schema/1, + namespace/0 +]). --export([ error_codes/2 - , error_code/2 - ]). +-export([ + error_codes/2, + error_code/2 +]). namespace() -> "dashboard". @@ -38,8 +40,9 @@ api_spec() -> emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true, translate_body => true}). paths() -> - [ "/error_codes" - , "/error_codes/:code" + [ + "/error_codes", + "/error_codes/:code" ]. schema("/error_codes") -> @@ -60,10 +63,12 @@ schema("/error_codes/:code") -> security => [], description => <<"API Error Codes">>, parameters => [ - {code, hoconsc:mk(hoconsc:enum(emqx_dashboard_error_code:all()), #{ - desc => <<"API Error Codes">>, - in => path, - example => hd(emqx_dashboard_error_code:all())})} + {code, + hoconsc:mk(hoconsc:enum(emqx_dashboard_error_code:all()), #{ + desc => <<"API Error Codes">>, + in => path, + example => hd(emqx_dashboard_error_code:all()) + })} ], responses => #{ 200 => hoconsc:ref(?MODULE, error_code) @@ -77,7 +82,6 @@ fields(error_code) -> {description, hoconsc:mk(string(), #{desc => <<"Description">>})} ]. - error_codes(_, _) -> {200, emqx_dashboard_error_code:list()}. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl b/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl index 619173c8c..f1900dba5 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl @@ -9,25 +9,28 @@ -behaviour(minirest_api). --export([ api_spec/0]). +-export([api_spec/0]). --export([ paths/0 - , schema/1 - , fields/1 - ]). +-export([ + paths/0, + schema/1, + fields/1 +]). --export([ monitor/2 - , monitor_current/2 - ]). +-export([ + monitor/2, + monitor_current/2 +]). api_spec() -> emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true, translate_body => true}). paths() -> - [ "/monitor" - , "/monitor/nodes/:node" - , "/monitor_current" - , "/monitor_current/nodes/:node" + [ + "/monitor", + "/monitor/nodes/:node", + "/monitor_current", + "/monitor_current/nodes/:node" ]. schema("/monitor") -> @@ -43,7 +46,6 @@ schema("/monitor") -> } } }; - schema("/monitor/nodes/:node") -> #{ 'operationId' => monitor, @@ -57,7 +59,6 @@ schema("/monitor/nodes/:node") -> } } }; - schema("/monitor_current") -> #{ 'operationId' => monitor_current, @@ -69,7 +70,6 @@ schema("/monitor_current") -> } } }; - schema("/monitor_current/nodes/:node") -> #{ 'operationId' => monitor_current, @@ -102,17 +102,19 @@ parameter_node() -> }, {node, hoconsc:mk(binary(), Info)}. - fields(sampler) -> Samplers = - [{SamplerName, hoconsc:mk(integer(), #{desc => swagger_desc(SamplerName)})} - || SamplerName <- ?SAMPLER_LIST], + [ + {SamplerName, hoconsc:mk(integer(), #{desc => swagger_desc(SamplerName)})} + || SamplerName <- ?SAMPLER_LIST + ], [{time_stamp, hoconsc:mk(non_neg_integer(), #{desc => <<"Timestamp">>})} | Samplers]; - fields(sampler_current) -> Names = maps:values(?DELTA_SAMPLER_RATE_MAP) ++ ?GAUGE_SAMPLER_LIST, - [{SamplerName, hoconsc:mk(integer(), #{desc => swagger_desc(SamplerName)})} - || SamplerName <- Names]. + [ + {SamplerName, hoconsc:mk(integer(), #{desc => swagger_desc(SamplerName)})} + || SamplerName <- Names + ]. %% ------------------------------------------------------------------------------------------------- %% API @@ -141,26 +143,39 @@ monitor_current(get, #{bindings := Bindings}) -> %% ------------------------------------------------------------------------------------------------- %% Internal -swagger_desc(received) -> swagger_desc_format("Received messages "); -swagger_desc(received_bytes) -> swagger_desc_format("Received bytes "); -swagger_desc(sent) -> swagger_desc_format("Sent messages "); -swagger_desc(sent_bytes) -> swagger_desc_format("Sent bytes "); -swagger_desc(dropped) -> swagger_desc_format("Dropped messages "); +swagger_desc(received) -> + swagger_desc_format("Received messages "); +swagger_desc(received_bytes) -> + swagger_desc_format("Received bytes "); +swagger_desc(sent) -> + swagger_desc_format("Sent messages "); +swagger_desc(sent_bytes) -> + swagger_desc_format("Sent bytes "); +swagger_desc(dropped) -> + swagger_desc_format("Dropped messages "); swagger_desc(subscriptions) -> - <<"Subscriptions at the time of sampling." - " Can only represent the approximate state">>; + << + "Subscriptions at the time of sampling." + " Can only represent the approximate state" + >>; swagger_desc(topics) -> - <<"Count topics at the time of sampling." - " Can only represent the approximate state">>; + << + "Count topics at the time of sampling." + " Can only represent the approximate state" + >>; swagger_desc(connections) -> - <<"Connections at the time of sampling." - " Can only represent the approximate state">>; - -swagger_desc(received_msg_rate) -> swagger_desc_format("Dropped messages ", per); + << + "Connections at the time of sampling." + " Can only represent the approximate state" + >>; +swagger_desc(received_msg_rate) -> + swagger_desc_format("Dropped messages ", per); %swagger_desc(received_bytes_rate) -> swagger_desc_format("Received bytes ", per); -swagger_desc(sent_msg_rate) -> swagger_desc_format("Sent messages ", per); +swagger_desc(sent_msg_rate) -> + swagger_desc_format("Sent messages ", per); %swagger_desc(sent_bytes_rate) -> swagger_desc_format("Sent bytes ", per); -swagger_desc(dropped_msg_rate) -> swagger_desc_format("Dropped messages ", per). +swagger_desc(dropped_msg_rate) -> + swagger_desc_format("Dropped messages ", per). swagger_desc_format(Format) -> swagger_desc_format(Format, last). diff --git a/apps/emqx_dashboard/src/emqx_dashboard_sup.erl b/apps/emqx_dashboard/src/emqx_dashboard_sup.erl index dee4a6aba..6b9e2adcb 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_sup.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_sup.erl @@ -28,8 +28,8 @@ start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> - {ok, {{one_for_one, 10, 100}, - [ + {ok, + {{one_for_one, 10, 100}, [ ?CHILD(emqx_dashboard_token), ?CHILD(emqx_dashboard_monitor), ?CHILD(emqx_dashboard_config) diff --git a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl index 039847704..e84d6f0af 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl @@ -407,7 +407,8 @@ trans_description(Spec, Hocon) -> Struct -> to_bin(Struct) end, case Desc of - undefined -> Spec; + undefined -> + Spec; Desc -> Desc1 = binary:replace(Desc, [<<"
\n">>, <<"\n">>], <<"
">>, [global]), Spec#{description => Desc1} diff --git a/apps/emqx_dashboard/src/emqx_dashboard_token.erl b/apps/emqx_dashboard/src/emqx_dashboard_token.erl index 2ec73d6e3..fc693daf1 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_token.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_token.erl @@ -18,12 +18,13 @@ -include("emqx_dashboard.hrl"). --export([ sign/2 - , verify/1 - , lookup/1 - , destroy/1 - , destroy_by_username/1 - ]). +-export([ + sign/2, + verify/1, + lookup/1, + destroy/1, + destroy_by_username/1 +]). -boot_mnesia({mnesia, [boot]}). @@ -42,54 +43,60 @@ -export([start_link/0, salt/0]). --export([ init/1 - , handle_call/3 - , handle_cast/2 - , handle_info/2 - , terminate/2 - , code_change/3 - ]). +-export([ + init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3 +]). %%-------------------------------------------------------------------- %% jwt function --spec(sign(Username :: binary(), Password :: binary()) -> - {ok, Token :: binary()} | {error, Reason :: term()}). +-spec sign(Username :: binary(), Password :: binary()) -> + {ok, Token :: binary()} | {error, Reason :: term()}. sign(Username, Password) -> do_sign(Username, Password). --spec(verify(Token :: binary()) -> Result :: ok | {error, token_timeout | not_found}). +-spec verify(Token :: binary()) -> Result :: ok | {error, token_timeout | not_found}. verify(Token) -> do_verify(Token). --spec(destroy(KeyOrKeys :: list() | binary() | #?ADMIN_JWT{}) -> ok). +-spec destroy(KeyOrKeys :: list() | binary() | #?ADMIN_JWT{}) -> ok. destroy([]) -> ok; -destroy(JWTorTokenList) when is_list(JWTorTokenList)-> +destroy(JWTorTokenList) when is_list(JWTorTokenList) -> lists:foreach(fun destroy/1, JWTorTokenList); destroy(#?ADMIN_JWT{token = Token}) -> destroy(Token); -destroy(Token) when is_binary(Token)-> +destroy(Token) when is_binary(Token) -> do_destroy(Token). --spec(destroy_by_username(Username :: binary()) -> ok). +-spec destroy_by_username(Username :: binary()) -> ok. destroy_by_username(Username) -> do_destroy_by_username(Username). %% @doc create 4 bytes salt. --spec(salt() -> binary()). +-spec salt() -> binary(). salt() -> <> = crypto:strong_rand_bytes(2), iolist_to_binary(io_lib:format("~4.16.0b", [X])). mnesia(boot) -> ok = mria:create_table(?TAB, [ - {type, set}, - {rlog_shard, ?DASHBOARD_SHARD}, - {storage, disc_copies}, - {record_name, ?ADMIN_JWT}, - {attributes, record_info(fields, ?ADMIN_JWT)}, - {storage_properties, [{ets, [{read_concurrency, true}, - {write_concurrency, true}]}]}]). + {type, set}, + {rlog_shard, ?DASHBOARD_SHARD}, + {storage, disc_copies}, + {record_name, ?ADMIN_JWT}, + {attributes, record_info(fields, ?ADMIN_JWT)}, + {storage_properties, [ + {ets, [ + {read_concurrency, true}, + {write_concurrency, true} + ]} + ]} + ]). %%-------------------------------------------------------------------- %% jwt apply @@ -110,15 +117,17 @@ do_sign(Username, Password) -> _ = mria:transaction(?DASHBOARD_SHARD, fun mnesia:write/1, [JWTRec]), {ok, Token}. -do_verify(Token)-> +do_verify(Token) -> case lookup(Token) of {ok, JWT = #?ADMIN_JWT{exptime = ExpTime}} -> case ExpTime > erlang:system_time(millisecond) of true -> NewJWT = JWT#?ADMIN_JWT{exptime = jwt_expiration_time()}, - {atomic, Res} = mria:transaction(?DASHBOARD_SHARD, - fun mnesia:write/1, - [NewJWT]), + {atomic, Res} = mria:transaction( + ?DASHBOARD_SHARD, + fun mnesia:write/1, + [NewJWT] + ), Res; _ -> {error, token_timeout} @@ -137,7 +146,7 @@ do_destroy_by_username(Username) -> %%-------------------------------------------------------------------- %% jwt internal util function --spec(lookup(Token :: binary()) -> {ok, #?ADMIN_JWT{}} | {error, not_found}). +-spec lookup(Token :: binary()) -> {ok, #?ADMIN_JWT{}} | {error, not_found}. lookup(Token) -> Fun = fun() -> mnesia:read(?TAB, Token) end, case mria:ro_transaction(?DASHBOARD_SHARD, Fun) of @@ -167,9 +176,9 @@ token_ttl() -> format(Token, Username, ExpTime) -> #?ADMIN_JWT{ - token = Token, + token = Token, username = Username, - exptime = ExpTime + exptime = ExpTime }. %%-------------------------------------------------------------------- @@ -210,8 +219,9 @@ timer_clean(Pid) -> -dialyzer({nowarn_function, clean_expired_jwt/1}). clean_expired_jwt(Now) -> - Spec = [{#?ADMIN_JWT{exptime = '$1', token = '$2', _ = '_'}, - [{'<', '$1', Now}], ['$2']}], - {atomic, JWTList} = mria:ro_transaction(?DASHBOARD_SHARD, - fun() -> mnesia:select(?TAB, Spec) end), + Spec = [{#?ADMIN_JWT{exptime = '$1', token = '$2', _ = '_'}, [{'<', '$1', Now}], ['$2']}], + {atomic, JWTList} = mria:ro_transaction( + ?DASHBOARD_SHARD, + fun() -> mnesia:select(?TAB, Spec) end + ), ok = destroy(JWTList). diff --git a/apps/emqx_dashboard/src/proto/emqx_dashboard_proto_v1.erl b/apps/emqx_dashboard/src/proto/emqx_dashboard_proto_v1.erl index bcfa9f0d2..7ec976702 100644 --- a/apps/emqx_dashboard/src/proto/emqx_dashboard_proto_v1.erl +++ b/apps/emqx_dashboard/src/proto/emqx_dashboard_proto_v1.erl @@ -18,10 +18,11 @@ -behaviour(emqx_bpapi). --export([ introduced_in/0 - , do_sample/2 - , current_rate/1 - ]). +-export([ + introduced_in/0, + do_sample/2, + current_rate/1 +]). -include("emqx_dashboard.hrl"). -include_lib("emqx/include/bpapi.hrl"). @@ -29,7 +30,7 @@ introduced_in() -> "5.0.0". --spec do_sample(node(), Latest:: pos_integer() | infinity) -> list(map()) | emqx_rpc:badrpc(). +-spec do_sample(node(), Latest :: pos_integer() | infinity) -> list(map()) | emqx_rpc:badrpc(). do_sample(Node, Latest) -> rpc:call(Node, emqx_dashboard_monitor, do_sample, [Node, Latest], ?RPC_TIMEOUT). diff --git a/apps/emqx_dashboard/test/emqx_dashboard_admin_SUITE.erl b/apps/emqx_dashboard/test/emqx_dashboard_admin_SUITE.erl index 23a92cb18..8c9d36912 100644 --- a/apps/emqx_dashboard/test/emqx_dashboard_admin_SUITE.erl +++ b/apps/emqx_dashboard/test/emqx_dashboard_admin_SUITE.erl @@ -43,7 +43,7 @@ end_per_suite(Config) -> end_per_testcase(_, _Config) -> All = emqx_dashboard_admin:all_users(), - [emqx_dashboard_admin:remove_user(Name) || #{username := Name} <- All]. + [emqx_dashboard_admin:remove_user(Name) || #{username := Name} <- All]. end_suite() -> application:unload(emqx_management), @@ -144,7 +144,7 @@ t_update_user(_) -> UpdateUser = maps:get(username, NewUserInfo), NewDesc = maps:get(description, NewUserInfo), - {error,<<"username_not_found">>} = emqx_dashboard_admin:update_user(BadUpdateUser, NewDesc), + {error, <<"username_not_found">>} = emqx_dashboard_admin:update_user(BadUpdateUser, NewDesc), ok. t_change_password(_) -> @@ -160,7 +160,7 @@ t_change_password(_) -> {ok, ok} = emqx_dashboard_admin:change_password(User, OldPassword, NewPassword), %% change pwd again - {error,<<"password_error">>} = + {error, <<"password_error">>} = emqx_dashboard_admin:change_password(User, OldPassword, NewPassword), {error, <<"username_not_found">>} = @@ -185,4 +185,3 @@ t_clean_token(_) -> timer:sleep(5), {error, not_found} = emqx_dashboard_admin:verify_token(Token2), ok. - diff --git a/apps/emqx_management/src/emqx_mgmt_api_banned.erl b/apps/emqx_management/src/emqx_mgmt_api_banned.erl index 0fe8d56f7..1cf87b367 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_banned.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_banned.erl @@ -158,7 +158,8 @@ banned(post, #{body := Body}) -> {400, 'BAD_REQUEST', list_to_binary(Reason)}; Ban -> case emqx_banned:create(Ban) of - {ok, Banned} -> {200, format(Banned)}; + {ok, Banned} -> + {200, format(Banned)}; {error, {already_exist, Old}} -> OldBannedFormat = emqx_json:encode(format(Old)), {400, 'ALREADY_EXISTS', OldBannedFormat} diff --git a/git-blame-ignore-revs b/git-blame-ignore-revs index fd8910521..1879071d6 100644 --- a/git-blame-ignore-revs +++ b/git-blame-ignore-revs @@ -33,3 +33,5 @@ b168102615e574df15ec6a91304747b4637a9171 b4451823350ec46126c49ca915b4b169dd4cf49e # reformat apps/emqx_auto_subscribe and apps/emqx_conf a4feb3e6e95c18cb531416112e57520c5ba00d40 +# reformat apps/emqx_dashboard +fda246814b38ced2d229c42307c447970b09f3ab diff --git a/scripts/check-format.sh b/scripts/check-format.sh index d64279764..d97863eec 100755 --- a/scripts/check-format.sh +++ b/scripts/check-format.sh @@ -17,6 +17,7 @@ APPS+=( 'apps/emqx_management') APPS+=( 'apps/emqx_psk') APPS+=( 'apps/emqx_plugin_libs' 'apps/emqx_machine' 'apps/emqx_statsd' ) APPS+=( 'apps/emqx_auto_subscribe' 'apps/emqx_conf') +APPS+=( 'apps/emqx_dashboard') for app in "${APPS[@]}"; do echo "$app ..."