diff --git a/apps/emqx_dashboard/src/emqx_dashboard_api.erl b/apps/emqx_dashboard/src/emqx_dashboard_api.erl index deb7dc74c..874d2bf2b 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_api.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_api.erl @@ -41,7 +41,7 @@ namespace() -> "dashboard". api_spec() -> - emqx_dashboard_swagger:spec(?MODULE). + emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}). paths() -> ["/login", "/logout", "/users", "/users/:username", "/users/:username/change_pwd"]. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl index 99525a89a..9033a9b40 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl @@ -4,7 +4,7 @@ -include_lib("hocon/include/hoconsc.hrl"). %% API --export([spec/1]). +-export([spec/1, spec/2]). -export([translate_req/2]). -ifdef(TEST). @@ -24,23 +24,37 @@ -define(TO_REF(_N_, _F_), iolist_to_binary([to_bin(_N_), ".", to_bin(_F_)])). -define(TO_COMPONENTS(_M_, _F_), iolist_to_binary([<<"#/components/schemas/">>, ?TO_REF(namespace(_M_), _F_)])). --spec(spec(module()) -> {list({Path, Specs, OperationId, Options}), list(Component)} when +%% @equiv spec(Module, #{check_schema => false}) +-spec(spec(module()) -> + {list({Path, Specs, OperationId, Options}), list(Component)} when Path :: string()|binary(), Specs :: map(), OperationId :: atom(), Options :: #{filter => fun((map(), #{module => module(), path => string(), method => atom()}) -> map())}, Component :: map()). -spec(Module) -> +spec(Module) -> spec(Module, #{check_schema => false}). + +-spec(spec(module(), #{check_schema => boolean()}) -> + {list({Path, Specs, OperationId, Options}), list(Component)} when + Path :: string()|binary(), + Specs :: map(), + OperationId :: atom(), + Options :: #{filter => fun((map(), + #{module => module(), path => string(), method => atom()}) -> map())}, + Component :: map()). +spec(Module, Options) -> Paths = apply(Module, paths, []), {ApiSpec, AllRefs} = lists:foldl(fun(Path, {AllAcc, AllRefsAcc}) -> {OperationId, Specs, Refs} = parse_spec_ref(Module, Path), - {[{Path, Specs, OperationId, ?DEFAULT_FILTER} | AllAcc], + CheckSchema = support_check_schema(Options), + {[{Path, Specs, OperationId, CheckSchema} | AllAcc], Refs ++ AllRefsAcc} end, {[], []}, Paths), {ApiSpec, components(lists:usort(AllRefs))}. + -spec(translate_req(#{binding => list(), query_string => list(), body => map()}, #{module => module(), path => string(), method => atom()}) -> {ok, #{binding => list(), query_string => list(), body => map()}}| @@ -59,6 +73,10 @@ translate_req(Request, #{module := Module, path := Path, method := Method}) -> {400, 'BAD_REQUEST', iolist_to_binary(io_lib:format("~s : ~p", [Key, Reason]))} end. +support_check_schema(#{check_schema := true}) -> ?DEFAULT_FILTER; +support_check_schema(#{check_schema := Func})when is_function(Func, 2) -> #{filter => Func}; +support_check_schema(_) -> #{filter => undefined}. + parse_spec_ref(Module, Path) -> Schema = try diff --git a/apps/emqx_dashboard/test/emqx_swagger_parameter_SUITE.erl b/apps/emqx_dashboard/test/emqx_swagger_parameter_SUITE.erl index 74cb53a26..a5c458ffa 100644 --- a/apps/emqx_dashboard/test/emqx_swagger_parameter_SUITE.erl +++ b/apps/emqx_dashboard/test/emqx_swagger_parameter_SUITE.erl @@ -162,7 +162,13 @@ t_in_mix_trans_error(_Config) -> ok. t_api_spec(_Config) -> - emqx_dashboard_swagger:spec(?MODULE), + {Spec, _Components} = emqx_dashboard_swagger:spec(?MODULE), + Filter = fun(V, S) -> lists:all(fun({_, _, _, #{filter := Filter}}) -> Filter =:= V end, S) end, + ?assertEqual(true, Filter(undefined, Spec)), + {Spec1, _Components1} = emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}), + ?assertEqual(true, Filter(fun emqx_dashboard_swagger:translate_req/2, Spec1)), + {Spec2, _Components2} = emqx_dashboard_swagger:spec(?MODULE, #{check_schema => fun emqx_dashboard_swagger:translate_req/2}), + ?assertEqual(true, Filter(fun emqx_dashboard_swagger:translate_req/2, Spec2)), ok. validate(Path, ExpectParams) ->