mirror of
https://github.com/processone/ejabberd
synced 2025-10-03 01:39:35 +02:00
Merge pull request #4357 from badlop/adhoc_api
New mod_adhoc_api and related improvements
This commit is contained in:
commit
418ca34c85
19 changed files with 1266 additions and 130 deletions
|
@ -23,8 +23,6 @@
|
|||
|
||||
%%%% definitions
|
||||
|
||||
%% @format-begin
|
||||
|
||||
-module(commands_tests).
|
||||
|
||||
-compile(export_all).
|
||||
|
@ -56,10 +54,29 @@ single_cases() ->
|
|||
single_test(http_tuple),
|
||||
single_test(http_list_tuple),
|
||||
single_test(http_list_tuple_map),
|
||||
single_test(adhoc_list_commands),
|
||||
single_test(adhoc_apiversion),
|
||||
single_test(adhoc_apizero),
|
||||
single_test(adhoc_apione),
|
||||
single_test(adhoc_integer),
|
||||
single_test(adhoc_string),
|
||||
single_test(adhoc_binary),
|
||||
single_test(adhoc_tuple),
|
||||
single_test(adhoc_list),
|
||||
single_test(adhoc_list_tuple),
|
||||
single_test(adhoc_atom),
|
||||
single_test(adhoc_rescode),
|
||||
single_test(adhoc_restuple),
|
||||
%%single_test(adhoc_all),
|
||||
single_test(clean)]}.
|
||||
|
||||
-endif.
|
||||
|
||||
%% @format-begin
|
||||
|
||||
single_test(T) ->
|
||||
list_to_atom("commands_" ++ atom_to_list(T)).
|
||||
|
||||
setup(_Config) ->
|
||||
M = <<"mod_example">>,
|
||||
clean(_Config),
|
||||
|
@ -90,6 +107,9 @@ ejabberdctl(_Config) ->
|
|||
Installed = execute(modules_installed, []),
|
||||
?match(true, lists:keymember(mod_example, 1, Installed)).
|
||||
|
||||
execute(Name, Args) ->
|
||||
ejabberd_commands:execute_command2(Name, Args, #{caller_module => ejabberd_ctl}, 1000000).
|
||||
|
||||
%%%==================================
|
||||
%%%% mod_http_api
|
||||
|
||||
|
@ -130,7 +150,7 @@ http_restuple(Config) ->
|
|||
|
||||
http_list(Config) ->
|
||||
ListS = ["one", "first", "primary"],
|
||||
ListB = [<<"one">>, <<"first">>, <<"primary">>],
|
||||
ListB = lists:sort([<<"one">>, <<"first">>, <<"primary">>]),
|
||||
?match(ListB, query(Config, "command_test_list", #{arg_list => ListS})),
|
||||
?match(ListB, query(Config, "command_test_list", #{arg_list => ListB})).
|
||||
|
||||
|
@ -148,36 +168,24 @@ http_tuple(Config) ->
|
|||
|
||||
http_list_tuple(Config) ->
|
||||
LTA = [#{element1 => "one", element2 => "uno"},
|
||||
#{element1 => "dos", element2 => "two"},
|
||||
#{element1 => "two", element2 => "dos"},
|
||||
#{element1 => "three", element2 => "tres"}],
|
||||
LTB = [#{<<"element1">> => <<"one">>, <<"element2">> => <<"uno">>},
|
||||
#{<<"element1">> => <<"dos">>, <<"element2">> => <<"two">>},
|
||||
#{<<"element1">> => <<"three">>, <<"element2">> => <<"tres">>}],
|
||||
LTB = lists:sort([#{<<"element1">> => <<"one">>, <<"element2">> => <<"uno">>},
|
||||
#{<<"element1">> => <<"two">>, <<"element2">> => <<"dos">>},
|
||||
#{<<"element1">> => <<"three">>, <<"element2">> => <<"tres">>}]),
|
||||
?match(LTB, query(Config, "command_test_list_tuple", #{arg_list => LTA})),
|
||||
?match(LTB, query(Config, "command_test_list_tuple", #{arg_list => LTB})).
|
||||
|
||||
http_list_tuple_map(Config) ->
|
||||
LTA = #{<<"one">> => <<"uno">>,
|
||||
<<"dos">> => <<"two">>,
|
||||
<<"two">> => <<"dos">>,
|
||||
<<"three">> => <<"tres">>},
|
||||
LTB = lists:sort([#{<<"element1">> => <<"one">>, <<"element2">> => <<"uno">>},
|
||||
#{<<"element1">> => <<"dos">>, <<"element2">> => <<"two">>},
|
||||
#{<<"element1">> => <<"two">>, <<"element2">> => <<"dos">>},
|
||||
#{<<"element1">> => <<"three">>, <<"element2">> => <<"tres">>}]),
|
||||
?match(LTB, lists:sort(query(Config, "command_test_list_tuple", #{arg_list => LTA}))).
|
||||
|
||||
%%%==================================
|
||||
%%%% internal functions
|
||||
|
||||
single_test(T) ->
|
||||
list_to_atom("commands_" ++ atom_to_list(T)).
|
||||
|
||||
execute(Name, Args) ->
|
||||
ejabberd_commands:execute_command2(Name, Args, #{caller_module => ejabberd_ctl}, 1000000).
|
||||
|
||||
page(Config, Tail) ->
|
||||
Server = ?config(server_host, Config),
|
||||
Port = ct:get_config(web_port, 5280),
|
||||
"http://" ++ Server ++ ":" ++ integer_to_list(Port) ++ "/api/" ++ Tail.
|
||||
%%% internal functions
|
||||
|
||||
query(Config, Tail, Map) ->
|
||||
BodyQ = misc:json_encode(Map),
|
||||
|
@ -192,6 +200,248 @@ make_query(Config, Tail, BodyQ) ->
|
|||
[{body_format, binary}]),
|
||||
Body).
|
||||
|
||||
page(Config, Tail) ->
|
||||
Server = ?config(server_host, Config),
|
||||
Port = ct:get_config(web_port, 5280),
|
||||
"http://" ++ Server ++ ":" ++ integer_to_list(Port) ++ "/api/" ++ Tail.
|
||||
|
||||
%%%==================================
|
||||
%%%% ad-hoc
|
||||
|
||||
%%% list commands
|
||||
|
||||
adhoc_list_commands(Config) ->
|
||||
{ok, Result} = get_items(Config, <<"api-commands">>),
|
||||
{value, #disco_item{name = <<"command_test_binary">>}} =
|
||||
lists:keysearch(<<"command_test_binary">>, #disco_item.name, Result),
|
||||
suite:disconnect(Config).
|
||||
|
||||
get_items(Config, Node) ->
|
||||
case suite:send_recv(Config,
|
||||
#iq{type = get,
|
||||
to = server_jid(Config),
|
||||
sub_els = [#disco_items{node = Node}]})
|
||||
of
|
||||
#iq{type = result, sub_els = [#disco_items{node = Node, items = Items}]} ->
|
||||
{ok, Items};
|
||||
#iq{type = result, sub_els = []} ->
|
||||
{empty, []};
|
||||
#iq{type = error} = Err ->
|
||||
xmpp:get_error(Err)
|
||||
end.
|
||||
|
||||
%%% apiversion
|
||||
|
||||
adhoc_apiversion(Config) ->
|
||||
Node = <<"api-commands/command_test_apiversion">>,
|
||||
ArgFields = make_fields_args([]),
|
||||
ResFields = make_fields_res([{<<"apiversion">>, <<"2">>}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok, ResFields}, set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% apizero
|
||||
|
||||
adhoc_apizero(Config) ->
|
||||
Node = <<"api-commands/command_test_apizero">>,
|
||||
ArgFields = make_fields_args([]),
|
||||
ResFields = make_fields_res([{<<"apiversion">>, <<"0">>}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok, ResFields}, set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% apione
|
||||
|
||||
adhoc_apione(Config) ->
|
||||
Node = <<"api-commands/command_test_apione">>,
|
||||
ArgFields = make_fields_args([]),
|
||||
ResFields = make_fields_res([{<<"apiversion">>, <<"1">>}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok, ResFields}, set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% integer
|
||||
|
||||
adhoc_integer(Config) ->
|
||||
Node = <<"api-commands/command_test_integer">>,
|
||||
ArgFields = make_fields_args([{<<"arg_integer">>, <<"12345">>}]),
|
||||
ResFields = make_fields_res([{<<"res_integer">>, <<"12345">>}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok, ResFields}, set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% string
|
||||
|
||||
adhoc_string(Config) ->
|
||||
Node = <<"api-commands/command_test_string">>,
|
||||
ArgFields = make_fields_args([{<<"arg_string">>, <<"Some string.">>}]),
|
||||
ResFields = make_fields_res([{<<"res_string">>, <<"Some string.">>}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok, ResFields}, set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% binary
|
||||
|
||||
adhoc_binary(Config) ->
|
||||
Node = <<"api-commands/command_test_binary">>,
|
||||
ArgFields = make_fields_args([{<<"arg_binary">>, <<"Some binary.">>}]),
|
||||
ResFields = make_fields_res([{<<"res_string">>, <<"Some binary.">>}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok, ResFields}, set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% tuple
|
||||
|
||||
adhoc_tuple(Config) ->
|
||||
Node = <<"api-commands/command_test_tuple">>,
|
||||
ArgFields = make_fields_args([{<<"arg_tuple">>, <<"one:two:three">>}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok,
|
||||
[{xdata_field,
|
||||
<<"res_tuple">>,
|
||||
'text-single',
|
||||
<<"res_tuple">>,
|
||||
false,
|
||||
<<" {element1 : element2 : element3}">>,
|
||||
[<<"one : two : three">>],
|
||||
[],
|
||||
[]}]},
|
||||
set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% list
|
||||
|
||||
adhoc_list(Config) ->
|
||||
Node = <<"api-commands/command_test_list">>,
|
||||
ArgFields = make_fields_args([{<<"arg_list">>, [<<"one">>, <<"first">>, <<"primary">>]}]),
|
||||
ResFields =
|
||||
make_fields_res([{<<"res_list">>, lists:sort([<<"one">>, <<"first">>, <<"primary">>])}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok, ResFields}, set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% list_tuple
|
||||
|
||||
adhoc_list_tuple(Config) ->
|
||||
Node = <<"api-commands/command_test_list_tuple">>,
|
||||
ArgFields =
|
||||
make_fields_args([{<<"arg_list">>, [<<"one:uno">>, <<"two:dos">>, <<"three:tres">>]}]),
|
||||
ResFields =
|
||||
make_fields_res([{<<"res_list">>,
|
||||
lists:sort([<<"one : uno">>, <<"two : dos">>, <<"three : tres">>])}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok, ResFields}, set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% atom
|
||||
|
||||
adhoc_atom(Config) ->
|
||||
Node = <<"api-commands/command_test_atom">>,
|
||||
ArgFields = make_fields_args([{<<"arg_string">>, <<"a_test_atom">>}]),
|
||||
ResFields = make_fields_res([{<<"res_atom">>, <<"a_test_atom">>}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok, ResFields}, set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% rescode
|
||||
|
||||
adhoc_rescode(Config) ->
|
||||
Node = <<"api-commands/command_test_rescode">>,
|
||||
ArgFields = make_fields_args([{<<"code">>, <<"ok">>}]),
|
||||
ResFields = make_fields_res([{<<"res_atom">>, <<"0">>}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok, ResFields}, set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% restuple
|
||||
|
||||
adhoc_restuple(Config) ->
|
||||
Node = <<"api-commands/command_test_restuple">>,
|
||||
ArgFields =
|
||||
make_fields_args([{<<"code">>, <<"ok">>}, {<<"text">>, <<"Just a result text">>}]),
|
||||
ResFields = make_fields_res([{<<"res_atom">>, <<"Just a result text">>}]),
|
||||
{ok, Sid, _FormFields} = get_form(Config, Node),
|
||||
?match({ok, ResFields}, set_form(Config, Node, Sid, ArgFields)),
|
||||
suite:disconnect(Config).
|
||||
|
||||
%%% internal functions
|
||||
|
||||
server_jid(Config) ->
|
||||
jid:make(<<>>, ?config(server, Config), <<>>).
|
||||
|
||||
make_fields_args(Fields) ->
|
||||
lists:map(fun ({Var, Values}) when is_list(Values) ->
|
||||
#xdata_field{label = Var,
|
||||
var = Var,
|
||||
required = true,
|
||||
type = 'text-multi',
|
||||
values = Values};
|
||||
({Var, Value}) ->
|
||||
#xdata_field{label = Var,
|
||||
var = Var,
|
||||
required = true,
|
||||
type = 'text-single',
|
||||
values = [Value]}
|
||||
end,
|
||||
Fields).
|
||||
|
||||
make_fields_res(Fields) ->
|
||||
lists:map(fun ({Var, Values}) when is_list(Values) ->
|
||||
#xdata_field{label = Var,
|
||||
var = Var,
|
||||
type = 'text-multi',
|
||||
values = Values};
|
||||
({Var, Value}) ->
|
||||
#xdata_field{label = Var,
|
||||
var = Var,
|
||||
type = 'text-single',
|
||||
values = [Value]}
|
||||
end,
|
||||
Fields).
|
||||
|
||||
get_form(Config, Node) ->
|
||||
case suite:send_recv(Config,
|
||||
#iq{type = set,
|
||||
to = server_jid(Config),
|
||||
sub_els = [#adhoc_command{node = Node}]})
|
||||
of
|
||||
#iq{type = result,
|
||||
sub_els =
|
||||
[#adhoc_command{node = Node,
|
||||
action = execute,
|
||||
status = executing,
|
||||
sid = Sid,
|
||||
actions = #adhoc_actions{execute = complete, complete = true},
|
||||
xdata = #xdata{fields = Fields}}]} ->
|
||||
{ok, Sid, [F || F <- Fields, F#xdata_field.type /= fixed]};
|
||||
#iq{type = error} = Err ->
|
||||
xmpp:get_error(Err)
|
||||
end.
|
||||
|
||||
set_form(Config, Node, Sid, ArgFields) ->
|
||||
Xdata = #xdata{type = submit, fields = ArgFields},
|
||||
case suite:send_recv(Config,
|
||||
#iq{type = set,
|
||||
to = server_jid(Config),
|
||||
sub_els =
|
||||
[#adhoc_command{node = Node,
|
||||
action = complete,
|
||||
sid = Sid,
|
||||
xdata = Xdata}]})
|
||||
of
|
||||
#iq{type = result,
|
||||
sub_els =
|
||||
[#adhoc_command{node = Node,
|
||||
action = execute,
|
||||
status = completed,
|
||||
sid = Sid,
|
||||
xdata = #xdata{fields = ResFields}}]} ->
|
||||
ResFields2 = [F || F <- ResFields, F#xdata_field.type /= fixed],
|
||||
{ok, ResFields2 -- ArgFields};
|
||||
#iq{type = error} = Err ->
|
||||
xmpp:get_error(Err)
|
||||
end.
|
||||
|
||||
%%%==================================
|
||||
|
||||
%%% vim: set foldmethod=marker foldmarker=%%%%,%%%=:
|
||||
|
|
|
@ -111,6 +111,7 @@ max_fsm_queue: 1000
|
|||
queue_type: file
|
||||
modules:
|
||||
mod_adhoc: []
|
||||
mod_adhoc_api: []
|
||||
mod_admin_extra: []
|
||||
mod_admin_update_sql: []
|
||||
mod_announce: []
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue