diff --git a/apps/emqx_gateway/src/emqx_gateway_api_authn.erl b/apps/emqx_gateway/src/emqx_gateway_api_authn.erl index 105a96989..143507b0b 100644 --- a/apps/emqx_gateway/src/emqx_gateway_api_authn.erl +++ b/apps/emqx_gateway/src/emqx_gateway_api_authn.erl @@ -82,17 +82,15 @@ authn(get, #{bindings := #{name := Name0}}) -> authn(put, #{bindings := #{name := Name0}, body := Body}) -> with_gateway(Name0, fun(GwName, _) -> - %% TODO: return the authn instances? - ok = emqx_gateway_http:update_authn(GwName, Body), - {204} + {ok, Authn} = emqx_gateway_http:update_authn(GwName, Body), + {200, Authn} end); authn(post, #{bindings := #{name := Name0}, body := Body}) -> with_gateway(Name0, fun(GwName, _) -> - %% TODO: return the authn instances? - ok = emqx_gateway_http:add_authn(GwName, Body), - {204} + {ok, Authn} = emqx_gateway_http:add_authn(GwName, Body), + {201, Authn} end); authn(delete, #{bindings := #{name := Name0}}) -> @@ -181,7 +179,7 @@ schema("/gateway/:name/authentication") -> , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) , 500 => error_codes([?INTERNAL_ERROR], <<"Ineternal Server Error">>) - , 204 => <<"Updated">> %% XXX: ??? return the updated object + , 200 => schema_authn() } }, post => @@ -193,7 +191,7 @@ schema("/gateway/:name/authentication") -> , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) , 500 => error_codes([?INTERNAL_ERROR], <<"Ineternal Server Error">>) - , 204 => <<"Added">> + , 201 => schema_authn() } }, delete => diff --git a/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl b/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl index f1744363c..2a16907f8 100644 --- a/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl +++ b/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl @@ -93,8 +93,9 @@ listeners(post, #{bindings := #{name := Name0}, body := LConf}) -> undefined -> ListenerId = emqx_gateway_utils:listener_id( GwName, Type, LName), - ok = emqx_gateway_http:add_listener(ListenerId, LConf), - {204}; + {ok, RespConf} = emqx_gateway_http:add_listener( + ListenerId, LConf), + {201, RespConf}; _ -> return_http_error(400, "Listener name has occupied") end @@ -123,8 +124,8 @@ listeners_insta(put, #{body := LConf, }) -> ListenerId = emqx_mgmt_util:urldecode(ListenerId0), with_gateway(Name0, fun(_GwName, _) -> - ok = emqx_gateway_http:update_listener(ListenerId, LConf), - {204} + {ok, RespConf} = emqx_gateway_http:update_listener(ListenerId, LConf), + {200, RespConf} end). listeners_insta_authn(get, #{bindings := #{name := Name0, @@ -145,16 +146,17 @@ listeners_insta_authn(post, #{body := Conf, id := ListenerId0}}) -> ListenerId = emqx_mgmt_util:urldecode(ListenerId0), with_gateway(Name0, fun(GwName, _) -> - ok = emqx_gateway_http:add_authn(GwName, ListenerId, Conf), - {204} + {ok, Authn} = emqx_gateway_http:add_authn(GwName, ListenerId, Conf), + {201, Authn} end); listeners_insta_authn(put, #{body := Conf, bindings := #{name := Name0, id := ListenerId0}}) -> ListenerId = emqx_mgmt_util:urldecode(ListenerId0), with_gateway(Name0, fun(GwName, _) -> - ok = emqx_gateway_http:update_authn(GwName, ListenerId, Conf), - {204} + {ok, Authn} = emqx_gateway_http:update_authn( + GwName, ListenerId, Conf), + {200, Authn} end); listeners_insta_authn(delete, #{bindings := #{name := Name0, id := ListenerId0}}) -> @@ -246,7 +248,9 @@ schema("/gateway/:name/listeners") -> , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) , 500 => error_codes([?INTERNAL_ERROR], <<"Ineternal Server Error">>) - , 204 => <<"Created">> + , 201 => emqx_dashboard_swagger:schema_with_examples( + ref(listener), + examples_listener_list()) } } }; @@ -290,7 +294,9 @@ schema("/gateway/:name/listeners/:id") -> , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) , 500 => error_codes([?INTERNAL_ERROR], <<"Ineternal Server Error">>) - , 200 => <<"Updated">> + , 200 => emqx_dashboard_swagger:schema_with_examples( + ref(listener), + examples_listener()) } } }; @@ -319,7 +325,7 @@ schema("/gateway/:name/listeners/:id/authentication") -> , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) , 500 => error_codes([?INTERNAL_ERROR], <<"Ineternal Server Error">>) - , 204 => <<"Added">> + , 201 => schema_authn() } }, put => @@ -332,7 +338,7 @@ schema("/gateway/:name/listeners/:id/authentication") -> , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) , 500 => error_codes([?INTERNAL_ERROR], <<"Ineternal Server Error">>) - , 204 => <<"Updated">> + , 200 => schema_authn() } }, delete => @@ -344,7 +350,7 @@ schema("/gateway/:name/listeners/:id/authentication") -> , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) , 500 => error_codes([?INTERNAL_ERROR], <<"Ineternal Server Error">>) - , 204 => <<"Deleted">> + , 200 => <<"Deleted">> } } }; @@ -431,9 +437,7 @@ schema("/gateway/:name/listeners/:id/authentication/users/:uid") -> , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) , 500 => error_codes([?INTERNAL_ERROR], <<"Ineternal Server Error">>) - , 200 => emqx_dashboard_swagger:schema_with_example( - ref(emqx_authn_api, response_user), - emqx_authn_api:response_user_examples()) + , 204 => <<"Deleted">> } } }; @@ -451,8 +455,7 @@ schema("/gateway/:name/listeners/:id/authentication/import_users") -> #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - %% XXX: Put a hint message into 204 return ? + <<"Ineternal Server Error">>) , 204 => <<"Imported">> } } diff --git a/apps/emqx_gateway/src/emqx_gateway_conf.erl b/apps/emqx_gateway/src/emqx_gateway_conf.erl index e97b0062d..c39819329 100644 --- a/apps/emqx_gateway/src/emqx_gateway_conf.erl +++ b/apps/emqx_gateway/src/emqx_gateway_conf.erl @@ -59,7 +59,8 @@ -define(AUTHN_BIN, ?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME_BINARY). -type atom_or_bin() :: atom() | binary(). --type ok_or_err() :: ok_or_err(). +-type ok_or_err() :: ok | {error, term()}. +-type map_or_err() :: map() | {error, term()}. -type listener_ref() :: {ListenerType :: atom_or_bin(), ListenerName :: atom_or_bin()}. @@ -85,7 +86,8 @@ load_gateway(GwName, Conf) -> {Ls, Conf1} -> Conf1#{<<"listeners">> => unconvert_listeners(Ls)} end, - update({?FUNCTION_NAME, bin(GwName), NConf}). + %% TODO: + ret_ok_err(update({?FUNCTION_NAME, bin(GwName), NConf})). %% @doc convert listener array to map unconvert_listeners(Ls) when is_list(Ls) -> @@ -111,13 +113,14 @@ update_gateway(GwName, Conf0) -> Exclude0 = [listeners, ?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME_ATOM], Exclude1 = [atom_to_binary(K, utf8) || K <- Exclude0], Conf = maps:without(Exclude0 ++ Exclude1, Conf0), - update({?FUNCTION_NAME, bin(GwName), Conf}). + + ret_ok_err(update({?FUNCTION_NAME, bin(GwName), Conf})). %% FIXME: delete cert files ?? -spec unload_gateway(atom_or_bin()) -> ok_or_err(). unload_gateway(GwName) -> - update({?FUNCTION_NAME, bin(GwName)}). + ret_ok_err(update({?FUNCTION_NAME, bin(GwName)})). %% @doc Get the gateway configurations. %% Missing fields are filled with default values. This function is typically @@ -139,18 +142,20 @@ convert_listeners(GwName, Ls) when is_map(Ls) -> lists:append([do_convert_listener(GwName, Type, maps:to_list(Conf)) || {Type, Conf} <- maps:to_list(Ls)]). -do_convert_listener(GwName, Type, Conf) -> - [begin - ListenerId = emqx_gateway_utils:listener_id(GwName, Type, LName), - Running = emqx_gateway_utils:is_running(ListenerId, LConf), - bind2str( - LConf#{ - id => ListenerId, - type => Type, - name => LName, - running => Running - }) - end || {LName, LConf} <- Conf, is_map(LConf)]. +do_convert_listener(GwName, LType, Conf) -> + [ do_convert_listener2(GwName, LType, LName, LConf) + || {LName, LConf} <- Conf, is_map(LConf)]. + +do_convert_listener2(GwName, LType, LName, LConf) -> + ListenerId = emqx_gateway_utils:listener_id(GwName, LType, LName), + Running = emqx_gateway_utils:is_running(ListenerId, LConf), + bind2str( + LConf#{ + id => ListenerId, + type => LType, + name => LName, + running => Running + }). bind2str(LConf = #{bind := Bind}) when is_integer(Bind) -> maps:put(bind, integer_to_binary(Bind), LConf); @@ -194,48 +199,56 @@ listener(ListenerId) -> {error, Reason} end. --spec add_listener(atom_or_bin(), listener_ref(), map()) -> ok_or_err(). +-spec add_listener(atom_or_bin(), listener_ref(), map()) -> map_or_err(). add_listener(GwName, ListenerRef, Conf) -> - update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf}). + ret_listener_or_err( + GwName, ListenerRef, + update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf})). --spec update_listener(atom_or_bin(), listener_ref(), map()) -> ok_or_err(). +-spec update_listener(atom_or_bin(), listener_ref(), map()) -> map_or_err(). update_listener(GwName, ListenerRef, Conf) -> - update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf}). + ret_listener_or_err( + GwName, ListenerRef, + update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf})). -spec remove_listener(atom_or_bin(), listener_ref()) -> ok_or_err(). remove_listener(GwName, ListenerRef) -> - update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef)}). + ret_ok_err(update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef)})). --spec add_authn(atom_or_bin(), map()) -> ok_or_err(). +-spec add_authn(atom_or_bin(), map()) -> map_or_err(). add_authn(GwName, Conf) -> - update({?FUNCTION_NAME, bin(GwName), Conf}). + ret_authn(GwName, update({?FUNCTION_NAME, bin(GwName), Conf})). --spec add_authn(atom_or_bin(), listener_ref(), map()) -> ok_or_err(). +-spec add_authn(atom_or_bin(), listener_ref(), map()) -> map_or_err(). add_authn(GwName, ListenerRef, Conf) -> - update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf}). + ret_authn( + GwName, ListenerRef, + update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf})). --spec update_authn(atom_or_bin(), map()) -> ok_or_err(). +-spec update_authn(atom_or_bin(), map()) -> map_or_err(). update_authn(GwName, Conf) -> - update({?FUNCTION_NAME, bin(GwName), Conf}). + ret_authn(GwName, update({?FUNCTION_NAME, bin(GwName), Conf})). --spec update_authn(atom_or_bin(), listener_ref(), map()) -> ok_or_err(). +-spec update_authn(atom_or_bin(), listener_ref(), map()) -> map_or_err(). update_authn(GwName, ListenerRef, Conf) -> - update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf}). + ret_authn( + GwName, ListenerRef, + update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef), Conf})). -spec remove_authn(atom_or_bin()) -> ok_or_err(). remove_authn(GwName) -> - update({?FUNCTION_NAME, bin(GwName)}). + ret_ok_err(update({?FUNCTION_NAME, bin(GwName)})). -spec remove_authn(atom_or_bin(), listener_ref()) -> ok_or_err(). remove_authn(GwName, ListenerRef) -> - update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef)}). + ret_ok_err(update({?FUNCTION_NAME, bin(GwName), bin(ListenerRef)})). %% @private update(Req) -> res(emqx_conf:update([gateway], Req, #{override_to => cluster})). -res({ok, _Result}) -> ok; -res({error, {pre_config_update, emqx_gateway_conf, Reason}}) -> {error, Reason}; +res({ok, Result}) -> {ok, Result}; +res({error, {error, {pre_config_update,emqx_gateway_conf,Reason}}}) -> {error, Reason}; res({error, Reason}) -> {error, Reason}. bin({LType, LName}) -> @@ -245,6 +258,32 @@ bin(A) when is_atom(A) -> bin(B) when is_binary(B) -> B. +ret_ok_err({ok, _}) -> ok; +ret_ok_err(Err) -> Err. + +ret_authn(GwName, {ok, #{raw_config := GwConf}}) -> + Authn = emqx_map_lib:deep_get( + [bin(GwName), <<"authentication">>], + GwConf), + {ok, Authn}; +ret_authn(_GwName, Err) -> Err. + +ret_authn(GwName, {LType, LName}, {ok, #{raw_config := GwConf}}) -> + Authn = emqx_map_lib:deep_get( + [bin(GwName), <<"listeners">>, bin(LType), + bin(LName), <<"authentication">>], + GwConf), + {ok, Authn}; +ret_authn(_, _, Err) -> Err. + +ret_listener_or_err(GwName, {LType, LName}, {ok, #{raw_config := GwConf}}) -> + LConf = emqx_map_lib:deep_get( + [bin(GwName), <<"listeners">>, bin(LType), bin(LName)], + GwConf), + {ok, do_convert_listener2(GwName, LType, LName, LConf)}; +ret_listener_or_err(_, _, Err) -> + Err. + %%-------------------------------------------------------------------- %% Config Handler %%-------------------------------------------------------------------- diff --git a/apps/emqx_gateway/src/emqx_gateway_http.erl b/apps/emqx_gateway/src/emqx_gateway_http.erl index 98344f968..2a9840a9c 100644 --- a/apps/emqx_gateway/src/emqx_gateway_http.erl +++ b/apps/emqx_gateway/src/emqx_gateway_http.erl @@ -146,14 +146,14 @@ get_listeners_status(GwName, Config) -> %% Mgmt APIs - listeners %%-------------------------------------------------------------------- --spec add_listener(atom() | binary(), map()) -> ok. +-spec add_listener(atom() | binary(), map()) -> {ok, map()}. add_listener(ListenerId, NewConf0) -> {GwName, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId), NewConf = maps:without([<<"id">>, <<"name">>, <<"type">>, <<"running">>], NewConf0), confexp(emqx_gateway_conf:add_listener(GwName, {Type, Name}, NewConf)). --spec update_listener(atom() | binary(), map()) -> ok. +-spec update_listener(atom() | binary(), map()) -> {ok, map()}. update_listener(ListenerId, NewConf0) -> {GwName, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId), @@ -194,23 +194,23 @@ wrap_chain_name(ChainName, Conf) -> Conf end. --spec add_authn(gateway_name(), map()) -> ok. +-spec add_authn(gateway_name(), map()) -> {ok, map()}. add_authn(GwName, AuthConf) -> confexp(emqx_gateway_conf:add_authn(GwName, AuthConf)). --spec add_authn(gateway_name(), binary(), map()) -> ok. +-spec add_authn(gateway_name(), binary(), map()) -> {ok, map()}. add_authn(GwName, ListenerId, AuthConf) -> - {_, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId), - confexp(emqx_gateway_conf:add_authn(GwName, {Type, Name}, AuthConf)). + {_, LType, LName} = emqx_gateway_utils:parse_listener_id(ListenerId), + confexp(emqx_gateway_conf:add_authn(GwName, {LType, LName}, AuthConf)). --spec update_authn(gateway_name(), map()) -> ok. +-spec update_authn(gateway_name(), map()) -> {ok, map()}. update_authn(GwName, AuthConf) -> confexp(emqx_gateway_conf:update_authn(GwName, AuthConf)). --spec update_authn(gateway_name(), binary(), map()) -> ok. +-spec update_authn(gateway_name(), binary(), map()) -> {ok, map()}. update_authn(GwName, ListenerId, AuthConf) -> - {_, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId), - confexp(emqx_gateway_conf:update_authn(GwName, {Type, Name}, AuthConf)). + {_, LType, LName} = emqx_gateway_utils:parse_listener_id(ListenerId), + confexp(emqx_gateway_conf:update_authn(GwName, {LType, LName}, AuthConf)). -spec remove_authn(gateway_name()) -> ok. remove_authn(GwName) -> @@ -218,10 +218,11 @@ remove_authn(GwName) -> -spec remove_authn(gateway_name(), binary()) -> ok. remove_authn(GwName, ListenerId) -> - {_, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId), - confexp(emqx_gateway_conf:remove_authn(GwName, {Type, Name})). + {_, LType, LName} = emqx_gateway_utils:parse_listener_id(ListenerId), + confexp(emqx_gateway_conf:remove_authn(GwName, {LType, LName})). confexp(ok) -> ok; +confexp({ok, Res}) -> {ok, Res}; confexp({error, not_found}) -> error({update_conf_error, not_found}); confexp({error, already_exist}) -> diff --git a/apps/emqx_gateway/test/emqx_gateway_api_SUITE.erl b/apps/emqx_gateway/test/emqx_gateway_api_SUITE.erl index 8e25a4e6e..3ae9bcc12 100644 --- a/apps/emqx_gateway/test/emqx_gateway_api_SUITE.erl +++ b/apps/emqx_gateway/test/emqx_gateway_api_SUITE.erl @@ -196,12 +196,12 @@ t_authn(_) -> backend => <<"built-in-database">>, user_id_type => <<"clientid">> }, - {204, _} = request(post, "/gateway/stomp/authentication", AuthConf), + {201, _} = request(post, "/gateway/stomp/authentication", AuthConf), {200, ConfResp} = request(get, "/gateway/stomp/authentication"), assert_confs(AuthConf, ConfResp), AuthConf2 = maps:merge(AuthConf, #{user_id_type => <<"username">>}), - {204, _} = request(put, "/gateway/stomp/authentication", AuthConf2), + {200, _} = request(put, "/gateway/stomp/authentication", AuthConf2), {200, ConfResp2} = request(get, "/gateway/stomp/authentication"), assert_confs(AuthConf2, ConfResp2), @@ -219,7 +219,7 @@ t_authn_data_mgmt(_) -> backend => <<"built-in-database">>, user_id_type => <<"clientid">> }, - {204, _} = request(post, "/gateway/stomp/authentication", AuthConf), + {201, _} = request(post, "/gateway/stomp/authentication", AuthConf), {200, ConfResp} = request(get, "/gateway/stomp/authentication"), assert_confs(AuthConf, ConfResp), @@ -262,14 +262,14 @@ t_listeners(_) -> type => <<"tcp">>, bind => <<"61613">> }, - {204, _} = request(post, "/gateway/stomp/listeners", LisConf), + {201, _} = request(post, "/gateway/stomp/listeners", LisConf), {200, ConfResp} = request(get, "/gateway/stomp/listeners"), assert_confs([LisConf], ConfResp), {200, ConfResp1} = request(get, "/gateway/stomp/listeners/stomp:tcp:def"), assert_confs(LisConf, ConfResp1), LisConf2 = maps:merge(LisConf, #{bind => <<"61614">>}), - {204, _} = request( + {200, _} = request( put, "/gateway/stomp/listeners/stomp:tcp:def", LisConf2 @@ -298,12 +298,12 @@ t_listeners_authn(_) -> user_id_type => <<"clientid">> }, Path = "/gateway/stomp/listeners/stomp:tcp:def/authentication", - {204, _} = request(post, Path, AuthConf), + {201, _} = request(post, Path, AuthConf), {200, ConfResp2} = request(get, Path), assert_confs(AuthConf, ConfResp2), AuthConf2 = maps:merge(AuthConf, #{user_id_type => <<"username">>}), - {204, _} = request(put, Path, AuthConf2), + {200, _} = request(put, Path, AuthConf2), {200, ConfResp3} = request(get, Path), assert_confs(AuthConf2, ConfResp3), @@ -325,7 +325,7 @@ t_listeners_authn_data_mgmt(_) -> user_id_type => <<"clientid">> }, Path = "/gateway/stomp/listeners/stomp:tcp:def/authentication", - {204, _} = request(post, Path, AuthConf), + {201, _} = request(post, Path, AuthConf), {200, ConfResp2} = request(get, Path), assert_confs(AuthConf, ConfResp2),